แสดงบทความที่มีป้ายกำกับ btrfs แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ btrfs แสดงบทความทั้งหมด

วันศุกร์ที่ 26 สิงหาคม พ.ศ. 2554

btrfs: ทำ profile แบบ RAID ในระดับ filesystem

คุณสมบัติหนึ่งของ btrfs คือ มันสามารถใช้ดิสก์หลายๆ ตัวมารวมเป็นพื้นที่เดียวกันได้ โดยไม่จำเป็นต้องพึ่ง RAID หรือ LVM ซึ่งสามารถกำหนด metadata profile และ data profie ได้ว่าให้มีคุณสมบัติคล้าย RAID แบบใด ซึ่งปัจจุบันสามารถกำหนดให้เป็น raid0, raid1, raid10

ตอนสร้าง filesystem แบบ btrfs มันจะใช้ metadate profile เป็น raid1 และ data profile เป็น raid0 ถ้าสร้างบนดิสก์ตัวเดียว metadata จะเก็บบนดิสก์ตัวเดียวกัน 2 สำเนา

# mkfs.btrfs /dev/sda1
เทียบเท่า
# mkfs.btrfs -m raid1 -d raid0 /dev/sda1

สร้างจากดิสก์ 2 ตัว
# mkfs.btrfs /dev/sda1 /dev/sdb1
เวลาเมานท์ก็ระบุตัวใดตัวหนึ่งก็ได้เช่น
# mount /dev/sda1 /mnt/data

อันที่จริงแล้วมันไม่ได้เป็น RAID จริงๆ คือไม่ได้เป็นลักษณะของ disk array แต่เป็นการกำหนดว่าหน่วยข้อมูลที่จัดเก็บใน filesystem บนดิสก์หลายๆ ตัว ให้มีลักษณะของการเก็บอย่างไร ได้แก่

raid0
เก็บหน่วยข้อมูลในลักษณะ stripping คือกระจายหน่วยข้อมูลที่ต่อเนื่องกัน ให้ไปอยู่บนดิสก์หลายๆ ตัว ทำให้การอ่านและเขียนเร็วขึ้นมากตามจำนวนดิสก์ที่มี

ต้องใช้ดิสก์อย่างน้อย 1 ตัว อันนี้จะต่างจาก RAID ปกติ ที่จะต้องใช้ดิสก์ 2 ตัวขึ้นไป คือถ้ามีดิสก์เพียง 1 ตัว มันก็จะเก็บข้อมูลตามปกตินั่นเอง
ถ้าในตอนแรกมีดิสก์ 2 ตัว เมื่อสั่ง delete ดิสก์ออก 1 ตัว มันจะคัดลอกข้อมูลจากตัวที่จะเอาออก มาที่ตัวที่เหลือ แล้วจึงเอาออก ซึ่งในการทำแบบนี้ สามารถทำในขณะที่ filesystem กำลังทำงานอยู่ได้ทันที ในการเพิ่ม ก็สามารถเพิ่มดิสก์เข้ามาได้ทันที โดยสามารถสั่ง balance เพื่อกระจายหน่วยข้อมูลออกไปเก็บบนดิสก์ทุกตัวอีกที
ความปลอดภัยของข้อมูล
แบบ raid0 นี้ข้อมูลแต่ละหน่วยมีเพียงชุดเดียว ไม่มีสำเนา หากมีดิสก์ตัวใดตัวหนึ่งเสีย ข้อมูลที่อยู่ในดิสก์ตัวนั้นจะเสียไปเลย

raid1
เก็บข้อมูลหน่วยละ 2 ชุด และอยู่คนละดิสก์กันเสมอ หรือเรียกอีกอย่างหนึ่งว่า mirroring ต้องใช้ดิสก์ 2 ตัวขึ้นไปเสมอ ดังนั้นถ้าตอนแรกสร้างบนดิสก์ 2 ตัว จะสั่ง delete ตัวใดตัวหนึ่งออกไม่ได้เลย แต่ถ้าดิสก์เกิดเสีย ยังสามารถเมานท์แบบ degrade ได้เพราะข้อมูลมีครบทั้งสองตัว

ตัวอย่าง
# mkfs.btrfs -d raid1 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
# mount /dev/sda1 /mnt/data

raid10
เก็บข้อมูลหน่วยละ 2 ชุดคนละดิสก์กัน และเรียงข้อมูลแบบ stripping ด้วย ทำให้ได้ทั้งความปลอดภัย และความเร็วในการอ่านและบันทึกข้อมูล แบบนี้ใช้ดิสก์ 4 ตัวขึ้นไปเสมอ ถ้ามีเพียง 4 ตัวจะ delete ตัวใดตัวหนึ่งออกไม่ได้

ตัวอย่าง
# mkfs.btrfs -m raid10 -d raid10 /dev/sd[a-d]1
# mount /dev/sda1 /mnt/data

สามารถเพิ่มดิสก์เข้าไปใน pool ของมันได้เรื่อยๆ เช่นเพิ่มดิสก์ตัวที่ 5 เข้ามา ก็สร้าง partition แล้วเพิ่มเข้ามาได้เลย
# btrfs device add /dev/sde1 /mnt/data
# btrfs filesystem balance /mnt/data
สังเกตว่าไม่ต้อง mkfs.btrfs แล้ว แค่เพิ่มเข้าไปเลย และหลังจากเพิ่ม สามารถสั่ง balance เพื่อกระจายข้อมูลไปยังดิสก์ตัวใหม่ด้วย

การถอดดิสก์ออกจาก pool ใช้คำสั่งตามตัวอย่างนี้
# btrfs device delete /dev/sde1 /mnt/data

การเมานท์เมื่อมีดิสก์บางตัวเสียหาย หรือถูกถอดออกไปโดยไม่ได้สั่ง delete
# mount -o degraded /dev/sda1 /mnt/data
ซึ่งก็ควรจัดหาดิสก์มาทดแทนให้เร็วที่สุดแล้วสั่ง
# btrfs device add /dev/sde1 /mnt/data
# btrfs device delete missing /mnt/data

ข้อสังเกตจากการทดลองใช้งานจริงมาระยะหนึ่ง

  1. data profile raid1 เวลาสร้างบนดิสก์ที่มากกว่า 2 ตัว มันชอบเอาข้อมูลไปกองอยู่บนดิสก์แค่ 2 ตัว ไม่ค่อยกระจายเท่าไหร่ ทำให้ดิสก์บางตัวทำงานหนัก ขณะที่บางตัวไม่ค่อยถูกใช้งาน เมื่อสั่ง balance ยิ่งทำให้ข้อมูลถูกย้ายมาเก็บแค่ 2 ตัว
  2. data profile raid10 เวลาถอดดิสก์ออกจากเครื่อง แล้วสั่งเมานท์ จะเมานท์ไม่ได้ แม้ว่าจะระบุอ็อพชัน -o degraded แล้วก็ตาม ส่วนแบบ raid1 ยังไม่ได้ลอง
  3. กำหนด layout ของการเก็บข้อมูลไม่ได้ จึงไม่สามารถระบุให้เก็บข้อมูลเป็น 3 ชุด แทนที่จะเป็น 2 ชุดได้ ซึ่งทำให้เสี่ยงที่จะเกิดปัญหาถ้ามีดิสก์เสีย 2 ตัวพร้อมๆ กัน
  4. ยังไม่รองรับ profile แบบ raid5, raid6
  5. ยังเปลี่ยน profile ไม่ได้ ถ้าสร้างแบบไหน ก็ต้องใช้แบบนั้นตลอดไป
  6. แต่ละ subvolume ไม่สามารถกำหนด profile แตกต่างกันได้
  7. การ balance ทำได้ช้ามาก
  8. สามารถสั่ง defragment ได้ แต่ก็ช้ามากเช่นกัน
  9. ยังไม่สามารถสั่งตรวจสอบ filesystem แบบ online คือกำลังเมานท์อยู่ได้ และการตรวจสอบแบบ offline ก็ยังไม่สมบูรณ์
โดยรวมๆ ยังมีหลายๆ อย่างไม่สมบูรณ์ แต่โดยส่วนตัวคิดว่า เมื่อสมบูรณ์กว่านี้ เราคงไม่จำเป็นต้องใช้ RAID อีกต่อไป

วันพุธที่ 24 สิงหาคม พ.ศ. 2554

btrfs: การสร้าง snapshot ของข้อมูล ด้วยวิธี cp --reflink

ในครั้งก่อนเราได้ดูวิธีการทำ snapshot ของ subvolume ใน btrfs ไปแล้ว ซึ่งวิธีนั้นเหมาะกับผู้ที่เป็น admin เพราะมีสิทธิของ root ที่จะทำได้

ถ้าเราเป็นผู้ใช้ทั่วๆ ไป แต่มีพื้นที่เก็บข้อมูลบน filesystem แบบ btrfs เราสามารถทำสิ่งที่คล้ายๆ กับการทำ snapshot ได้เช่นกัน แต่จะใช้พื้นที่เยอะกว่าเล็กน้อย และช้ากว่าหน่อยนึงด้วย

วิธีการคือการใช้คำสั่ง cp (copy) โดยใช้อ็อพชั่น --reflink=always กับ -a ซึ่ง -a หรือ --archive คือการคัดลอกทั้ง subdirectory และไม่แปลง soft-link กลับเป็นไฟล์ และรักษาคุณสมบัติของไฟล์ทุกประการไว้
ส่วน --reflink ใช้กับการคัดลอกแบบ CoW คือไฟล์ที่ได้จะอยู่บนคนละ inode แต่ใน inode ชี้ไปหารายการบล็อคชุดเดียวกันกับต้นฉบับ เว้นแต่เมื่อบล็อคใดมีการแก้ไข จะถูกสำเนาไปเป็นบล็อคใหม่ทันที

เช่น ใน home ของผู้ใช้มีข้อมูลสำคัญเก็บใน Documents ต้องการสำเนาทั้งหมดเก็บไว้แบบ snapshot

$ mkdir backups
$ cp -a --reflink=always Documents backups/Documents-20110825

การคัดลอกจะใช้เวลาไม่นานนัก เพราะมีการอัพเดทเฉพาะส่วน metadata โดยส่วนข้อมูลยังชี้ไปที่เดิม พื้นที่ของดิสก์จะลดลงเล็กน้อย

สามารถสำเนาแบบนี้ได้อีกหลายๆ ครั้งตามต้องการ เช่น ในวันต่อมาก็สั่ง
$ cp -a --reflink=always Documents backups/Documents-20110826

เมื่อต้องการลบ snapshot เหล่านี้ออกบ้าง ก็ใช้คำสั่ง rm -rf ออกได้ เช่น

$ rm -rf backups/Documents-20110825

ซึ่งจะได้คืนเนื้อที่ที่เกิดจากความแตกต่างระหว่าง snapshot กับข้อมูลปัจจุบัน

วันจันทร์ที่ 22 สิงหาคม พ.ศ. 2554

btrfs: การสร้าง snapshot ของข้อมูล

btrfs เป็น filesystem ของ Linux (น่าจะรองรับในทุก distro ในปัจจุบัน) ที่มีคุณสมบัติอย่างหนึ่งคือ CoW (Copy on Write) คือสามารถคัดลอกไฟล์เป็น 2 ชุดโดยอ้างอิงบล็อกของข้อมูลชุดเดียวกันได้ แต่เมื่อไฟล์ใดมีการแก้ไข จึงจะคัดลอกบล็อกที่แก้ไขเป็นอีกบล็อกหนึ่งแล้วจึงแก้ไขมัน ทำให้เวลาคัดลอกลักษณะนี้ มันใช้เนื้อที่น้อยมาก และจะใช้เนื้อที่เพิ่มขึ้นทีละนิดเมื่อไฟล์มีการเปลี่ยนแปลง และสามารถคัดลอกสำเนาในลักษณะนี้ได้หลายๆ ครั้ง (หลายๆ เวอร์ชัน) โดยที่เนื้อที่ที่ใช้เพิ่มขึ้นเฉพาะส่วนที่เปลี่ยนแปลงของแต่ละเวอร์ชันเท่านั้น

คุณสมบัตินี้ถูกใช้ในการทำ snapshot ของ filesystem ในระดับของ subvolume ด้วยคำสั่ง

 btrfs subvolume snapshot <source> [<dest>/]<name>

โดย <source> ต้องเป็น path ของ subvolume ที่ถูกเมานท์ ส่วน <dest> ต้องเป็น path ที่อยู่ใน subvolume ที่อยู่ใน btrfs pool เดียวกัน

เช่น
ในระบบมี subvolume ชื่อ @ เมานท์ไว้ที่ / (เป็น root directory)
และ @home เมานท์ไว้ที่ /home

# mkdir /backups
# btrfs subvolume snapshot /home /backups/home-20110822
Create a snapshot of '/home' in '/backups/home-20110822'


ใน /backups/home-20110822 จะมีข้อมูลเก็บอยู่เหมือนใน ้/home ในขณะเวลานั้นๆ ทันที โดยใช้เนื้อที่เพิ่มขึ้นเพียงเล็กน้อย และใช้เวลาในการทำ snapshot สั้นมากๆ แม้ว่าข้อมูลจะมีเป็นจำนวนมากก็ตาม ซึ่งผู้ดูแลระบบอาจจะแจ้งให้ผู้ใช้ทราบว่า สามารถมาเรียกคืนข้อมูลเก่าๆ ย้อนหลังจาก snapshot ที่เก็บไว้ที่ /backups ก็ได้

snapshot ที่สร้างขึ้น สามารถแก้ไขได้ โดยไม่กระทบกับข้อมูลปัจจุบัน ซึ่งในทางปฏิบัติเราไม่ควรมาแก้ตรงนี้

การลบ snapshot
เนื่องจากเนื้อของดิสก์จะถูกใช้เพิ่มขึ้น เมื่อข้อมูลปัจจุบันต่างจาก snapshot แต่ละรุ่น ดังนั้นการจะเรียกคืนเนื้อที่ส่วนนี้กลับมา ต้องลบ snapshot เก่าๆ ทิ้งไปบ้าง (อาจจะกำหนดเป็นนโยบายว่า จะเก็บย้อนหลังเพียง 7 วัน แล้วเขียน cron script เพื่อจัดการอัตโนมัติ เป็นต้น)

คำสั่ง
 btrfs subvolume delete <subvolume>

เช่น
# btrfs subvolume delete /backups/home-20110822
Delete subvolume '/backups/home-20110822'

ข้อควรระวังคือ ถ้าทำ snapshot ใน filesystem ที่มีไฟล์ถูกเปิดใช้งานอยู่ เช่น mysql server สำเนา snapshot ที่ได้จะไม่สมบูรณ์เพราะไฟล์ที่เปิดอยู่มักจะมีข้อมูลบางส่วนค้างอยู่ในหน่วยความจำ ยังไม่ได้ถูกบันทึกในไฟล์จริง ดังนั้นก่อนจะทำ snapshot ควรปิดระบบที่อาจจะเปิดไฟล์ค้างอยู่ก่อน (ในที่นี้คือให้ปิดโปรแกรม mysql server ก่อน) แล้วจึงสั่งทำ snapshot

ถ้าระบบของเราใช้ btrfs ที่มี data profile และ metadata profile เป็นแบบ RAID1 หรือสร้างบนระบบ RAID1, RAID10, RAID5/6 ไม่ว่าจะเป็นซอฟต์แวร์หรือฮาร์ดแวร์แล้วละก็ อาจจะกล่าวได้ว่า
"ลาก่อน โปรแกรม backup ทั้งหลาย"