พาร์ติชันธรรมดาในบท M8 เหมือนกล่องที่ตอกตะปูปิดตาย — อยากเพิ่มที่ทีหลังลำบากมาก บทนี้จะสอน LVM ระบบที่ออกแบบมาให้ “ขยาย/ย่อพื้นที่ได้ตลอด” แม้ตอนเครื่องกำลังทำงานอยู่ และนี่คือหัวใจของข้อสอบ storage
🌱 ต่อจาก M8 — ถ้ายังไม่รู้จัก partition แนะนำให้อ่าน M8 ก่อนในบท M8 เราสร้าง พาร์ติชันธรรมดา ขึ้นมา — มันทำงานได้ดี แต่มีปัญหาใหญ่อยู่อย่างหนึ่ง: ขยายยากมาก สมมุติคุณแบ่งพาร์ติชันไว้ 10 GB แล้ววันหนึ่งข้อมูลเต็ม อยากเพิ่มเป็น 15 GB... พาร์ติชันธรรมดามักจะติดตรงที่ว่าพื้นที่ว่างที่เหลือไม่ได้ “อยู่ติดกัน” กับพาร์ติชันเดิมพอดี ทำให้ขยายไม่ได้ง่ายๆ บางทีต้องลบแล้วสร้างใหม่ ซึ่งเสี่ยงข้อมูลหาย
LVM (Logical Volume Manager) เกิดมาเพื่อแก้ปัญหานี้โดยเฉพาะ มันใส่ “ชั้นกลาง” คั่นระหว่างดิสก์จริงกับพื้นที่ที่เราเอาไปใช้ ทำให้:
โจทย์ storage ของ RHCSA ชอบสั่งให้ “สร้าง logical volume ขนาด X แล้ว mount ที่ Y” และที่ออกบ่อยกว่านั้นคือ “ขยาย logical volume เดิมให้ใหญ่ขึ้น” — ถ้าคุณทำ LVM คล่อง คะแนนส่วน storage แทบจะอยู่ในกระเป๋าแล้ว
LVM ฟังดูซับซ้อน แต่จริงๆ มีแค่ 3 ชั้น ที่ต้องเข้าใจ ขอให้จำลำดับนี้ให้ขึ้นใจ เพราะทุกคำสั่งในบทนี้จะวนอยู่กับ 3 ตัวนี้:
/dev/sdb1)mkfs แล้ว mount ใช้งานจริงนึกภาพระบบน้ำในบ้านแบบนี้:
• PV = ถังน้ำหลายใบ ที่คุณซื้อมา แต่ละใบคือดิสก์/พาร์ติชัน 1 ก้อน
• VG = สระรวม ที่คุณเทน้ำจากทุกถังลงไป — ตอนนี้น้ำทั้งหมดกองรวมเป็นก้อนเดียว ไม่สนแล้วว่ามาจากถังไหน
• LV = แก้วน้ำ ที่คุณตักจากสระมาใช้ดื่ม (เอาไป mkfs + mount)
จุดเด็ดอยู่ตรงนี้: คุณขยายแก้วให้ใหญ่ขึ้นได้เรื่อยๆ ตราบใดที่สระยังมีน้ำเหลือ และถ้าสระเริ่มจะหมด ก็แค่ซื้อถังใบใหม่ (ดิสก์ใหม่) มาเทเติมลงสระ — ง่ายแค่นั้นเอง
LV lvdata (2G) LV lvweb (3G) ← ถังย่อยที่เอาไปใช้จริง (mkfs+mount) ───────────────────────────────── VG vgdata ← สระรวม (พื้นที่กองรวมกัน) ───────────────────────────────── PV /dev/sdb1 PV /dev/sdc1 ← ดิสก์/พาร์ติชันดิบ
อ่านจากล่างขึ้นบน: ดิสก์ดิบ (PV) → เทรวมเป็นสระ (VG) → ตักออกมาเป็นถัง (LV) เวลาทำงานจริงเราก็สร้างเรียงตามลำดับนี้พอดี
สมมุติเรามีดิสก์ลูกใหม่ และทำพาร์ติชัน /dev/sdb1 ไว้แล้ว (จากบท M8) ตอนนี้จะเปลี่ยนมันเป็น LVM ที่ใช้งานได้จริง ทำตามลำดับ PV → VG → LV → mkfs → mount
[root@server1 ~]# pvcreate /dev/sdb1 Physical volume "/dev/sdb1" successfully created.
บอก LVM ว่า “เอาก้อนนี้มาเป็นถังน้ำของเรานะ” — ตอนนี้ /dev/sdb1 พร้อมเข้าสระแล้ว
[root@server1 ~]# vgcreate vgdata /dev/sdb1 Volume group "vgdata" successfully created
vgdataชื่อสระที่เราตั้งเอง (จะเรียกชื่อนี้ตลอดบทนี้)/dev/sdb1PV ที่จะเทลงสระ — ใส่ได้หลายก้อน เว้นวรรคคั่น[root@server1 ~]# lvcreate -L 2G -n lvdata vgdata Logical volume "lvdata" created.
-L 2Gขนาดที่ต้องการ (L ใหญ่ = ระบุเป็น “หน่วยขนาด” เช่น 2G, 500M)-n lvdataชื่อของ LV ที่เราตั้งvgdataตักมาจากสระไหน (ต้องบอกชื่อ VG เสมอ)-L (ใหญ่) = ระบุ “ขนาดจริง” เช่น -L 2G
-l (เล็ก) = ระบุ “เปอร์เซ็นต์หรือจำนวน extent” เช่น -l 50%FREE (เอา 50% ของพื้นที่ว่าง) หรือ -l 100%FREE (เอาที่เหลือทั้งหมด) — มีประโยชน์มากตอนสอบเมื่อโจทย์บอกเป็นเปอร์เซ็นต์
[root@server1 ~]# mkfs.xfs /dev/vgdata/lvdata meta-data=/dev/vgdata/lvdata isize=512 ... ...
สังเกต path ของ LV: /dev/ชื่อVG/ชื่อLV = /dev/vgdata/lvdata — จำรูปแบบนี้ให้ขึ้นใจ (มี path อีกแบบคือ /dev/mapper/vgdata-lvdata ซึ่งหมายถึงอันเดียวกัน)
[root@server1 ~]# mkdir /data [root@server1 ~]# mount /dev/vgdata/lvdata /data [root@server1 ~]# df -h /data Filesystem Size Used Avail Use% Mounted on /dev/mapper/vgdata-lvdata 2.0G 47M 2.0G 3% /data
ตอนนี้ /data ใช้งานได้แล้ว! แต่ mount แบบนี้หายเมื่อ reboot — ต้องใส่ลง /etc/fstab ด้วย (ดูข้อ 9)
แต่ละชั้นมีคำสั่งดูสถานะของตัวเอง จำง่ายๆ ว่า ลงท้ายด้วย s = ดูแบบ สรุปสั้น (ใช้บ่อยสุด) ส่วนลงท้ายด้วย display = ดูแบบ ละเอียดเต็ม
[root@server1 ~]# pvs PV VG Fmt Attr PSize PFree /dev/sdb1 vgdata lvm2 a-- <5.00g <3.00g [root@server1 ~]# vgs VG #PV #LV #SN Attr VSize VFree vgdata 1 1 0 wz--n- <5.00g <3.00g [root@server1 ~]# lvs LV VG Attr LSize lvdata vgdata -wi-ao---- 2.00g
pvsดู PV ทั้งหมด — คอลัมน์ PFree = พื้นที่ว่างในดิสก์ก้อนนั้นvgsดู VG — คอลัมน์ VFree = น้ำที่เหลือในสระ (สำคัญตอนจะขยาย LV!)lvsดู LV — คอลัมน์ LSize = ขนาดถังตอนนี้lsblk แสดงดิสก์ → พาร์ติชัน → LVM ซ้อนกันเป็นชั้นๆ ทำให้เห็นภาพรวมว่าอะไรซ้อนอยู่บนอะไร ลองพิมพ์ดูบ่อยๆ จะเข้าใจโครงสร้างเร็วขึ้นมาก ส่วน pvdisplay / vgdisplay / lvdisplay ใช้เมื่ออยากดูรายละเอียดลึกของแต่ละชั้น
นี่คือหัวใจที่แท้จริงของบทนี้ โจทย์มักจะให้ “ขยาย logical volume เดิมให้ใหญ่ขึ้น” การขยายมี 2 ขั้นตอนที่ต้องทำทั้งคู่ — และมือใหม่มักลืมขั้นที่ 2 จนพื้นที่ไม่เพิ่มจริง
นึกภาพ ถังน้ำที่หุ้มด้วยพลาสติกแร็ป — การ lvextend = ขยาย “ตัวถัง” ให้ใหญ่ขึ้น แต่พลาสติกแร็ปที่หุ้มอยู่ (ตัว filesystem) ยังเท่าเดิม! คุณต้อง “ขยายแร็ปตามไปด้วย” ระบบไฟล์ถึงจะใช้พื้นที่ใหม่ได้จริง
[root@server1 ~]# lvextend -L +1G /dev/vgdata/lvdata Size of logical volume vgdata/lvdata changed from 2.00 GiB to 3.00 GiB. Logical volume vgdata/lvdata successfully resized.
-L +1Gมีเครื่องหมาย + = “เพิ่มอีก 1G จากของเดิม” (เดิม 2G → เป็น 3G)-L 5Gไม่มี + = “ตั้งขนาดใหม่ให้เป็น 5G” (ระบุปลายทางตรงๆ)-l +100%FREEดูดน้ำที่เหลือในสระทั้งหมดมาใส่ถังนี้ขั้นนี้ คำสั่งต่างกันตามชนิด filesystem ดูให้ดี:
[root@server1 ~]# xfs_growfs /data data blocks changed from 524288 to 786432
XFS ขยายโดยอ้าง จุด mount (/data) ไม่ใช่ path ของ device — และ XFS ขยายได้อย่างเดียว ย่อไม่ได้
[root@server1 ~]# resize2fs /dev/vgdata/lvdata Resizing the filesystem on /dev/vgdata/lvdata to 786432 (4k) blocks.
ext4 ขยายโดยอ้าง path ของ device ไม่ใช่จุด mount — สลับกับ XFS พอดี ระวังสับสน
option -r (resize filesystem) จะทำ ทั้งสองขั้นในคำสั่งเดียว — LVM ดูเองว่าเป็น XFS หรือ ext4 แล้วเรียกคำสั่งขยาย filesystem ที่ถูกต้องให้อัตโนมัติ:
[root@server1 ~]# lvextend -r -L +1G /dev/vgdata/lvdata
ในห้องสอบ ใช้ -r ทุกครั้งจะปลอดภัยที่สุด เพราะลืมขั้นที่ 2 ไม่ได้เลย — คำสั่งเดียวจบ
หลังขยายเสร็จ พิมพ์ df -h /data ดูว่าตัวเลข Size โตขึ้นจริง ถ้า lvs บอกว่า LV ใหญ่ขึ้นแล้วแต่ df ยังเท่าเดิม = คุณลืมขยาย filesystem (ขั้นที่ 2)
ถ้าจะขยาย LV แต่ vgs บอกว่า VFree เหลือ 0 (น้ำในสระหมด) คุณต้อง เติมดิสก์ใหม่ลงสระก่อน ทำ 2 ขั้น: สร้าง PV ใหม่ แล้วเทเข้า VG เดิม
[root@server1 ~]# pvcreate /dev/sdc1 Physical volume "/dev/sdc1" successfully created. [root@server1 ~]# vgextend vgdata /dev/sdc1 Volume group "vgdata" successfully extended [root@server1 ~]# vgs VG #PV #LV #SN Attr VSize VFree vgdata 2 1 0 wz--n- <10.00g 7.00g
pvcreateขึ้นทะเบียนดิสก์ก้อนใหม่ (เหมือนข้อ 3 ขั้น 1)vgextendเทถังใหม่ลงสระเดิม — สังเกต VFree เพิ่มขึ้น และ #PV เป็น 2พอสระมีน้ำแล้ว ก็กลับไปทำ lvextend -r (ข้อ 5) ขยายถังได้ตามปกติ
เวลาดู vgdisplay จะเจอคำว่า PE ย่อมาจาก Physical Extent = หน่วยก้อนเล็กที่สุดที่ LVM ใช้แบ่งพื้นที่ ค่ามาตรฐานคือ 4 MB ต่อ 1 extent
PE เหมือน “อิฐก้อนมาตรฐาน” — น้ำในสระจริงๆ ถูกหั่นเป็นอิฐก้อนละ 4 MB เวลาตักไปทำถัง (LV) ก็คือเอาอิฐมาเรียงต่อกัน ตอนสอบไม่ต้องคำนวณ PE เอง แค่รู้ว่ามันคือหน่วยย่อยของ LVM ก็พอ (นั่นคือเหตุผลที่ -l ระบุเป็น “จำนวน extent” ได้)
คุณเอา LV ไปทำเป็น swap (พื้นที่ช่วยจำเมื่อ RAM เต็ม) ได้ด้วย ขั้นตอนคล้ายเดิม แค่เปลี่ยนจาก mkfs เป็น mkswap
[root@server1 ~]# lvcreate -L 1G -n lvswap vgdata [root@server1 ~]# mkswap /dev/vgdata/lvswap [root@server1 ~]# swapon /dev/vgdata/lvswap [root@server1 ~]# swapon --show NAME TYPE SIZE USED PRIO /dev/dm-1 partition 1024M 0B -2
mkswapฟอร์แมต LV ให้เป็นรูปแบบ swapswaponเปิดใช้งาน swap ก้อนนี้ทันทีเพื่อให้ swap เปิดเองหลัง reboot ต้องเพิ่มบรรทัดใน /etc/fstab โดยใช้คอลัมน์ที่ 2 เป็น swap และคอลัมน์ที่ 3 เป็น swap เช่นกัน:
/dev/vgdata/lvswap none swap defaults 0 0
คำสั่ง mount ที่เราพิมพ์มือ หายหมดเมื่อ reboot — เหมือนบท M8 เป๊ะ LV ที่สร้างต้องถูกบันทึกลง /etc/fstab ด้วย ไม่งั้นพอเครื่องรีสตาร์ตในห้องสอบ งานคุณจะหายและได้ 0 คะแนน
# ใช้ path ของ LV (อ่านง่าย แนะนำสำหรับ LVM) /dev/vgdata/lvdata /data xfs defaults 0 0 # หรือจะใช้ UUID ก็ได้ (หาด้วย: blkid /dev/vgdata/lvdata) UUID=abc123... /data xfs defaults 0 0
สำหรับ LVM การใช้ path /dev/vgdata/lvdata ใน fstab ทำได้และอ่านง่าย (ต่างจากพาร์ติชันธรรมดาที่แนะนำ UUID) เพราะชื่อ VG/LV ไม่เปลี่ยนเหมือนชื่อ /dev/sdb
หลังแก้ /etc/fstab ให้ umount /data แล้วพิมพ์ mount -a (mount ทุกอย่างใน fstab) ถ้า ไม่มี error = บรรทัดของคุณถูกต้อง พิมพ์ df -h /data ยืนยันอีกที
ถ้าพิมพ์ผิดใน fstab แล้วไม่ทดสอบ เครื่องอาจ บูตไม่ขึ้น ทำ mount -a เพื่อจับ error ตั้งแต่ตอนนี้เสมอ — นี่คือนิสัยที่ช่วยชีวิตในห้องสอบ
lvextend ทำให้ lvs โตขึ้นจริง แต่ df -h ยังเท่าเดิม เพราะ filesystem ไม่ได้ขยายตาม — แก้โดยใช้ lvextend -r หรืออย่าลืม xfs_growfs/resize2fsxfs_growfs ใช้กับ XFS เท่านั้น ส่วน resize2fs ใช้กับ ext4 — ใช้ผิดชนิดจะ error เช็คชนิด filesystem ด้วย df -hT ก่อนถ้าไม่แน่ใจ-L +1G = เพิ่มอีก 1G แต่ -L 1G (ไม่มี +) = ตั้งขนาดให้เป็น 1G ซึ่งอาจ เล็กลงกว่าเดิม! ระวังให้ดี/dev/ชื่อVG/ชื่อLV หรือ /dev/mapper/VG-LV — อย่าเดาเอง ดูจาก lvs หรือ lsblk/data) ไม่ใช่ device ส่วน resize2fs อ้าง device — จำสลับกันบ่อยmount -a ทดสอบ| คำสั่ง | ทำอะไร |
|---|---|
pvcreate /dev/sdb1 | ขึ้นทะเบียนดิสก์/พาร์ติชันเป็น PV |
vgcreate vgdata /dev/sdb1 | สร้าง VG (สระ) จาก PV |
vgextend vgdata /dev/sdc1 | เติม PV ใหม่ลง VG เดิม (สระน้ำเพิ่ม) |
lvcreate -L 2G -n lvdata vgdata | สร้าง LV ขนาด 2G ชื่อ lvdata |
lvcreate -l 50%FREE -n lvx vgdata | สร้าง LV เอา 50% ของพื้นที่ว่าง |
mkfs.xfs /dev/vgdata/lvdata | ฟอร์แมต LV เป็น XFS |
mount /dev/vgdata/lvdata /data | เอา LV ไป mount (ชั่วคราว) |
pvs / vgs / lvs | ดูสถานะแต่ละชั้นแบบสรุป |
lsblk | ดูภาพรวมดิสก์ → พาร์ติชัน → LVM |
lvextend -r -L +1G /dev/vgdata/lvdata | ขยาย LV + filesystem ในคำสั่งเดียว |
xfs_growfs /data | ขยาย filesystem XFS (อ้างจุด mount) |
resize2fs /dev/vgdata/lvdata | ขยาย filesystem ext4 (อ้าง device) |
mkswap + swapon | ทำ LV เป็น swap แล้วเปิดใช้ |
mount -a | ทดสอบ /etc/fstab (ทำก่อน reboot เสมอ) |
สร้าง LVM จากศูนย์ได้ครบลำดับ (pvcreate → vgcreate → lvcreate → mkfs → mount) → ขยาย LV พร้อม filesystem ได้ด้วย lvextend -r → เติมดิสก์เข้า VG เมื่อสระเต็ม → และใส่ทุกอย่างลง /etc/fstab แล้วทดสอบด้วย mount -a ก่อน reboot ครบนี้ = พิชิตส่วน storage ของข้อสอบได้สบาย!