2 คะแนน โดย GN⁺ 2023-09-06 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • คู่มือเริ่มต้นที่สรุปตั้งแต่การ แก้ปัญหา, การจัดวางวอลุ่มใหม่ ไปจนถึงกลยุทธ์การสำรองข้อมูล โดยอ้างอิงจากกรณี ZFS ขัดข้องบน FreeNAS และอธิบายโครงสร้างกับคำสั่งที่จำเป็นสำหรับการใช้งาน ZFS ครั้งแรกอย่างต่อเนื่องในลำดับเดียว
  • ZFS มอบทั้ง filesystem และ logical volume manager ในตัว และหลังจากเริ่มต้นที่ Sun Microsystems แล้ว ปัจจุบันบน Linux และ FreeBSD เป็นต้น มักใช้โค้ดของ OpenZFS
  • โครงสร้างพื้นฐานแบ่งเป็น vdev ที่รวมดิสก์กายภาพเข้าด้วยกัน, pool ที่รวม vdev เหล่านั้น, dataset ที่ทำหน้าที่เป็น filesystem และ volume ที่อยู่ในรูปแบบ block device โดย RAIDZ-1/2/3 สามารถทนต่อดิสก์เสียได้ 1, 2, และ 3 ลูกตามลำดับ
  • คำสั่งที่ใช้จริงในการทำงานมีศูนย์กลางอยู่ที่ zpool create/status/list/import/export/destroy/scrub และ zfs create/mount/list/get/set/snapshot/diff/rollback/send/recv/destroy และเพื่อหลีกเลี่ยงปัญหาจากการเปลี่ยนชื่ออุปกรณ์ จึงนิยมใช้ device UUID
  • snapshot ใช้ปกป้องสถานะของข้อมูล ณ ช่วงเวลาหนึ่งได้อย่างเบา ๆ และสามารถทำสำเนาไปยัง pool หรือระบบอื่นด้วย zfs send/recv ได้ แต่ snapshot เพียงอย่างเดียวยังทดแทน backup หรือ DR ได้ยาก

แนวคิดพื้นฐานของ ZFS

  • ZFS เป็นทั้ง local filesystem แบบเดียวกับ ext4, NTFS, exFAT และทำหน้าที่เป็น logical volume manager แบบเดียวกับ LVM บน Linux ไปพร้อมกัน
  • ถูกสร้างโดย Sun Microsystems และซอร์สโค้ดของ ZFS เคยเผยแพร่ภายใต้ไลเซนส์โอเพนซอร์สจนกระทั่ง Oracle เข้าซื้อ Sun
  • เนื่องจากโค้ดที่เปิดเผยไว้ถูกพอร์ตไปยังหลายระบบปฏิบัติการอยู่แล้ว จึงเกิดโครงการ OpenZFS ขึ้นภายหลัง และระบบตระกูล Unix ส่วนใหญ่ เช่น Linux และ FreeBSD ก็ใช้โค้ดชุดนี้
  • เนื้อหานี้เรียบเรียงจากมุมมองของผู้เริ่มต้น เพื่อช่วยให้ผู้ที่เพิ่งรู้จัก ZFS เข้าใจโครงสร้างและคำสั่งสำหรับการดูแลระบบ

องค์ประกอบของ ZFS

  • vdev ประกอบด้วย physical drive ตั้งแต่หนึ่งลูกขึ้นไป และอาจรวมไฟล์แทนฮาร์ดไดรฟ์ได้ด้วย
    • สามารถจัดเป็นแบบ mirror หรือ RAIDZ ได้
    • มี vdev อยู่ 7 ประเภท รวมถึงประเภทสำคัญอย่าง hot spare, L2ARC และ ZIL
  • pool ประกอบด้วย vdev ตั้งแต่หนึ่งชุดขึ้นไป และโดยทั่วไปจะสร้าง volume หรือ dataset ภายใน pool
    • ตอนสร้าง pool ด้วยคำสั่ง zpool จะต้องกำหนด vdev ไปพร้อมกัน
    • สามารถผสม vdev หลายประเภทเพื่อจัดระดับ RAIDZ ได้
  • dataset คือองค์ประกอบของ ZFS ที่เทียบได้กับ filesystem
    • สามารถตั้งค่าการเข้าถึงของผู้ใช้, quota, การบีบอัด, snapshot และอื่น ๆ ได้
  • volume คล้ายกับ dataset แต่ให้การแสดงผลในรูปแบบ block device
    • รองรับเพียงบางความสามารถของ dataset
    • มีประโยชน์เมื่อจะรัน filesystem อื่นบน ZFS หรือ export iSCSI extent

ประเภทของ RAIDZ

  • Dynamic/Simple Stripe หรือ RAID0 กระจายข้อมูลโดยไม่มี parity และถ้าเสียอุปกรณ์ไปหนึ่งตัวจะสูญเสียข้อมูลทั้งหมด
  • MIRROR หรือ RAID1 ทำการมิเรอร์ดิสก์ และมักใช้กับดิสก์ 2~4 ลูกหรือมากกว่านั้น
  • RAIDZ-1 หรือ RAID5 กระจาย parity ไปพร้อมกับข้อมูล และสามารถทนต่อการสูญเสีย physical drive ได้ 1 ลูกก่อนที่ RAID จะพัง
    • RAIDZ ต้องใช้ดิสก์อย่างน้อย 3 ลูก
  • RAIDZ-2 หรือ RAID6 สามารถทนต่อการสูญเสีย physical drive ได้สูงสุด 2 ลูก
    • RAIDZ-2 ต้องใช้ดิสก์อย่างน้อย 4 ลูก
  • RAIDZ-3 สามารถทนต่อการสูญเสีย physical drive ได้สูงสุด 3 ลูก
    • แม้จะต้องใช้ดิสก์อย่างน้อย 4 ลูก แต่โดยทั่วไปไม่แนะนำให้ใช้น้อยกว่า 5 ลูก

การสร้าง pool และตรวจสอบสถานะ

  • ZFS pool สร้างด้วยรูปแบบ zpool create [pool] [devices]
    • ตัวอย่าง pool แบบดิสก์เดี่ยว: zpool create tank /dev/sdb
    • ตัวอย่าง stripe 3 ดิสก์: zpool create tank /dev/sdb /dev/sdc /dev/sdd
    • ตัวอย่าง mirror 2 ดิสก์: zpool create tank mirror sdb sdc
    • ตัวอย่าง RAIDZ pool: zpool create tank raidz sdb sdc sdd
    • RAIDZ2/3 สามารถสร้างได้ด้วยรูปแบบ zpool create [pool name] raidz[1,2,3] [devices]
  • ตอนสร้าง pool สามารถระบุ mount point เริ่มต้น ได้ด้วยแฟล็ก -m
    • ตัวอย่าง: zpool create tank -m /mnt/tank mirror sdb sdc
  • ในตัวอย่างจะใช้ชื่ออุปกรณ์แบบ /dev/sdx แต่เพื่อหลีกเลี่ยงปัญหาการบูตจากการเปลี่ยนชื่ออุปกรณ์ จึงนิยมใช้ device UUID
  • zpool status เป็นคำสั่งพื้นฐานสำหรับตรวจสอบสถานะของ pool
    • state แสดงว่า pool อยู่ในสถานะออนไลน์หรือไม่
    • status แสดงข้อมูลเพิ่มเติมเกี่ยวกับ pool
    • action แสดงงานถัดไปที่จำเป็น
    • scan แสดงความคืบหน้าของ scrub หรือสถานะ scrub ล่าสุด
    • errors แสดงว่ามีปัญหากับ pool หรือไม่
  • zpool list แสดงรายละเอียดอย่างขนาดของ pool, allocation, พื้นที่ว่าง, fragmentation, capacity, dedup และ health
  • zpool history แสดงประวัติคำสั่งที่ใช้เปลี่ยนแปลงการตั้งค่าตั้งแต่สร้าง pool

การ import, export, ลบ pool และ scrub

  • หลังสร้างแล้ว pool มักจะถูก import และ mount โดยอัตโนมัติ แต่ในงานแก้ปัญหาหรือหลัง reimage ระบบ อาจต้อง import ด้วยตนเอง
  • หากรัน zpool import โดยไม่ระบุชื่อ pool จะเห็นรายการ pool ที่สามารถ import ได้
    • ถ้าไม่มี pool ที่ import ได้ จะขึ้น no pools available to import
    • ถ้าระบุชื่อ pool จะ import pool นั้น และคำสั่ง import จะทำการ mount pool ด้วย
    • zpool import -a จะนำเข้า pool ที่ import ได้ทั้งหมด
  • หากใช้ -R เช่น zpool import -R /mnt/tank2 tank จะ mount ไว้ที่ alternate root
    • ตำแหน่งนี้ไม่ใช่ mount path ของ pool เอง แต่เป็นโฟลเดอร์ root ทางเลือก
  • zpool export [pool name] เป็นคำสั่งตรงข้ามกับ import โดยจะพยายาม unmount filesystem ที่ mount อยู่ใน pool ก่อนแล้วจึง export
    • ถ้า unmount filesystem ไม่สำเร็จ สามารถบังคับ unmount ด้วย -f
    • หากมี ZFS volume ที่กำลังใช้งานอยู่ ต่อให้ใช้ -f ก็จะ export ไม่สำเร็จ
  • zpool destroy จะลบ pool พร้อม dataset หรือ volume ลูกทั้งหมด
    • เนื่องจากจะลบทั้งข้อมูลและ snapshot ทั้งหมดด้วย จึงต้องใช้ความระมัดระวัง
  • ZFS scrub จะตรวจสอบความถูกต้องของข้อมูลโดยเทียบทุก block ใน pool กับ checksum ที่รู้จัก
    • ใน vdev ที่มี parity จะใช้ข้อมูลจากดิสก์ปกติเพื่อกู้คืนข้อมูลที่เสียหาย
    • เพื่อคงสภาพระบบให้ดี ควรรัน scrub ตามตารางเวลา
    • เริ่ม: zpool scrub [pool]
    • ตรวจสอบสถานะ: ดูส่วน scan ของ zpool status
    • หยุด: zpool scrub -s [pool]

การสร้าง dataset และ mount

  • zfs create เป็นคำสั่งสำหรับสร้าง filesystem หรือ volume ใหม่ และในที่นี้จะเน้นที่ dataset มากกว่า volume
  • zfs create tank/dataset1 จะสร้าง dataset1 ภายใต้ tank
    • dataset tank จะถูกสร้างให้อัตโนมัติตอน zpool create
  • zfs create -p ทำงานเหมือน mkdir -p โดยจะสร้าง dataset แม่ที่ยังไม่มีไปพร้อมกัน
    • ถ้า dataset แม่ไม่มีอยู่ zfs create แบบปกติจะล้มเหลว
  • หากรัน zfs mount โดยไม่ใส่อาร์กิวเมนต์ จะเห็น ZFS filesystem ที่ mount อยู่ในปัจจุบันพร้อม mount point
    • เอาต์พุตนี้จะไม่รวม child dataset
  • zfs mount [pool|dataset] จะ mount filesystem ที่ระบุ
    • zfs mount -a จะ mount filesystem ทั้งหมด
  • child dataset สามารถ mount ได้แม้ไม่มี parent dataset
    • ในกรณีนั้น ระบบปฏิบัติการจะสร้าง path ที่จำเป็นใน filesystem ให้
    • ภายหลังถ้าจะ mount parent dataset อาจเกิดข้อผิดพลาด directory is not empty เพราะมีไดเรกทอรีที่ถูกสร้างไว้แล้ว
  • zfs unmount [dataset] จะ unmount dataset ที่ระบุ

การดู dataset และตั้งค่า property

  • zfs list [dataset name] จะแสดงข้อมูลของ dataset ที่ระบุ
    • สามารถส่ง mount point แทนชื่อ dataset เป็นอาร์กิวเมนต์ได้เช่นกัน
  • หากรัน zfs list โดยไม่ระบุชื่อ dataset จะแสดง dataset ทั้งหมดในระบบแบบ recursive
  • เมื่อระบุชื่อ dataset สามารถใช้แฟล็ก -r เพื่อแสดงข้อมูลภายใต้ dataset นั้นแบบ recursive ได้
  • ZFS property ใช้ควบคุมพฤติกรรมของ filesystem, volume, snapshot และ clone
    • อาจดูคล้าย mount option
  • zfs get all [dataset] จะแสดง property ทั้งหมดของ dataset
  • สามารถตรวจค่า property เฉพาะได้ เช่น zfs get compression tank
  • การตั้งค่า property ใช้ zfs set
    • ตัวอย่าง: zfs set compression=lz4 tank
    • หลังตั้งค่าแล้วสามารถตรวจสอบได้ด้วย zfs get compression tank ว่าค่า compression เปลี่ยนเป็น lz4

การทำงานและการใช้งานของ snapshot

  • snapshot จะเก็บสถานะของ filesystem ณ ช่วงเวลาหนึ่ง แต่ไม่ได้คัดลอกไฟล์
  • snapshot จะทำเครื่องหมายข้อมูลเดิมเป็นแบบ read-only และแม้ภายหลังจะมีข้อมูลใหม่ถูกเพิ่มเข้า filesystem ก็จะไม่กระทบ data block เดิมที่ snapshot ปกป้องไว้
  • ลำดับตัวอย่างมีดังนี้
    • สร้าง snapshot 1 จาก filesystem ที่มีข้อมูลเดิม Data A
    • จากนั้นเพิ่ม Data B แล้วสร้าง snapshot 2
    • จากนั้นเพิ่ม Data C
    • snapshot 1 จะปกป้อง Data A
    • snapshot 2 จะปกป้อง Data A และ Data B
    • แม้ลบ snapshot 1 ไป Data A ก็ยังถูกปกป้องต่อโดย snapshot 2
  • ปริมาณข้อมูลที่ snapshot ใช้มีน้อยมาก
    • เพราะไม่ได้คัดลอกไฟล์ แต่เพียงบันทึก top-level metadata block ของ filesystem ว่าเป็นส่วนหนึ่งของ snapshot
  • snapshot มีประโยชน์สำหรับการทดสอบพัฒนาซอฟต์แวร์หรือสร้าง failsafe ก่อนอัปเกรด
  • ไม่ควรมองว่า snapshot เพียงอย่างเดียวเป็นโซลูชัน backup หรือ DR

คำสั่ง snapshot

  • การสร้าง snapshot ใช้รูปแบบ zfs snapshot [pool/dataset@snapshot_name]
    • ตัวอย่าง: zfs snapshot tank/dataset1@snapshot1
  • ดูรายการ snapshot ได้ด้วย zfs list -t snapshot
  • ถ้ามี child dataset หลายตัว สามารถสร้าง snapshot ที่ top-level dataset หรือใช้แฟล็ก -r เพื่อสร้าง snapshot แบบ recursive ได้
    • ตัวอย่าง snapshot ปกติ: zfs snapshot tank@snapshot-master
    • ตัวอย่าง snapshot แบบ recursive: zfs snapshot -r tank@recursive
  • zfs diff [older snapshot] [newer snapshot] ใช้เปรียบเทียบความต่างระหว่าง snapshot
    • สามารถดูไฟล์ที่ถูกเพิ่มและ path ที่ถูกแก้ไขได้จากเอาต์พุต
  • การกู้คืน snapshot ทำได้ด้วย zfs rollback [pool/dataset@snapshot_name]
    • เมื่อ rollback แล้ว ไฟล์ที่สร้างหลัง snapshot จะถูกลบ
    • snapshot ที่ใหม่กว่าก็จะถูกลบด้วย และในกรณีนี้อาจถูกขอให้ใช้ตัวเลือก -r

ZFS send/recv และการทำ replication

  • ZFS send เป็นความสามารถในการส่ง snapshot ออกไปเป็น data stream
  • สามารถทำ replication ของ snapshot และ dataset ไปยังไฟล์, pool อื่น หรือระบบอื่นผ่าน SSH ได้
  • ตัวอย่างนี้ใช้ pool สองชุดคือ tank และ backup
    • dataset tank/Movies มีข้อมูลขนาด 1.50G
    • ก่อนส่ง จะสร้าง snapshot ด้วย zfs snapshot tank/Movies@$(date '+%Y-%m-%d_%H-%M')
    • จากนั้นส่ง snapshot ไปยัง backup pool ด้วย zfs send tank/Movies@2020-11-03_15-29 | zfs recv backup/Movies
  • หลังส่งเสร็จ จะเห็นทั้ง backup/Movies และ tank/Movies ใน zfs list และตรวจพบ snapshot ทั้งสองฝั่งใน zfs list -t snapshot
  • zfs send เป็นฟีเจอร์ที่ควรศึกษาเพิ่มเติมทั้งในแง่ตัวเลือกและกรณีใช้งาน และเมื่อใช้ร่วมกับ RAIDZ และ snapshot ก็ช่วยให้ filesystem แข็งแกร่งขึ้นได้

การลบ dataset และ snapshot

  • การลบ dataset ใช้รูปแบบ zfs destroy [pool/dataset]
    • สามารถใช้แฟล็ก -r ได้เช่นกัน
  • การลบ snapshot ก็ใช้ zfs destroy [pool/dataset@snapshot_name]
    • การลบ snapshot ก็สามารถใช้แฟล็ก -r ได้เช่นกัน
  • ZFS ยังมีความสามารถอีกมาก แต่เนื้อหานี้ใกล้เคียงกับจุดเริ่มต้นสำหรับทำความเข้าใจแนวคิดพื้นฐานและคำสั่งหลัก

แหล่งอ้างอิง

1 ความคิดเห็น

 
GN⁺ 2023-09-06
ความคิดเห็นจาก Hacker News
  • เพิ่งเริ่มใช้ ZFS ได้ไม่นาน แต่เส้นโค้งการเรียนรู้ชันกว่าที่คิด อยากให้มี wrapper ที่ใช้ง่ายซึ่งทำให้ use case ทั่วไปเรียบง่ายมาก ๆ
    ตัวอย่างเช่น การสร้าง pool ก็ควรใช้ค่า default ที่สมเหตุสมผลไปเลย เช่น ashift=12, การบีบอัด lz4, xattr=sa, acltype=posixacl, atime=off และสำหรับ encryption ก็อยากให้มีแค่เปิด/ปิด แทนที่จะมีตัวเลือกหลายอย่าง
    อยากให้ช่วยสร้าง encryption key ให้ ตั้งค่า service ของ systemd ที่ถอดรหัส pool ตอนบูต และแนะนำการสำรอง key ด้วย zfs list ควรแสดงว่า dataset ถูก mount อยู่หรือไม่, ถูกเข้ารหัสหรือไม่, และ key ถูกโหลดอยู่หรือไม่
    อยากให้เลิกใช้ recursive dataset และแยก pool กับ dataset ให้ชัดเจนด้วย {pool}:{dataset} แทน {pool}/{dataset} ส่วนชื่อ pool หรือ snapshot ก็ไม่ต้องให้ตั้งเอง แต่ให้ตั้งกฎอย่าง {hostname}-[A-Z], {pool name}_{datetime created} และชื่อย่อแบบตัวเลขให้อัตโนมัติ
    ตอนสร้าง pool ไม่ควรต้องป้อน disk ID เอง และแม้จะสร้างด้วย /dev/sda, /dev/sdb แล้วสลับลำดับ drive ภายหลังก็ไม่ควรสับสน โดยควรบันทึก metadata ไว้ใน disk
    ความคืบหน้าควรแสดงด้วย pv เสมอ และควรตั้งค่า scrub รายสัปดาห์ รวมถึง snapshot รายชั่วโมง/รายวัน/รายสัปดาห์/รายเดือนและการ cleanup ให้อัตโนมัติ
    ถ้าส่งข้อมูลไปยัง disk ที่ไม่มี pool ควรถามยืนยันก่อน แล้วสร้าง pool แบบ disk เดียวที่มีการตั้งค่าเหมือน pool ต้นทางให้ และอยากให้รวม zpool กับ zfs เป็นคำสั่งเดียว
    เวลา send dataset ที่เข้ารหัสควรใช้ --raw ให้อัตโนมัติ ค่า default ของการส่งควรเป็น --replicate และถ้าเป็นไปได้ก็ควรใช้ -I นอกจากนี้ ไม่ควรซ่อน filesystem ของ snapshot ไว้ในไดเรกทอรีลับ และควรมีวิธี mount และ browse snapshot dataset ได้ง่าย ๆ
    • เป็นส่วนผสมระหว่างข้อเสนอที่สมเหตุสมผลกับรสนิยมที่แรงมาก ค่า default ashift=12 หรือ syntax {pool}:{dataset} พอเข้าใจได้ แต่ดูเหมือนจะเปลี่ยนตอนนี้ยากไปแล้ว และบางข้อเสนออาจทำให้ use case ที่เราไม่รู้จักพังได้
      วิธีตั้งชื่อ pool ด้วย hostname ไม่เหมาะกับ SAN pool ที่อาจถูกนำเข้าได้จากหลาย host
      ผมมองว่า scrub รายสัปดาห์, snapshot ตามรอบเวลา, และ cleanup ตามรอบเวลา เป็นงานที่ควรให้ scheduler ของระบบปฏิบัติการจัดการ การรวม zpool กับ zfs ก็อาจทำได้ แต่สุดท้ายคงกลายเป็นประมาณ zfs -pool XXXX, zfs -volume XXXX ซึ่งไม่รู้ว่าจำเป็นตรงไหน
      recursive dataset มีกรณีที่มีประโยชน์จริง ๆ อยู่ ในทางกลับกัน ผมเห็นด้วยเต็มที่ว่า zfs list ควรแสดงว่า mount อยู่หรือไม่, เข้ารหัสหรือไม่, และโหลด key อยู่หรือไม่
      ส่วนที่บอกว่าไม่ต้องป้อน disk ID นั้นกำกวม จะระบุด้วย ID, WWN, label, sdX หรือวิธีอื่น ๆ ก็ได้ แต่ไม่ว่าอย่างไรก็ต้องบอกอยู่ดีว่าจะใช้ disk ไหน
      ฟีเจอร์ที่บันทึก metadata ลง disk เพื่อให้ยังหาเจอแม้สลับลำดับนั้นมีอยู่แล้ว ต่อให้ถอดเสียบ drive สลับไปสองสามตัวแล้ว import pool ก็ยังหาเจอ
      ข้อเสนอบางอย่างเหมาะเป็นค่า default ได้ แต่บางข้อดูเหมือนไม่ได้พิจารณา use pattern และความต้องการนอกเหนือจากของตัวเองมากพอ ZFS รองรับผู้ใช้ที่กว้างกว่านั้นมาก
    • การสร้าง pool ด้วย /dev/sda, /dev/sdb แล้วบอกว่า ZFS สับสนนั้น พูดตรง ๆ แล้วใกล้เคียงกับปัญหาของผู้ใช้ที่ใช้งานไม่ถูกยุค มากกว่าจะเป็น ปัญหาของ ZFS
      บน Linux มี reference แบบสมบูรณ์อย่าง /dev/disk/by-id/ata-$manufactuer-$serial-$whatever มาค่อนข้างนานแล้ว เวลา create pool ควรใช้ path พวกนี้
    • หลายข้อเสนอขึ้นกับรสนิยมอย่างมาก ซึ่งไม่ใช่เรื่องแย่ในตัวมันเอง แต่ดูเหมือนตั้งใจไปเขย่าขนบเดิมโดยไม่จำเป็น เช่น ไม่เข้าใจว่าทำไมต้องเป็น {pool}:{dataset}
      ถ้าไม่อยากตั้งชื่อ snapshot เอง เครื่องมือเล็ก ๆ ที่ผมทำไว้ https://github.com/rollcat/zfs-autosnap อาจเหมาะ
      ใส่ zfs-autosnap snap ไว้ใน cron แบบรายชั่วโมง และใส่ zfs-autosnap gc แบบรายวัน ก็จะหมุนประวัติ snapshot ตาม retention policy ให้
      การใช้ wrapper ของคำสั่ง ZFS แบบง่าย ๆ ไม่ได้ยาก ดังนั้นจะเอา code ของผมไปทำเครื่องมือของตัวเองก็ได้
    • เคยอ่านมาว่า หนึ่งในงานสุดท้ายของช่างตีเหล็กฝึกหัดคือการทำเครื่องมือทั้งหมดที่ช่างตีเหล็กจริงจะใช้เอง เช่น ทั่ง ค้อน คีม ฯลฯ
      ที่ทำงานผมก็เขียน script หลายตัวสำหรับสร้าง ZFS array ให้ตรงกับรูปแบบ deployment ที่ตั้งใจไว้ในวันนั้น ๆ ภายในนั้นรวมถึงการสร้าง volume ที่เข้ารหัสด้วย LUKS เพื่อวาง zvol, การทำให้ naming convention เป็นมาตรฐาน, การตั้งค่า default อย่าง ashift=12, การบีบอัด lz4
      นั่นเป็นเรื่องก่อนที่ ZFS จะมี native encryption อยู่มาก และวิธีปัจจุบันก็ยังไม่มีปัญหา เลยไม่ได้อัปเดต script ให้รองรับ ZFS encryption
      ตอนนี้ผมจำ flag จำนวนมากไม่ได้แล้ว แต่ script ทำหน้าที่เป็นเอกสาร และคนอื่นในทีมแค่รัน make-zfs-big-mirror หรือ make-big-zfs-undundant-raid0 ก็พอ
      สักวันถ้ามีงาน provision ระบบเกิน 20 ครั้งต่อปี แม้แต่ส่วนนี้ก็อาจถูกทำให้เป็น automation ใน provisioning ได้
    • อย่างที่หลายคนพูดไปแล้ว นี่เป็น ข้อเสนอที่มีรสนิยมแรงมาก การมีความเห็นไม่ใช่เรื่องผิด แต่หลายข้ออยู่ตั้งแต่ “ไม่ใช่วิธีที่ผมคุ้นใน Linux” ไปจนถึงข้อเสนอที่มีปัญหาจริง ๆ
      การไม่ให้ตั้งชื่อ pool นั้นไม่สมเหตุสมผล คุณไม่ได้สร้าง pool บ่อยขนาดนั้น แค่ตั้งชื่อไปก็พอ
      ถ้าไม่อยากตั้งชื่อ snapshot ก็ใช้ httm กับ zfs allow ได้ เช่น httm -S . จะสร้าง snapshot อย่าง rpool/ROOT/ubuntu_tiebek@snap_2022-12-14-12:31:41_httmSnapFileMount
      zfs และ zpool ต่างเป็น คำสั่ง Unix ที่ยอดเยี่ยม ซึ่งมีคำสั่งย่อยหลายตัว ผมคิดว่านักออกแบบ ZFS ตัดสินใจได้ฉลาดมากที่ไม่ทำคำสั่งจัดการแบบคำสั่งเดียวที่ซับซ้อนกว่า
      การ mount และ browse snapshot dataset อย่างชัดเจนก็ทำได้ง่ายด้วย zfs mount เพียงแต่อยากให้เชื่อด้วยว่า virtual interface ที่เสถียรช่วยให้ค้นหา version ทั้งหมดของไฟล์ได้ง่าย และเรื่องนี้ทำใน btrfs ฯลฯ ยากกว่ามาก httm ก็น่าดูไว้เช่นกัน
      [0]: https://kimono-koans.github.io/opinionated-guide/#dynamic-sn...
  • ยังมีสิ่งที่มีประโยชน์เพิ่มเติมใน ZFS อีก ควรรู้ความแตกต่างระหว่าง zpool-attach(8) กับ zpool-replace(8) และ zfs list -t all -o space จะแสดงให้เห็นว่าพื้นที่ถูกใช้ไปที่ไหน
    สำหรับการปกป้องระบบปฏิบัติการก่อนการเปลี่ยนแปลงหรืออัปเกรดครั้งใหญ่ ZFS Boot Environments คือฟีเจอร์ที่ดีที่สุด ลิงก์ https://is.gd/BECTL อาจเป็นจุดเริ่มต้นที่มีประโยชน์
    zpool history poolname จะแสดงทั้งการตั้งค่าพูลและประวัติการเปลี่ยนแปลงทั้งหมด เช่น การเปลี่ยนแปลงอย่าง zpool create, autotrim=on, atime=off, compression=zstd, recordsize=1m จะถูกบันทึกไว้
    ยังมีข้อมูลสำคัญที่คู่มือนี้ไม่ได้กล่าวถึงด้วย มิเรอร์แบบ 3-way แม้ดิสก์ 2 ใน 3 ลูกจะเสีย ข้อมูลก็ยังอยู่, มิเรอร์แบบ 4-way แม้ดิสก์ 3 ใน 4 ลูกจะเสียก็ยังอยู่ และมิเรอร์แบบ N-way แม้ดิสก์ N-1 จาก N ลูกจะเสีย ข้อมูลก็ยังคงถูกเก็บรักษาไว้
    มีประโยชน์เมื่อข้อมูลสำคัญที่สุด แต่สล็อตหรือจำนวนดิสก์มีไม่มาก

    • มิเรอร์แบบ N-way ยังมีคุณสมบัติที่ ZFS สามารถกระจายการอ่านไปยังหลายดิสก์ได้ด้วย จุดนี้เคยค่อนข้างสำคัญในยุคดิสก์จานหมุนที่จำนวนงาน I/O ถูกจำกัด
  • ใช้งาน ฐานข้อมูล PostgreSQL ขนาดใหญ่ระดับหลาย TB บน ZFS มาหลายปีแล้ว ZFS ทำให้การสำรองข้อมูล การสร้างสภาพแวดล้อมทดสอบจากสแนปช็อตในอดีต และการประหยัดดิสก์ด้วยการบีบอัดในตัวทำได้ง่ายมาก
    ถ้าสนใจ สามารถอ่านประสบการณ์ได้ที่ https://lackofimagination.org/2022/04/our-experience-with-po...

  • ตอนเริ่มใช้ ZFS สิ่งที่ช่วยได้มากที่สุดคือ ZFS Handbook ของ FreeBSD และบทความของ Aaron Toponce
    [0] https://docs.freebsd.org/en/books/handbook/zfs/
    1 https://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux...

    • ชอบ เอกสารของ FreeBSD
      เคยติดตั้ง FreeBSD บน HP Microserver รุ่นเก่าที่มี ECC RAM 1GB ซึ่งหาได้จากของที่มีอยู่ และมีฮาร์ดดิสก์เก่า 500GB อีก 5 ลูก จึงตั้งค่าเป็นมิเรอร์ 5x โดยดูจาก FreeBSD Handbook ตอนนั้นใช้ FreeBSD เป็นครั้งแรก แต่ก็ทำได้ราบรื่นมาก
  • ช่วงหลังได้สร้างโครงสร้างพื้นฐานใหม่จำนวนมาก ซึ่งส่วนใหญ่เป็นเซิร์ฟเวอร์ LAMP จึงตัดสินใจวางทั้งหมดบน ZFS บน Linux เพื่อการจำลองสำรองข้อมูลที่มีประสิทธิภาพและการเข้ารหัส
    ใช้ ZFS ร่วมกับ rsync สำหรับแบ็กอัปมานานแล้วจึงค่อนข้างคุ้นเคย และผลลัพธ์ก็ออกมาดี แต่พอพยายามทำให้ถูกต้องจริง ๆ กลับใช้เวลามากกว่าที่คาดไว้มาก โดยเฉพาะเรื่องฐานข้อมูลและการจำลองข้อมูล มีคำแนะนำผิด ๆ บนเว็บอยู่เยอะ
    สำหรับฐานข้อมูล อย่างน้อยควรทำการปรับแต่งพื้นฐาน เช่น การจัดแนวขนาดบล็อก สำหรับ mariadb/InnoDB เอกสารของฝั่ง Let's Encrypt ที่ https://github.com/letsencrypt/openzfs-nvme-databases ดีเหนือกว่าอย่างชัดเจน เพราะอธิบายเหตุผลของทุกข้อและอ้างอิงแหล่งข้อมูลหลายแห่ง จึงมีคุณค่ามาก
    ถ้าค้นเว็บต่อไป จะเจอคำแนะนำที่ขัดแย้งกัน เกร็ดเล่า และตำนานต่าง ๆ อย่างไม่รู้จบ พร้อมทฤษฎีที่ไม่สมบูรณ์และไม่มีหลักฐานรองรับ สุดท้ายต้องทดสอบเอง ทำความเข้าใจสิ่งที่กำลังปรับ และการตัดสินใจไม่ปรับบางอย่างก็เป็นเรื่องที่ยอมรับได้
    สำหรับการจำลองข้อมูล แนะนำให้อ่านหน้า manual จริง ๆ ZFS มีเครื่องมือจำลองข้อมูลที่แข็งแกร่ง แต่มีความเอนกประสงค์มากจนให้ความรู้สึกเหมือนคำสั่ง plumbing ระดับล่างของ Git มันไม่ได้สมมติว่าจะใช้ผ่าน SSH จึงต้องต่อประกอบเอง และถ้าจะทำอัตโนมัติก็ต้องคิดถึงเงื่อนไขขอบเขตต่าง ๆ ด้วย ทำให้ตอนแรกดูน่ากลัว
    ด้วยเหตุนี้ทุกคนจึงไปใช้เครื่องมืออย่าง syncoid แต่สคริปต์จำลองข้อมูลสาย syncoid มีจุดที่แย่มากอยู่ คือไม่ใช้โหมด send --replication ของ ZFS แต่ไปเขียนใหม่แบบไม่สมบูรณ์ด้วย Perl โดยอ้างว่ายืดหยุ่นกว่า
    ตอนทดสอบครั้งแรก พอกู้คืนใหม่แล้วเห็นว่า encryption root ทั้งหมดพัง และคุณสมบัติของ dataset ไม่ได้ซิงก์อัตโนมัติทั้งหมด ก็แทบคลั่ง หากใช้เพียง ตัวเลือกการจำลองแบบ recursive ในตัว ZFS ก็จะจัดการเรื่องนี้ให้
    ถ้าตั้งใจเขียนสคริปต์เองก็ไม่ยาก แค่ทำให้เรียบง่าย และอย่าใส่สิ่งไม่จำเป็นเต็ม pipeline แบบ syncoid เมื่อทดสอบจริง สิ่งเหล่านั้นยังทำให้ช้าลงด้วย ดู progress ด้วย pv แล้วส่งต่อไปเลย ก็ทำงานได้เร็ว
    สักวันอาจเผยแพร่สคริปต์จำลองข้อมูลของตัวเอง รู้สึกว่าแทบไม่มีสคริปต์อ้างอิงที่ดี ซึ่งครอบคลุมพื้นฐานแต่ไม่ไปเขียนการจำลองข้อมูลใหม่แบบเละเทะ

    • เอกสารนั้นกล่าวถึงการปรับ io_capacity และ io_capacity_max แต่เมื่อกดเข้าไปดูเอกสาร MySQL เพื่อดูบทบาทจริงของพารามิเตอร์แล้ว น่าเสียดายที่มันไม่ได้มีประโยชน์มากนัก
      ค่านี้ใช้ควบคุม I/O เบื้องหลัง เช่น การ merge change buffer และอาจแย่ง I/O ไปจากโปรเซสหลักที่ต้องทำงานจริง
      จากประสบการณ์ที่เคยดูแล MySQL DB ที่ค่อนข้างยุ่งระดับ 120K QPS ไม่จำเป็นต้องไปแตะทั้งสองค่านี้เลย หากรู้สึกว่าจำเป็น ควรเริ่มจากการมอนิเตอร์เวลาที่ redo log ใช้จนเต็ม และสัดส่วน dirty page ใน buffer pool ก่อน น่าจะดีกว่าหากไปปรับพารามิเตอร์อื่น
      [0] https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.ht...
    • เวลาทำการปรับแต่งพื้นฐานในฐานข้อมูล เช่น การจัดแนวขนาดบล็อก มีจุดที่ควรตรวจสอบซึ่งอาจคาดไม่ถึง โดยทั่วไปมักบอกให้ปรับ record size ให้ตรงกัน และในทางปฏิบัติมักนำไปสู่การลด record size ของไฟล์ซิสเต็ม ZFS ที่เก็บข้อมูล
      ในบางระดับอาจมีประสิทธิภาพมากขึ้น แต่จากประสบการณ์แล้วทำให้ อัตราการบีบอัด ลดลงอย่างมาก
      ผลข้างเคียงลำดับสองที่น่าสนใจคือ แม้จะขึ้นอยู่กับ workload แต่ถ้าคอขวดอยู่ที่แบนด์วิดท์ดิสก์ throughput อาจแย่ลงได้ เพราะการบีบอัดช่วยให้อ่าน/เขียนได้เร็วกว่าที่ดิสก์จริงรองรับ แต่ถ้าทำให้การบีบอัดแย่ลง ก็อาจส่งผลเสียต่อแบนด์วิดท์อ่าน/เขียน
  • ผมเริ่มใช้ ZFS บน Linux ตั้งแต่หลายปีก่อน และโดยรวมก็ราบรื่นดี
    สิ่งเดียวที่ทำให้แปลกใจคือ ค่าเริ่มต้นของ volblocksize ค่อนข้างแย่สำหรับการตั้งค่า RAIDZ ส่วนใหญ่ ถ้าไม่อยากเสียพื้นที่ดิสก์ดิบไป 50% ต้องเพิ่มค่านี้
    บทความที่เกี่ยวข้องมีดังนี้
    https://jro.io/nas/#overhead
    https://openzfs.github.io/openzfs-docs/Basic%20Concepts/RAID...
    https://www.delphix.com/blog/zfs-raidz-stripe-width-or-how-i...
    สุดท้ายถึงขั้นไปดูหนึ่งในสเปรดชีตเกี่ยวกับ ZFS
    ZFS overhead calc.xlsx
    https://docs.google.com/spreadsheets/d/1tf4qx1aMJp8Lo_R6gpT6...
    RAID-Z parity cost
    https://docs.google.com/spreadsheets/d/1pdu_X2tR4ztF6_HLtJ-D...

    • ส่วนตัวผมมองว่า ประสิทธิภาพการใช้พื้นที่ 50% ของ mirror vdev เป็นราคาที่สมเหตุสมผล เมื่อคิดถึงความเรียบง่ายและประสิทธิภาพที่ดีขึ้นมาก ตอนนี้ RAIDZ pool ก็ขยายได้แล้ว แต่ก็ยังซับซ้อนกว่ามาก และประสิทธิภาพก็ไม่ได้ดีเท่า
  • ตอนเด็กกว่านี้และยังโง่กว่านี้ ผมเคยอ่านบทความมากมายจากแฟนตัวยงที่เขียนว่า NAS OS โอเพนซอร์ส ซึ่งน่าจะเป็น FreeNAS กับ ZFS นั้นยอดเยี่ยมแค่ไหน ผมซื้อ HP microserver มือสองสเปกต่ำมากจาก eBay แล้วกระโจนเข้าไปทั้งที่ไม่ค่อยรู้ว่ากำลังทำอะไรอยู่
    ผมถามคำถามไปสองสามข้อในฟอรัมชุมชน แต่คำตอบส่วนใหญ่คือ “อ่านเอกสารหรือยัง?” “RAM พอไหม?”
    เอกสารที่ว่านั้นเป็นสไลด์ PowerPoint สไตล์อ่านยาก น้ำเสียงออกแนวเผยแพร่ศาสนานิด ๆ มีสมมติฐานเรื่องความรู้พื้นฐานเยอะ และไม่ได้อัปเดตเป็นประจำ ปริมาณ RAM ที่ต้องใช้ก็คลุมเครือ และเน้นแค่ว่าให้ใส่ให้มากที่สุดเท่าที่ทำได้
    สุดท้ายผมก็เมินสัญญาณเตือนทั้งหมด ทั้งเรื่องเทคโนโลยี บรรยากาศที่อวยเกินจริง และระดับความรู้ของตัวเอง แล้วก็สูญเสียข้อมูลไปมาก ได้เรียนรู้อะไรเยอะเลย

    • อยากรู้ว่าพอจำได้ไหมว่าประมาณกี่ปีมาแล้ว ZFS มีมาตั้งแต่ช่วงต้นทศวรรษ 2000 และเท่าที่จำได้ FreeNAS เริ่มในปี 2005
      ผมคิดว่า filesystem เสถียรขึ้นมากแล้ว และเอกสารก็ชัดเจนขึ้นด้วย
      ถึงอย่างนั้น เพราะมัน ทรงพลังกว่าและขั้นสูงกว่า filesystem แบบ journaling ดั้งเดิมอย่าง ext3 มาก วิธีที่จะทำให้ตัวเองพลาดก็มีมากขึ้นตามไปด้วย
  • ขอทิ้งบางอย่างไว้สำหรับภายหลังอีกหน่อยคือ ความซ้ำซ้อนทั้งหมดของ ZFS อยู่ที่ชั้น vdev zpool ถูกสร้างจาก vdev อย่างน้อยหนึ่งตัว และไม่ว่าในกรณีใด ถ้าเสีย vdev ไปหนึ่งตัวใน zpool, zpool ก็จะพังถาวร
    ในอดีต RAIDZ หรือก็คือ parity RAID ไม่สามารถขยายด้วยการเพิ่มดิสก์ได้ วิธีเดียวที่จะขยาย RAIDZ คือแทนที่ดิสก์แต่ละลูกในอาร์เรย์ทีละลูกด้วยดิสก์ที่ใหญ่กว่า แล้วภาวนาไม่ให้ดิสก์เสียระหว่าง rebuild
    ถ้าตัดสินแบบสมัครเล่นมาก ๆ ผมจะพิจารณา RAIDZ เฉพาะกรณีที่มีดิสก์จำนวนมากอย่าง RAIDZ2 หรือ RAIDZ3 เท่านั้น ถ้า n<=6 และงบประมาณเอื้อ ผมจะใช้ mirror vdev หลายตัว ในสภาพแวดล้อม production ควรต้องไปค้นคว้าตัวชี้วัดประสิทธิภาพการอ่าน/เขียนของ RAID หลายแบบเพิ่มเติม

    • mirror pool มักเป็นวิธีที่ปลอดภัยกว่าจริง
      แต่จะแนะนำ RAIDZ1 ได้ก็ต่อเมื่อมีแบ็กอัปทั้งไซต์ และค่อนข้างเชื่อมั่นในความสามารถกับการมอนิเตอร์ของตัวเองเท่านั้น
      กรณีของผมมีพูลไดรฟ์ 3x3 และส่ง snapshot ไปยังเป้าหมายแบ็กอัปที่อยู่ต่ำลงไปไม่กี่ U ในแร็ก เป้าหมายแบ็กอัปนั้นตื่นขึ้นมาทุกวัน มีพูลไดรฟ์ 3x4 และก็เป็น RAIDZ1 เช่นกัน
      ถ้าไดรฟ์ใน NAS เสีย แผนคือจะเริ่มแบ็กอัปทันที รับ snapshot แล้วค่อยเปลี่ยนไดรฟ์ วิธีนี้จะลดโอกาสที่ข้อมูลจะหายจากไดรฟ์ลูกที่สองเสียระหว่าง resilvering ให้เหลือน้อยที่สุด
      แน่นอนว่าข้อมูลที่สำคัญจริง ๆ ก็เก็บไว้นอกสถานที่ด้วย
  • ผมกำลังเจอ ปัญหา ZFS ที่ไม่เข้าใจ ใน zpool หนึ่ง zpool status แสดงรายการข้อผิดพลาดที่ตรวจพบ แต่ไม่ได้อยู่ในไฟล์ และมักปรากฏเฉพาะใน snapshot รวมถึงรายการเลขฐานสิบหกที่น่าจะเป็น snapshot ที่ถูกลบไปแล้ว
    ถ้าลบ snapshot ที่ถูกระบุว่ามีข้อผิดพลาด แล้วรัน zpool scrub สองครั้ง ข้อผิดพลาดก็หายไป และ scrub ก็ไม่พบข้อผิดพลาด zpool status ไม่เคยแสดงข้อผิดพลาดในอุปกรณ์ใดเลย
    ไฟล์ไม่มีข้อผิดพลาด อุปกรณ์ก็ไม่มีข้อผิดพลาด scrub ก็ตรวจไม่พบข้อผิดพลาด แต่ระหว่างใช้งานกลับมี “ข้อผิดพลาด” ใหม่วันละ 12 รายการโผล่ใน zpool status ไม่รู้ว่าเรื่องแบบนี้เกิดขึ้นได้อย่างไร

    • เป็นคำถามที่ดีมาก ตอนนี้ไม่มีเวลาค้นหา issue ซ้ำเอง แต่ลองค้นหาหรือถามใน mailing list https://zfsonlinux.topicbox.com/groups/zfs-discuss และ GitHub issue https://github.com/openzfs/zfs/issues ได้
      อันแรกดูแปลก ๆ แต่เป็นเว็บฟรอนต์เอนด์ปกติของ mailing list
    • กำลังเจอปัญหาเดียวกัน บางครั้งไฟล์ดูเหมือนเสียหายไม่ใช่แค่ใน snapshot แต่ในเวอร์ชันไฟล์ปัจจุบันด้วย
      ย้ายหรือแก้ไขไม่ได้ ลบได้อย่างเดียว ไม่รู้เลยว่าทำไมไฟล์พวกนี้ถึงเสียหาย โชคดีที่ทั้งหมดเป็น Linux ISO ขนาดใหญ่ เลยไม่ถึงกับร้ายแรง