พื้นฐาน

LVM ใน Linux: physical volume, volume group และ logical volume ในทางปฏิบัติ

อัปเดต: · Skillaria.Top

LVM (Logical Volume Manager) บน Linux คือชั้นที่อยู่ระหว่างดิสก์และระบบไฟล์ ดิสก์ถูกแปลงเป็น physical volume (PV) รวมเป็น volume group (VG) และตัด logical volume (LV) ขนาดใดก็ได้ออกจากกลุ่มนั้น ข้อได้เปรียบหลักคือขยายโวลุ่มได้ทันทีด้วย lvextend -r เพิ่มดิสก์เข้ากลุ่มได้โดยไม่หยุดบริการ และสร้างสแนปชอตก่อนการเปลี่ยนแปลงที่มีความเสี่ยง

LVM (Logical Volume Manager) คือตัวจัดการโวลุ่มตรรกะบน Linux ที่แยกระบบไฟล์ออกจากดิสก์ทางกายภาพ แทนที่จะผูก /var ไว้กับพาร์ติชัน /dev/sdb1 ตายตัว คุณนำดิสก์มารวมในพูลกลาง แล้วตัดโวลุ่มขนาดที่ต้องการออกจากพูลนั้น เมื่อพื้นที่ไม่พอ โวลุ่มขยายได้ด้วยคำสั่งเดียว โดยไม่ต้องรีบูตและไม่ต้องหยุดบริการ ด้านล่างจะอธิบายว่า LVM บน Linux ทำงานอย่างไร วิธีสร้างโวลุ่มตั้งแต่ต้น วิธีขยาย วิธีสร้างสแนปชอต และวิธีหลีกเลี่ยงข้อผิดพลาดที่พบบ่อย

ทำไมต้องใช้ LVM ในเมื่อมีพาร์ติชันธรรมดาอยู่แล้ว

พาร์ติชันธรรมดาคือช่วงต่อเนื่องของดิสก์เพียงลูกเดียว ขนาดถูกกำหนดตอนแบ่งพาร์ติชัน และจะขยายได้ก็ต่อเมื่อมีพื้นที่ว่างต่อจากมันทันที เมื่อดิสก์เต็ม ต้องซื้อดิสก์ใหม่ ย้ายข้อมูล และแก้ /etc/fstab ในขณะที่บริการต้องหยุดทำงานไปด้วย

LVM แก้ปัญหาสามอย่าง:

  • ขนาดยืดหยุ่น. โวลุ่มตรรกะขยายได้ (และสำหรับ ext4 ลดได้) ได้ทุกเมื่อ
  • รวมดิสก์. ดิสก์ทางกายภาพหลายลูกกลายเป็นพูลเดียว และโวลุ่มหนึ่งอาจอยู่บนสองดิสก์ได้พร้อมกัน
  • สแนปชอต. ภาพถ่ายโวลุ่ม ณ ขณะหนึ่งก่อนการอัปเดต การย้ายฐานข้อมูล หรือการดำเนินการที่มีความเสี่ยง

ด้วยเหตุนี้ตัวติดตั้งของ Ubuntu Server, RHEL, Rocky และ AlmaLinux จึงเสนอ LVM เป็นค่าเริ่มต้น และบนเซิร์ฟเวอร์ที่เก็บข้อมูลแทบทุกเครื่องก็ใช้ LVM

สามระดับของ LVM: PV, VG และ LV

ตรรกะทั้งหมดของ LVM สรุปได้เป็นสามแนวคิด ตัวอย่างเปรียบเทียบที่เข้าใจง่าย: ดิสก์คือถุงแป้ง กลุ่มคือคลังกลาง และโวลุ่มตรรกะคือแป้งที่ตักออกจากคลังตามปริมาณที่ต้องการ

ระดับคืออะไรตัวอย่างชื่อสร้างด้วยคำสั่ง
PV (Physical Volume)ดิสก์หรือพาร์ติชันที่ถูกเตรียมสำหรับ LVM/dev/sdb, /dev/sdc1pvcreate
VG (Volume Group)พูลที่รวม PV หนึ่งตัวหรือมากกว่าdata_vgvgcreate
LV (Logical Volume)โวลุ่มที่ตัดออกจาก VG ใช้สร้างระบบไฟล์บนนั้น/dev/data_vg/applvcreate

ภายใน VG พื้นที่ถูกแบ่งเป็นเอกซ์เทนต์ (PE, physical extents) ซึ่งเป็นบล็อกขนาดคงที่ ค่าเริ่มต้นคือ 4 MiB โวลุ่มตรรกะเป็นเพียงชุดของเอกซ์เทนต์ที่ไม่จำเป็นต้องเรียงติดกัน และอาจอยู่บนดิสก์ต่างลูกกัน นี่คือเหตุผลที่ขยายโวลุ่มได้ง่าย LVM เพียงแค่เพิ่มเอกซ์เทนต์ว่างให้โวลุ่มจากที่ใดก็ได้

โวลุ่มตรรกะเข้าถึงได้ด้วยพาธสองแบบที่เทียบเท่ากัน: /dev/data_vg/app และ /dev/mapper/data_vg-app เบื้องหลังเป็นอุปกรณ์ device-mapper ของเคอร์เนล

ตรวจสอบสิ่งที่มีอยู่

ตรวจก่อนว่าติดตั้งแพ็กเกจแล้ว: บน Debian และ Ubuntu คือ lvm2 (sudo apt install lvm2) ส่วนในตระกูล RHEL ติดตั้งมาพร้อมระบบ มีคำสั่งแบบสั้นและแบบละเอียดสำหรับดูภาพรวม:

$ sudo pvs
  PV         VG      Fmt  Attr PSize   PFree
  /dev/sdb   data_vg lvm2 a--  <20.00g      0
  /dev/sdc   data_vg lvm2 a--  <20.00g  <10.00g

$ sudo vgs
  VG      #PV #LV #SN Attr   VSize  VFree
  data_vg   2   1   0 wz--n- 39.99g <10.00g

$ sudo lvs
  LV   VG      Attr       LSize  Pool Origin Data%  Meta%
  app  data_vg -wi-ao---- 30.00g

รายละเอียดเพิ่มเติมแสดงด้วย pvdisplay, vgdisplay และ lvdisplay ภาพรวมพร้อมพาร์ติชันธรรมดาดูได้ด้วย lsblk โวลุ่มตรรกะจะปรากฏเป็นชนิด lvm

$ lsblk /dev/sdb /dev/sdc
NAME             MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sdb                8:16   0  20G  0 disk
└─data_vg-app    253:0    0  30G  0 lvm  /srv/app
sdc                8:32   0  20G  0 disk
└─data_vg-app    253:0    0  30G  0 lvm  /srv/app

ที่นี่โวลุ่ม app ขนาด 30 GB วางอยู่บนดิสก์สองลูกขนาด 20 GB ทั้งคู่ ซึ่งทำไม่ได้กับพาร์ติชันธรรมดา

LVM ตั้งแต่ต้น: จากดิสก์เปล่าถึงโวลุ่มที่เมานต์แล้ว

สมมติว่าเพิ่มดิสก์เปล่า /dev/sdb เข้าเซิร์ฟเวอร์ และต้องการโวลุ่มขนาด 15 GB สำหรับข้อมูลของแอปพลิเคชัน ตรวจชื่อดิสก์ด้วย lsblk สองครั้ง เพราะทุกคำสั่งด้านล่างจะลบข้อมูลบนอุปกรณ์ที่ระบุ

ขั้นที่ 1. สร้างฟิสิคัลโวลุ่ม

$ sudo pvcreate /dev/sdb
  Physical volume "/dev/sdb" successfully created.

สามารถมอบดิสก์ทั้งลูกให้ LVM ได้ หรือสร้างพาร์ติชันก่อนด้วย fdisk หรือ parted โดยตั้งประเภทเป็น "Linux LVM" แล้วระบุพาร์ติชันนั้น (/dev/sdb1) พาร์ติชันทำให้ผู้ดูแลคนอื่นเข้าใจได้ชัดเจนขึ้น และป้องกันการแบ่งพาร์ติชันทับ LVM โดยไม่ตั้งใจ ส่วนการขยายดิสก์ทั้งลูกในคลาวด์ทำได้ง่ายกว่า

ขั้นที่ 2. สร้างกลุ่มโวลุ่ม

$ sudo vgcreate data_vg /dev/sdb
  Volume group "data_vg" successfully created

ขั้นที่ 3. ตัดโวลุ่มตรรกะ

$ sudo lvcreate -n app -L 15G data_vg
  Logical volume "app" created.

แฟล็ก -L กำหนดขนาดแบบสัมบูรณ์ ส่วน -l กำหนดเป็นจำนวนเอกซ์เทนต์หรือเปอร์เซ็นต์: -l 100%FREE ใช้พื้นที่ว่างทั้งหมดของกลุ่ม และ -l 50%VG ใช้ครึ่งหนึ่งของกลุ่ม การเก็บพื้นที่ว่างไว้ใน VG เป็นแนวปฏิบัติที่ดี เพราะสามารถมอบให้โวลุ่มใดก็ได้ภายหลัง หรือใช้เป็นพื้นที่ของสแนปชอต

ขั้นที่ 4. ระบบไฟล์และการเมานต์

$ sudo mkfs.ext4 /dev/data_vg/app
$ sudo mkdir -p /srv/app
$ sudo mount /dev/data_vg/app /srv/app
$ df -h /srv/app
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/data_vg-app   15G   24K   14G   1% /srv/app

หากต้องการให้โวลุ่มเมานต์หลังรีบูต เพิ่มบรรทัดลงใน /etc/fstab สำหรับโวลุ่มตรรกะพาธ /dev/mapper/... คงที่ จึงใช้พาธนั้นได้ หรือจะใช้ UUID จาก blkid ก็ได้:

/dev/mapper/data_vg-app  /srv/app  ext4  defaults  0 2

ตรวจรายการด้วย sudo mount -a ก่อนรีบูต เพราะข้อผิดพลาดใน fstab อาจทำให้เซิร์ฟเวอร์เข้าสู่โหมดฉุกเฉิน

ขยาย LVM โวลุ่มโดยไม่หยุดบริการ

นี่คือเหตุผลหลักที่ควรใช้ LVM โวลุ่มขยายได้ขณะที่ระบบไฟล์เมานต์อยู่ และแอปพลิเคชันยังเขียนข้อมูลต่อได้ วิธีการขึ้นอยู่กับว่ากลุ่มยังมีพื้นที่ว่างหรือไม่

หากใน VG ยังมีพื้นที่ว่าง

$ sudo vgs data_vg
  VG      #PV #LV #SN Attr   VSize   VFree
  data_vg   1   1   0 wz--n- <20.00g <5.00g

$ sudo lvextend -r -L +4G /dev/data_vg/app
  Size of logical volume data_vg/app changed from 15.00 GiB to 19.00 GiB.
  Logical volume data_vg/app successfully resized.
resize2fs 1.47.0
Filesystem at /dev/mapper/data_vg-app is mounted on /srv/app; on-line resizing required

แฟล็กสำคัญคือ -r (--resizefs) ซึ่งขยายระบบไฟล์ทันทีหลังขยายโวลุ่ม หากไม่ใส่ โวลุ่มจะใหญ่ขึ้น แต่ df -h ยังแสดงขนาดเดิม เพราะระบบไฟล์ไม่รู้ว่ามีพื้นที่เพิ่ม นี่คือข้อผิดพลาดที่พบบ่อยที่สุด หากเกิดขึ้น ให้รัน resize2fs สำหรับ ext4 หรือ xfs_growfs สำหรับ XFS ด้วยตนเอง

$ sudo resize2fs /dev/data_vg/app      # ext4 ระบุอุปกรณ์
$ sudo xfs_growfs /srv/app             # XFS ระบุจุดเมานต์

ข้อสังเกต: -L +4G เพิ่มขึ้น 4 GB ส่วน -L 4G ตั้งขนาดรวมเป็น 4 GB หากต้องการให้โวลุ่มใช้พื้นที่ที่เหลือทั้งหมด ใช้ -l +100%FREE

หากพื้นที่ใน VG หมดแล้ว: เพิ่มดิสก์

เชื่อมต่อดิสก์ใหม่ (ในคลาวด์คือแนบโวลุ่มเพิ่ม) ค้นหาด้วย lsblk แล้วเพิ่มเข้ากลุ่ม:

$ sudo pvcreate /dev/sdc
$ sudo vgextend data_vg /dev/sdc
  Volume group "data_vg" successfully extended
$ sudo lvextend -r -l +100%FREE /dev/data_vg/app

สามคำสั่ง ไม่มีเวลาหยุดทำงาน ระบบไฟล์อยู่บนดิสก์สองลูกแล้ว และแอปพลิเคชันไม่รู้สึกถึงการเปลี่ยนแปลงนี้

หากขยายดิสก์ในคลาวด์

ในคลาวด์มักง่ายกว่าที่จะไม่เพิ่มดิสก์ แต่ขยายดิสก์ที่มีอยู่แล้ว เมื่อนั้นเคอร์เนลจะเห็นขนาดใหม่ของอุปกรณ์ และต้องขยายฟิสิคัลโวลุ่มด้วย pvresize:

$ sudo pvresize /dev/sdb
  Physical volume "/dev/sdb" changed
$ sudo lvextend -r -l +100%FREE /dev/data_vg/app

หาก PV สร้างบนพาร์ติชัน (/dev/sdb1) ให้ขยายพาร์ติชันก่อน เช่น ด้วย growpart /dev/sdb 1 จากแพ็กเกจ cloud-guest-utils แล้วจึงรัน pvresize /dev/sdb1

ลด LVM โวลุ่มได้หรือไม่

ทำได้ แต่ไม่ใช่กับระบบไฟล์ทุกชนิด และไม่สามารถทำขณะที่ระบบทำงานได้ XFS ลดขนาดไม่ได้เลย ต้องสร้างใหม่และย้ายข้อมูล ส่วน ext4 ลดได้ แต่ต้องเลิกเมานต์ก่อน:

$ sudo umount /srv/app
$ sudo lvreduce -r -L 10G /dev/data_vg/app

เมื่อใช้แฟล็ก -r LVM จะตรวจระบบไฟล์ (e2fsck) และย่อระบบไฟล์ก่อนลดโวลุ่ม หากไม่ใส่ -r คุณอาจตัดโวลุ่มให้เล็กกว่าระบบไฟล์ และทำให้ข้อมูลเสียหาย ก่อนลดขนาดต้องสำรองข้อมูลเสมอ

สแนปชอต LVM: ภาพถ่ายโวลุ่มก่อนการเปลี่ยนแปลงที่มีความเสี่ยง

สแนปชอตคือภาพถ่ายของโวลุ่มตรรกะ ณ ขณะหนึ่ง สร้างเสร็จในเวลาเพียงเสี้ยววินาทีและไม่คัดลอกข้อมูลทั้งหมด LVM ทำงานด้วยหลัก copy-on-write คือเก็บลงสแนปชอตเฉพาะบล็อกที่เปลี่ยนบนโวลุ่มต้นฉบับหลังจากสร้างสแนปชอต ดังนั้นสแนปชอตต้องการพื้นที่ใน VG เพียงเท่าจำนวนการเปลี่ยนแปลง ไม่ใช่ขนาดเต็มของโวลุ่ม

$ sudo lvcreate -s -n app_before_upgrade -L 2G /dev/data_vg/app
  Logical volume "app_before_upgrade" created.

$ sudo lvs data_vg
  LV                 VG      Attr       LSize  Origin Data%
  app                data_vg owi-aos--- 19.00g
  app_before_upgrade data_vg swi-a-s---  2.00g app    0.01

คอลัมน์ Data% แสดงว่าพื้นที่เก็บการเปลี่ยนแปลงของสแนปชอตเต็มไปแล้วเท่าไร หากเต็ม 100% สแนปชอตแบบคลาสสิกจะใช้ไม่ได้ และทำได้เพียงลบทิ้ง เลือกขนาดให้เผื่อปริมาณการเปลี่ยนแปลงที่คาดไว้ และติดตามสแนปชอตที่มีอายุนานด้วย lvs หรือขยายด้วย lvextend

วิธีย้อนกลับไปยังสแนปชอต

หากการอัปเดตผิดพลาด ให้คืนโวลุ่มสู่สถานะตอนที่สร้างสแนปชอต:

$ sudo umount /srv/app
$ sudo lvconvert --merge /dev/data_vg/app_before_upgrade
  Merging of volume data_vg/app_before_upgrade started.
$ sudo mount /srv/app

หลังการรวม (merge) สแนปชอตจะหายไป หากเลิกเมานต์โวลุ่มไม่ได้ (เช่น รูตของระบบ) การรวมจะรอจนกว่าโวลุ่มจะถูกเปิดใช้อีกครั้ง คือหลังรีบูต

หากทุกอย่างเรียบร้อยดี

ลบสแนปชอตทิ้งเพื่อไม่ให้ทำให้การเขียนช้าลงและไม่กินพื้นที่:

$ sudo lvremove /dev/data_vg/app_before_upgrade

สแนปชอตมีประโยชน์เมื่อเมานต์แบบอ่านอย่างเดียวเพื่อสำรองข้อมูลระบบที่กำลังทำงาน ด้วย mount -o ro และคัดลอกด้วย rsync หรือ tar สำหรับ XFS ให้เพิ่มตัวเลือก nouuid ไม่เช่นนั้นการเมานต์จะถูกปฏิเสธเพราะ UUID ซ้ำกับต้นฉบับ

LVM และ RAID: อย่าสับสนหน้าที่

LVM ไม่ได้ป้องกันความเสียหายของดิสก์ หากโวลุ่มกระจายอยู่บนดิสก์สองลูกและลูกหนึ่งเสีย โวลุ่มทั้งหมดจะเสียไป ไม่ใช่แค่ครึ่งหนึ่ง เพื่อความทนทานต่อความเสียหาย ให้วาง RAID (mdadm) ไว้ใต้ LVM หรือใช้โหมดมิเรอร์ที่มาพร้อมกับ LVM (lvcreate --type raid1 -m 1)

ทั้ง RAID และสแนปชอตไม่ได้มาแทนการสำรองข้อมูล สแนปชอตอยู่บนดิสก์เดียวกับต้นฉบับ ส่วน RAID จะทำมิเรอร์คำสั่ง rm -rf ที่พลาดไปด้วย จึงต้องมีสำเนาแยกไว้บนสื่ออื่น

ตารางคำสั่ง LVM

งานคำสั่ง
ภาพรวม PV, VG, LVpvs, vgs, lvs
สร้างฟิสิคัลโวลุ่มpvcreate /dev/sdb
สร้างกลุ่มvgcreate data_vg /dev/sdb
เพิ่มดิสก์เข้ากลุ่มvgextend data_vg /dev/sdc
สร้างโวลุ่มlvcreate -n app -L 15G data_vg
ขยายโวลุ่มและระบบไฟล์lvextend -r -L +5G /dev/data_vg/app
ขยาย PV หลังเพิ่มขนาดดิสก์pvresize /dev/sdb
สแนปชอตlvcreate -s -n snap -L 2G /dev/data_vg/app
ย้อนกลับไปยังสแนปชอตlvconvert --merge /dev/data_vg/snap
ถอดดิสก์ออกจากกลุ่มpvmove /dev/sdb แล้ว vgreduce data_vg /dev/sdb
ลบโวลุ่มlvremove /dev/data_vg/app

ข้อผิดพลาดที่พบบ่อย

  • ขยายโวลุ่มแล้ว แต่ df ยังแสดงขนาดเดิม. ลืมใส่ -r ให้รัน resize2fs หรือ xfs_growfs
  • Insufficient free space. ไม่มีเอกซ์เทนต์ว่างในกลุ่ม ตรวจด้วย vgs แล้วเพิ่มดิสก์ด้วย vgextend หรือขยาย PV
  • Device /dev/sdc excluded by a filter. ดิสก์ยังมีการแบ่งพาร์ติชันหรือลายเซ็นระบบไฟล์เก่าอยู่ หากแน่ใจว่าไม่ต้องการข้อมูลบนนั้น ล้างด้วย wipefs -a /dev/sdc
  • สแนปชอตกลายเป็น Invalid. พื้นที่เก็บการเปลี่ยนแปลงเต็ม 100% กู้คืนไม่ได้ ทำได้เพียงลบทิ้ง และครั้งหน้าควรจัดสรรพื้นที่ให้มากขึ้น

สรุป

LVM บน Linux มีสามชั้น: ฟิสิคัลโวลุ่ม (PV) รวมเป็นกลุ่ม (VG) และตัดออกเป็นโวลุ่มตรรกะ (LV) ซึ่งให้สิ่งที่พาร์ติชันธรรมดาไม่มี ได้แก่ การขยายโวลุ่มขณะทำงานด้วย lvextend -r การเพิ่มดิสก์โดยไม่หยุดบริการ และสแนปชอตก่อนการเปลี่ยนแปลงที่มีความเสี่ยง จำไว้ว่า LVM ไม่ได้มาแทน RAID หรือการสำรองข้อมูล การแบ่งดิสก์ LVM RAID และโควตาถูกฝึกใช้จริงในบทเรียนหลักสูตร Linux

คำถามที่พบบ่อย

จะย้ายพาร์ติชันที่มีข้อมูลและทำงานอยู่ไปเป็น LVM ได้หรือไม่?

ทำโดยตรงไม่ได้ เพราะ pvcreate จะเขียนทับส่วนต้นของอุปกรณ์ ต้องสร้าง LVM บนดิสก์อีกลูก คัดลอกข้อมูลด้วย rsync แก้ fstab แล้วจึงค่อยคืนพาร์ติชันเก่า

LVM ทำให้ดิสก์ช้าลงหรือไม่?

หากไม่มีสแนปชอต ค่าใช้จ่ายของ device-mapper แทบไม่รู้สึก แต่สแนปชอตแบบคลาสสิกที่ทำงานอยู่จะทำให้การเขียนลงโวลุ่มต้นฉบับช้าลงเพราะ copy-on-write จึงไม่ควรเก็บไว้เป็นสัปดาห์

บนคอมพิวเตอร์ที่บ้านหรือแล็ปท็อปจำเป็นต้องใช้ LVM หรือไม่?

ไม่จำเป็น แต่มีประโยชน์เมื่อเข้ารหัสดิสก์ (LUKS โดยมี LVM อยู่ข้างใน) หรือเมื่อต้องการเปลี่ยนขนาดพาร์ติชันโดยไม่ต้องแบ่งใหม่ บนเซิร์ฟเวอร์ที่เก็บข้อมูล LVM เป็นมาตรฐานแทบทั้งหมด

thin provisioning ใน LVM คืออะไร?

คือโวลุ่มบาง สร้างพูลด้วย lvcreate --type thin-pool และโวลุ่มในพูลนั้นจะใช้พื้นที่จริงเท่าที่เขียนข้อมูลไปแล้ว จึงจัดสรรโวลุ่มได้มากกว่าพื้นที่ทางกายภาพที่มี แต่ต้องคอยดูว่าพูลเต็มหรือยัง

จะถอดดิสก์ออกจากกลุ่มโวลุ่มโดยไม่สูญเสียข้อมูลได้อย่างไร?

ย้ายเอกซ์เทนต์ออกไปยังดิสก์อื่นในกลุ่มด้วย pvmove /dev/sdb (ต้องมีพื้นที่ว่างพอ) แล้วรัน vgreduce data_vg /dev/sdb และ pvremove /dev/sdb

เรียนหัวข้อนี้ผ่านวิดีโอ

หัวข้อนี้สอนอย่างละเอียดพร้อมฝึกปฏิบัติในคอร์ส “Linux: с нуля до уверенного администрирования”

ไปที่คอร์ส