SSD Nodes Learn 🎉 VPS เริ่ม $5.50/เดือน
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-13

การตั้งค่า ZFS บน VPS: จัดการ RAM อย่างไรให้คุ้มค่า

ZFS มอบฟีเจอร์ checksum และ snapshots ที่มีประโยชน์ แต่ ARC มักจอง RAM จนเต็มเครื่องบน VPS ขนาดเล็ก เรียนรู้วิธีปรับแต่งค่า zfs_arc_max เพื่อรักษาประสิทธิภาพแอปพลิเคชันของคุณ

สิ่งที่ ZFS มอบให้และสิ่งที่คุณต้องแลก

ZFS บน FreeBSD และ Linux ปัจจุบันใช้ codebase เดียวกันคือ OpenZFS ดังนั้นฟีเจอร์ต่างๆ จึงเหมือนกันทั้งสองระบบ เซิร์ฟเวอร์ที่รัน ZFS จะได้รับข้อมูลที่มีการตรวจสอบ checksum, snapshots ที่ไม่มีค่าใช้จ่ายจนกว่าข้อมูลจะมีการเปลี่ยนแปลง, การทำ replication ด้วย zfs send และการบีบอัดข้อมูลที่เปิดใช้งานได้เพียงแค่ตั้งค่า property เดียว สิ่งที่ต้องแลกคือหน่วยความจำ: ARC (adaptive replacement cache) จะจองพื้นที่ RAM จำนวนมากโดยค่าเริ่มต้น และบน VPS (virtual private server) ขนาด 2 GB หรือ 4 GB หน่วยความจำส่วนนั้นคือสิ่งที่แอปพลิเคชันของคุณต้องการใช้งาน

คู่มือนี้ประเมิน ZFS จากมุมมองของ VPS ที่เช่ามาซึ่งมีดิสก์เสมือนหนึ่งหรือสองลูก ไม่ใช่จากตู้เก็บข้อมูลที่มีช่องใส่ไดรฟ์ 40 ช่อง ฟีเจอร์ที่ยังคงมีประโยชน์ในสภาพแวดล้อมนี้คือสิ่งที่คุณควรให้ความสำคัญ ส่วนที่ไม่คุ้มค่าคือสิ่งที่คุณควรรู้ก่อนเริ่มสร้าง pool

OpenZFS บน FreeBSD และ Linux: โค้ดเบสเดียวกัน แต่แนวทางการจัดการแพ็กเกจที่ต่างกัน

FreeBSD ได้รวม ZFS ไว้ในระบบพื้นฐานมาตั้งแต่ FreeBSD 7.0 ในปี 2008 โดยเริ่มแรกเป็นฟีเจอร์ทดลอง นับตั้งแต่ OpenZFS 2.0 ในเดือนธันวาคม 2020 ทั้ง FreeBSD และ Linux ได้ใช้ซอร์สโค้ดชุดเดียวกันในการ build ทำให้ zfs และ zpool มีพฤติกรรมการทำงานที่เหมือนกันบนทั้งสองระบบ และ pool ที่สร้างบนระบบหนึ่งสามารถนำไป import บนอีกระบบหนึ่งได้

เหตุผลที่ ZFS เป็นแพ็กเกจบน Linux แต่เป็นส่วนหนึ่งของระบบพื้นฐานบน FreeBSD คือเรื่องของลิขสิทธิ์ OpenZFS อยู่ภายใต้สัญญาอนุญาต CDDL (Common Development and Distribution License) ในขณะที่ Linux kernel อยู่ภายใต้สัญญาอนุญาต GPL (General Public License) เวอร์ชัน 2 โครงการ kernel มองว่าสัญญาอนุญาตทั้งสองไม่สามารถใช้งานร่วมกันได้ โค้ดของ ZFS จึงไม่ถูกรวมเข้ากับ mainline Linux และแต่ละ distribution จึงต้องตัดสินใจว่าจะจัดการอย่างไร FreeBSD ไม่มีข้อขัดแย้งดังกล่าว ZFS จึงถูกรวมไว้ในระบบโดยตรง นี่คือข้อเท็จจริงทั้งหมดในทางปฏิบัติ: มีความแตกต่างเพียงเรื่องการจัดการแพ็กเกจเท่านั้น และคุณไม่จำเป็นต้องเลือกข้างแต่อย่างใด

SSD Nodes ไม่มีอิมเมจของ FreeBSD ให้บริการ ดังนั้นบนเซิร์ฟเวอร์ที่เช่าจากที่นี่ ส่วนของ Linux ในคู่มือนี้จึงเป็นสิ่งที่นำไปใช้ได้จริง หากคุณใช้งาน FreeBSD ที่อื่น เซิร์ฟเวอร์ FreeBSD จะมาพร้อมกับ ZFS โดยที่คุณไม่ต้อง build โมดูลเองและไม่ต้องกังวลเรื่องการอัปเกรด kernel แล้วระบบจะใช้งานไม่ได้

การติดตั้ง ZFS และการสร้าง pool

บน Ubuntu โมดูลจะมาพร้อมกับแพ็กเกจ kernel อยู่แล้ว คุณจึงเพียงแค่ติดตั้งชุดคำสั่งเท่านั้น

sudo apt update
sudo apt install -y zfsutils-linux
zfs version

zfs version จะแสดงผลลัพธ์สองบรรทัด คือเวอร์ชันของ userland และเวอร์ชันของ kernel module หากแสดงเพียงบรรทัดเดียว หมายความว่าโมดูลไม่ได้ถูกโหลด แพ็กเกจนี้อยู่ในคอมโพเนนต์ universe ซึ่ง Ubuntu server image เปิดใช้งานไว้เป็นค่าเริ่มต้น หาก apt หาแพ็กเกจไม่พบ ให้รัน sudo add-apt-repository universe ก่อน

บน Debian แพ็กเกจจะอยู่ในคอมโพเนนต์ contrib และโมดูลจะถูกคอมไพล์บนเครื่องของคุณโดยใช้ DKMS (dynamic kernel module support) ให้เพิ่ม contrib ต่อท้ายบรรทัด Components: ในไฟล์ /etc/apt/sources.list.d/debian.sources จากนั้นรัน sudo apt update แล้วตามด้วย:

sudo apt install -y linux-headers-$(dpkg --print-architecture) zfs-dkms zfsutils-linux

การติดตั้งจะทำการคอมไพล์โมดูลและแสดงข้อความ Building initial module for 6.12.0-... ซึ่งอาจใช้เวลาสองสามนาที โปรดจำไว้ว่าทุกครั้งที่มีการอัปเกรด kernel ระบบจะทำการคอมไพล์ใหม่ และหากการคอมไพล์ล้มเหลว คุณจะไม่สามารถ mount pool ได้จนกว่าจะแก้ไขปัญหาให้เรียบร้อย

บน FreeBSD ไม่จำเป็นต้องติดตั้งอะไรเพิ่มเติม เพียงแค่เปิดใช้งาน service และเริ่มการทำงาน

sysrc zfs_enable=YES
service zfs start

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

ls -l /dev/disk/by-id/
sudo zpool create -o ashift=12 tank /dev/disk/by-id/virtio-abc123def456
zpool status tank

zpool status ควรแสดงผลลัพธ์เป็น state: ONLINE โดยมีอุปกรณ์ของคุณปรากฏอยู่ภายใต้ tank การใช้ ashift=12 จะกำหนดขนาดบล็อกที่เล็กที่สุดของ pool ไว้ที่ 4 KiB ซึ่งสอดคล้องกับ SSD ในปัจจุบันและไม่สามารถเปลี่ยนแปลงได้หลังจากสร้าง pool ไปแล้ว

image ของเซิร์ฟเวอร์เช่าส่วนใหญ่จะบูตจาก root filesystem ที่เป็น ext4 ดังนั้น ZFS ในที่นี้จึงเป็นเพียง data pool บน volume ที่สอง ไม่ใช่ root filesystem ให้ตรวจสอบให้แน่ใจว่าอุปกรณ์นั้นคืออุปกรณ์ที่คุณต้องการจริงๆ ก่อนเริ่มสร้าง เพราะ การยืนยัน NVMe disk ที่คุณได้รับ ใช้เวลาเพียงหนึ่งนาที แต่การสร้างใหม่ทั้งหมดอาจกินเวลาทั้งบ่าย

Checksum จะซ่อมแซมข้อมูลได้ก็ต่อเมื่อ pool มีความซ้ำซ้อน (redundancy)

ทุกบล็อกข้อมูลที่ ZFS เขียนลงไปจะมี checksum กำกับไว้ และทุกครั้งที่มีการอ่านข้อมูล ระบบจะตรวจสอบ checksum เสมอ การตรวจพบข้อผิดพลาดจึงทำงานได้ตลอดเวลา แต่การซ่อมแซมจำเป็นต้องมีสำเนาชุดที่สอง

ใน pool ที่มีดิสก์เพียงลูกเดียว ZFS จะแจ้งสถานะตามความเป็นจริงและหยุดการทำงานเพียงแค่นั้น โดย zpool status -v จะแสดงผลดังนี้:

status: One or more devices has experienced an error resulting in data
        corruption.
action: Restore the file in question if possible.  Otherwise restore the
        entire pool from backup.
errors: Permanent errors have been detected in the following files:

        /tank/data/archive.tar

ระบบจะระบุชื่อไฟล์ที่เสียหายออกมา ในขณะที่ ext4 จะส่งคืนข้อมูลที่ผิดพลาดนั้นโดยไม่มีการแจ้งเตือนใดๆ ดังนั้นการที่ ZFS แจ้งเตือนจึงถือว่ามีประโยชน์มาก แต่ ZFS ยังไม่สามารถแก้ไขข้อมูลให้ถูกต้องได้เนื่องจากไม่มีสำเนาชุดที่สองใน pool สำหรับใช้กู้คืน

ในกรณีที่เป็น mirror การอ่านข้อมูลจะถูกดึงมาจากฝั่งที่ปกติ จากนั้นบล็อกที่เสียหายจะถูกเขียนทับใหม่ และเหตุการณ์ดังกล่าวจะปรากฏในคอลัมน์ CKSUM ของ zpool status นี่คือกระบวนการซ่อมแซมตัวเอง (self-healing) ซึ่งจำเป็นต้องใช้อุปกรณ์จัดเก็บข้อมูลสองตัว

sudo zpool create -o ashift=12 tank mirror /dev/disk/by-id/DISK1 /dev/disk/by-id/DISK2

บน VPS พื้นที่จัดเก็บข้อมูลของโฮสต์มักจะมีความซ้ำซ้อนอยู่แล้ว โดยส่วนใหญ่มักเป็น RAID 10 ภายใต้ hypervisor ซึ่งช่วยป้องกันกรณีดิสก์เสีย แต่ระบบจะไม่แจ้งเตือนเมื่อข้อมูลที่อ่านกลับมามีความผิดพลาด เนื่องจากตัว array ไม่สามารถทราบได้ว่าสำเนาชุดใดถูกต้อง แต่ ZFS สามารถทราบได้เพราะมีการเปรียบเทียบข้อมูลกับ checksum ที่เขียนไว้ด้วยตัวเอง

หากคุณมีดิสก์เสมือนเพียงลูกเดียวและต้องการความสามารถในการซ่อมแซมข้อมูล sudo zfs set copies=2 tank/important จะจัดเก็บสำเนาของทุกบล็อกใน dataset นั้นไว้สองชุดบนดิสก์ลูกเดียวกัน วิธีนี้จะทำให้พื้นที่ที่ใช้สำหรับ dataset นั้นเพิ่มขึ้นเป็นสองเท่า ซึ่งช่วยให้รอดพ้นจากกรณีบล็อกข้อมูลเสียหายได้ แต่จะไม่มีผลหากโวลุ่มทั้งหมดสูญหายไป

การทำ scrub คือการอ่านข้อมูลทั้งหมดใน pool เพื่อตรวจสอบความถูกต้อง

sudo zpool scrub tank
zpool status tank

pool ที่อยู่ในสถานะปกติจะแสดงบรรทัดข้อความคล้ายกับ scan: scrub repaired 0B in 00:04:11 with 0 errors ควรตั้งเวลาการทำงานนี้ไว้เป็นประจำ โดยการทำเดือนละครั้งถือว่าเพียงพอสำหรับ pool ขนาดเล็ก

systemctl list-unit-files 'zfs-scrub*'
sudo systemctl enable --now zfs-scrub-monthly@tank.timer

Dataset คือหน่วยของการกำหนดนโยบาย

Dataset คือระบบไฟล์ที่อยู่ภายใน pool และการสร้าง dataset นั้นทำได้ง่ายและประหยัดทรัพยากร ดังนั้นควรสร้างแยกตามงานแต่ละประเภท คุณสมบัติต่างๆ จะถูกสืบทอดมาจาก pool ซึ่งหมายความว่าคุณสามารถตั้งค่าเริ่มต้นไว้ที่ระดับ pool เพียงครั้งเดียว แล้วค่อยกำหนดค่าทับเฉพาะในส่วนที่จำเป็น

sudo zfs create tank/data
sudo zfs create tank/pg
sudo zfs set compression=lz4 tank
sudo zfs set atime=off tank
sudo zfs set quota=20G tank/data
sudo zfs set recordsize=16K tank/pg
zfs get -r compression,compressratio,quota tank

Compression เป็นคุณสมบัติที่ผู้คนมักละเลยด้วยความระมัดระวังเกินเหตุ ซึ่งเป็นความเข้าใจที่ผิด lz4 ใช้ CPU เพียงเล็กน้อยแต่ช่วยลดจำนวนไบต์ที่ต้องเขียนลงดิสก์ ดังนั้นสำหรับข้อมูลที่บีบอัดได้ การเปิดใช้งานนี้มักจะทำให้การอ่านและเขียนข้อมูลเร็วขึ้น zstd จะบีบอัดข้อมูลได้แน่นกว่าโดยแลกกับการใช้ CPU มากขึ้น ซึ่งเหมาะสำหรับไฟล์ log และไฟล์เก็บถาวรที่คุณไม่ค่อยได้เปิดอ่าน ตรวจสอบประสิทธิภาพที่ได้รับจริงด้วย zfs get compressratio tank และโปรดจำไว้ว่าอัตราส่วนการบีบอัดจะคำนวณเฉพาะข้อมูลที่เขียนหลังจากตั้งค่าคุณสมบัตินี้แล้วเท่านั้น

recordsize คือขนาดบล็อกที่ใหญ่ที่สุดที่ dataset จะเขียน โดยค่าเริ่มต้นคือ 128K หากฐานข้อมูลเขียนข้อมูลขนาด 8 KiB ลงใน record ขนาด 128 KiB จะทำให้การเขียนขนาดเล็กหนึ่งครั้งกลายเป็นการอ่าน record ทั้งหมดเพื่อแก้ไขแล้วเขียนกลับลงไปใหม่ ควรตั้งค่า recordsize=16K บน dataset ของฐานข้อมูลก่อนที่คุณจะโหลดข้อมูลเข้าไป เพราะคุณสมบัตินี้จะมีผลกับบล็อกที่เขียนใหม่เท่านั้น

quota คือวิธีที่คุณใช้ป้องกันไม่ให้ dataset ใด dataset หนึ่งใช้พื้นที่ใน pool จนเต็ม ZFS pool ที่มีความจุใกล้ 100% จะทำงานช้าลงและจัดการพื้นที่คืนได้ยาก ดังนั้นควรเผื่อพื้นที่ว่างไว้โดยเจตนา

Snapshot ไม่มีค่าใช้จ่ายจนกว่าข้อมูลจะมีการเปลี่ยนแปลง

ZFS จะไม่เขียนทับบล็อกข้อมูลที่ใช้งานอยู่จริง แต่จะใช้วิธีเขียนบล็อกใหม่แล้วอัปเดตตัวชี้ (pointer) แทน ซึ่งนี่คือความหมายของ copy-on-write การทำ snapshot คือการบันทึกสถานะว่า "ให้เก็บรักษาบล็อกที่ dataset นี้ชี้อยู่ ณ ขณะนี้ไว้" ดังนั้นการทำ snapshot จึงทำได้ทันทีและไม่มีค่าใช้จ่าย

sudo zfs snapshot tank/data@2026-08-11
zfs list -t snapshot -o name,used,refer -r tank/data

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

การกู้คืนไฟล์กลับมาไม่จำเป็นต้องมีขั้นตอนการ restore

ls /tank/data/.zfs/snapshot/
cp /tank/data/.zfs/snapshot/2026-08-11/notes.txt /tank/data/notes.txt

ไดเรกทอรี .zfs จะถูกซ่อนไว้แม้กระทั่งจาก ls -a จนกว่าคุณจะรันคำสั่ง sudo zfs set snapdir=visible tank/data ควรทำ snapshot ไว้ก่อนที่คุณจะจำเป็นต้องใช้มัน เพราะหากไม่มี snapshot การพิมพ์คำสั่ง rm -rf ผิดพลาดจะทำให้คุณต้องเข้าสู่ เส้นทางการกู้คืนข้อมูลของ ext4 ซึ่งเริ่มต้นด้วยการ unmount ดิสก์และสถานการณ์จะเลวร้ายลงหลังจากนั้น

การทำ rollback จะทิ้งข้อมูลทุกอย่างที่ถูกเขียนขึ้นหลังจาก snapshot นั้น

sudo zfs rollback tank/data@2026-08-11

ระบบจะปฏิเสธการทำงานหากมี snapshot ที่ใหม่กว่าอยู่ และคำสั่ง -r จะทำลาย snapshot ที่ใหม่กว่าเหล่านั้นเพื่อดำเนินการต่อ โปรดตรวจสอบชื่อ dataset ให้ถี่ถ้วนก่อนกด enter

Snapshot ไม่ใช่การสำรองข้อมูล (backup) มันอาศัยอยู่ใน pool เดียวกัน บน volume เดียวกัน และบนเซิร์ฟเวอร์เดียวกัน หาก volume เสียหายหรือเกิดเหตุการณ์ zpool destroy ข้อมูลและ snapshot ทั้งหมดก็จะสูญหายไปพร้อมกัน Snapshot ช่วยป้องกันคุณจากความผิดพลาดของตัวคุณเอง (rm) และจากการอัปเกรดที่ล้มเหลว ซึ่งครอบคลุมเหตุการณ์จริงส่วนใหญ่ แต่ snapshot ไม่สามารถป้องกันความเสียหายที่เกิดขึ้นกับตัว pool เองได้ รายละเอียดทั้งหมดระบุไว้ที่นี่: เหตุใด VPS snapshot จึงไม่ใช่การสำรองข้อมูล

การส่งและรับข้อมูล: การทำ replication ด้วยคำสั่งเดียว

zfs send จะเปลี่ยน snapshot ให้เป็น byte stream บน standard output และ zfs receive จะเปลี่ยน stream นั้นกลับเป็น dataset การคัดลอกครั้งแรกจะเป็นการส่งแบบเต็ม (full send)

sudo zfs snapshot tank/data@daily-2026-08-11
sudo zfs send tank/data@daily-2026-08-11 | ssh backup.example.com "sudo zfs recv -F backup/data"

หลังจากนั้น ให้ส่งเฉพาะส่วนที่มีการเปลี่ยนแปลงระหว่าง snapshot สองตัว

sudo zfs snapshot tank/data@daily-2026-08-12
sudo zfs send -i tank/data@daily-2026-08-11 tank/data@daily-2026-08-12 | ssh backup.example.com "sudo zfs recv backup/data"

ฝั่งรับจะต้องมี snapshot ที่คุณใช้เป็นต้นทางอยู่ หากไม่มี การรับข้อมูลจะหยุดลงพร้อมกับ cannot receive incremental stream: most recent snapshot of backup/data does not match incremental source เนื่องจาก ZFS ไม่มีฐานข้อมูลอ้างอิงสำหรับนำส่วนต่างไปปรับใช้ ให้ส่งจาก snapshot ที่ทั้งสองฝั่งมีเหมือนกัน หรือเริ่มการส่งแบบเต็มใหม่อีกครั้ง

ให้สิทธิ์การใช้งานบนฝั่งปลายทางแทนการใช้ root จากระยะไกล: sudo zfs allow -u backupuser create,mount,receive backup/data

นี่คือการสำรองข้อมูลนอกสถานที่ (off-site backup) ที่แท้จริงโดยมีเงื่อนไขเดียว คือฝั่งปลายทางต้องเป็น ZFS pool เนื่องจาก object storage ไม่สามารถรับ stream ได้ หากเป้าหมายของคุณเป็น storage ที่รองรับ S3 หรือโฮสต์ Linux ทั่วไป ให้ใช้เครื่องมือที่สื่อสารกับระบบเหล่านั้นได้ โดย การสำรองข้อมูลด้วย restic จาก VPS จะครอบคลุมแนวทางดังกล่าว

เหตุใด ZFS จึงใช้ RAM จำนวนมาก? ARC

ARC (adaptive replacement cache) คือแคชสำหรับการอ่านของ ZFS ซึ่งทำงานอยู่ในหน่วยความจำระดับเคอร์เนลแทนที่จะใช้ Linux page cache ปกติ ดังนั้น free -h จึงไม่รายงานหน่วยความจำส่วนนี้ภายใต้ buff/cache แต่จะแสดงเป็นหน่วยความจำที่ถูกใช้งาน เครื่องที่ใช้ ZFS ซึ่งดูเหมือน RAM เต็มมักเป็นเพราะแคชกำลังทำงานอยู่ (warm cache) ซึ่งเป็นสาเหตุส่วนใหญ่ของรายงานที่ว่า "ZFS กิน RAM ของฉัน"

ค่าจำกัดเริ่มต้นถูกตั้งไว้สูงโดยเจตนา OpenZFS 2.3 กำหนดขนาดสูงสุดของ ARC ไว้ที่ค่าที่มากกว่าระหว่าง RAM ลบด้วย 1 GiB หรือ 5/8 ของ RAM ทั้งหมด ส่วน OpenZFS 2.2 และเวอร์ชันก่อนหน้าบน Linux จะใช้ค่าครึ่งหนึ่งของ RAM ในขณะที่ FreeBSD ใช้กฎใหม่นี้มานานแล้ว ให้รันคำสั่ง zfs version เพื่อตรวจสอบว่าระบบของคุณใช้กฎใด

ChartDefault maximum ARC size by instance RAM, from the OpenZFS default rule (GiB)
The data behind this chart
[
  {
    "label": "2 GB VPS",
    "openzfs_2_2_linux_gib": 1,
    "openzfs_2_3_gib": 1.25
  },
  {
    "label": "4 GB VPS",
    "openzfs_2_2_linux_gib": 2,
    "openzfs_2_3_gib": 3
  },
  {
    "label": "8 GB VPS",
    "openzfs_2_2_linux_gib": 4,
    "openzfs_2_3_gib": 7
  },
  {
    "label": "16 GB VPS",
    "openzfs_2_2_linux_gib": 8,
    "openzfs_2_3_gib": 15
  }
]

ตัวเลขเหล่านี้เป็นกฎค่าเริ่มต้นตามเอกสารที่ใช้กับขนาด instance ทั่วไป ไม่ใช่การวัดค่าจากเครื่องที่กำลังทำงานอยู่ บน instance ขนาด 4 GB กฎของเวอร์ชัน 2.3 จะอนุญาตให้ ARC มีขนาด 3 GiB ในขณะที่เครื่องเดียวกันบนเวอร์ชัน 2.2 จะจำกัดไว้ที่ 2 GiB ส่วน instance ขนาด 2 GB ภายใต้กฎของเวอร์ชัน 2.3 จะยังคงอนุญาตให้ใช้ได้ 1.25 GiB โดยแอปพลิเคชันของคุณจะได้รับหน่วยความจำส่วนที่เหลือไปใช้งาน

ให้ตรวจสอบตัวเลขจริงจากเซิร์ฟเวอร์ของคุณเองแทนการเชื่อถือตาราง:

grep -E '^(size|c_max) ' /proc/spl/kstat/zfs/arcstats
arc_summary | head -n 20

คอลัมน์ที่สามคือหน่วยเป็นไบต์ c_max คือเพดานสูงสุดที่บังคับใช้ในขณะนี้ และ size คือขนาดที่ ARC ถือครองอยู่จริงในปัจจุบัน

ARC สามารถคืนหน่วยความจำได้ เมื่อเคอร์เนลส่งสัญญาณว่ามีแรงกดดันด้านหน่วยความจำ ARC จะลดขนาดลง ปัญหาคือเรื่องของจังหวะเวลา (timing) เนื่องจากการลดขนาดจะเกิดขึ้นก็ต่อเมื่อมีแรงกดดันดังกล่าว ดังนั้นกระบวนการที่ต้องการหน่วยความจำหลายร้อย MiB ในทันทีอาจถูก OOM (out of memory) killer จัดการก่อนที่ ARC จะคืนหน่วยความจำเสร็จสิ้น บนเครื่องขนาด 2 GB ที่รันฐานข้อมูลและเว็บเซิร์ฟเวอร์ เหตุการณ์นี้ไม่ใช่เรื่องแปลก คู่มือของ OpenZFS ระบุไว้เช่นเดียวกันเกี่ยวกับการปรับค่าด้วยตนเองว่า การลดค่าจำกัด "จะไม่ทำให้ ARC ลดขนาดลงหากไม่มีแรงกดดันด้านหน่วยความจำมากระตุ้นให้เกิดการลดขนาด"

วิธีการจำกัดขนาด ARC บน VPS ขนาดเล็ก

ให้ตัดสินใจเลือกปริมาณหน่วยความจำสำหรับภาระงานก่อน โดยรวมความต้องการของฐานข้อมูลและแอปพลิเคชันเข้าด้วยกัน เผื่อพื้นที่ว่างสำหรับระบบปฏิบัติการไว้เล็กน้อย แล้วจึงจัดสรรส่วนที่เหลือให้กับ ARC สำหรับอินสแตนซ์ขนาด 4 GB ที่รัน Postgres และเว็บแอปพลิเคชันหนึ่งตัว การกำหนด ARC ไว้ที่ 512 MiB ถึง 1 GiB ถือเป็นจุดเริ่มต้นที่เหมาะสม

กำหนดค่าให้มีผลทันทีโดยใช้หน่วยเป็นไบต์ ตัวอย่างนี้คือ 1 GiB

echo 1073741824 | sudo tee /sys/module/zfs/parameters/zfs_arc_max

ทำให้การตั้งค่าคงอยู่หลังการรีบูต

echo 'options zfs zfs_arc_max=1073741824' | sudo tee /etc/modprobe.d/zfs.conf
sudo update-initramfs -u

ขั้นตอนการตั้งค่า initramfs มีความสำคัญเนื่องจากโมดูลอาจโหลดจาก initramfs ก่อนที่ระบบไฟล์ root จะถูก mount ซึ่งจะทำให้ระบบไม่อ่านไฟล์ที่คุณเพิ่งสร้างขึ้น หลังจากรีบูตแล้ว ให้ตรวจสอบด้วยบรรทัด c_max จาก arcstats

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

บน FreeBSD การจำกัดค่านี้จะเป็น sysctl ภายใต้ vfs.zfs.arc ให้รัน sysctl vfs.zfs.arc เพื่อดูค่าปัจจุบันและชื่อที่ถูกต้องซึ่งเวอร์ชันของคุณใช้งานอยู่ จากนั้นจึงเขียนค่าสูงสุดลงใน /boot/loader.conf

กฎเพิ่มเติมอีกสองข้อสำหรับหน่วยความจำบนเซิร์ฟเวอร์ขนาดเล็ก คือให้ปิดการใช้งาน deduplication เนื่องจากตาราง dedup จะถูกเก็บไว้ในหน่วยความจำ โดยมีกฎทั่วไปที่ยอมรับกันว่าต้องใช้ RAM 1 ถึง 3 GB ต่อข้อมูลที่ไม่ซ้ำกัน 1 TB และห้ามทำ swap บน zvol (อุปกรณ์บล็อกที่แบ่งออกมาจาก pool) เพราะการทำ swap ผ่านระบบไฟล์ที่กำลังพยายามคืนหน่วยความจำอาจทำให้เครื่องค้าง (deadlock) ได้ ให้เก็บ swap ไว้บนพาร์ติชันปกติหรือไฟล์ swap ที่อยู่นอก pool แทน

เมื่อ ext4 หรือ XFS ร่วมกับ restic เป็นทางเลือกที่ดีกว่า

ZFS จะแสดงประสิทธิภาพได้เต็มที่บนเซิร์ฟเวอร์ที่มีหน่วยความจำเหลือเฟือและมีดิสก์ลูกที่สอง นอกเหนือจากกรณีนั้น การใช้ระบบไฟล์ทั่วไปร่วมกับเครื่องมือสำรองข้อมูลที่แท้จริงย่อมได้เปรียบกว่า ให้เลือกใช้ ext4 หรือ XFS เมื่อ:

  • อินสแตนซ์มี RAM ขนาด 2 GB หรือ 4 GB และภาระงานต้องการใช้ RAM ทั้งหมดนั้น
  • มีดิสก์เสมือนเพียงลูกเดียวและไม่มีสำเนาที่สอง ดังนั้น ZFS จะทำได้เพียงตรวจพบข้อผิดพลาดแต่ไม่สามารถซ่อมแซมได้
  • ปลายทางการสำรองข้อมูลของคุณคือ object storage หรือโฮสต์ Linux ทั่วไป ซึ่งไม่มีระบบใดที่สามารถรับสตรีม zfs send ได้
  • คุณใช้งาน Debian ร่วมกับ DKMS และไม่สามารถรับความเสี่ยงจากการอัปเกรด kernel ที่อาจทำให้โมดูลไม่ถูกคอมไพล์ได้
  • คุณต้องการใช้ ZFS บนระบบไฟล์ root แต่ image ของผู้ให้บริการมีให้เลือกเพียง ext4 เท่านั้น

ให้คงการใช้ ZFS ไว้เมื่อคุณมีโวลุ่มข้อมูลแยกต่างหาก มี RAM เหลือเฟือ (8 GB ขึ้นไปถือว่าเพียงพอ) และมีแผนการใช้งาน snapshot และ zfs send ที่ชัดเจนแทนที่จะเพียงแค่เปิดใช้งานมัน สำหรับกรณีอื่นทั้งหมด การใช้ ext4 ร่วมกับ restic เพื่อเขียนข้อมูลสำรองที่เข้ารหัสและทำ deduplication ไปยังพื้นที่จัดเก็บที่เซิร์ฟเวอร์ไม่ได้ควบคุมโดยตรง จะให้ผลลัพธ์ในลักษณะเดียวกันโดยไม่สิ้นเปลืองหน่วยความจำ

รูปแบบความล้มเหลวและข้อความที่คุณจะพบ

Pool หายไปหลังจากรีบูต zpool status จะแสดง no pools available บริการ import จะอ่านค่าจาก /etc/zfs/zpool.cache ดังนั้นหากไม่มีชื่อ pool ในไฟล์ดังกล่าว ระบบจะไม่ทำการ import pool นั้นโดยอัตโนมัติเมื่อบูตเครื่อง sudo zpool import จะแสดงรายการ pool ที่สามารถ import ได้ sudo zpool import tank จะทำการดึง pool กลับมา และ sudo zpool set cachefile=/etc/zfs/zpool.cache tank จะทำให้การตั้งค่านี้คงอยู่ถาวร หาก pool ไม่ได้ถูก export อย่างถูกต้องจากระบบอื่น ระบบจะแจ้งเตือน cannot import 'tank': pool may be in use from other system ซึ่ง sudo zpool import -f tank จะใช้เพื่อข้ามการตรวจสอบนี้เมื่อคุณมั่นใจแล้วว่าไม่มีโฮสต์อื่นใช้งาน pool นั้นอยู่

modprobe: FATAL: Module zfs not found in directory /lib/modules/6.12.0-... บน Debian หลังจากอัปเกรด kernel สาเหตุเกิดจาก DKMS ไม่ได้ build โมดูลสำหรับ kernel ใหม่ ซึ่งมักเป็นเพราะยังไม่ได้ติดตั้ง header ที่ตรงกัน dkms status จะแสดงรายการสิ่งที่ถูก build ไว้สำหรับแต่ละ kernel จากนั้นใช้ sudo apt install -y linux-headers-$(uname -r) ตามด้วย sudo dkms autoinstall เพื่อ build ใหม่ และ sudo zpool import tank เพื่อนำ pool กลับมาใช้งาน

Pool เต็มทั้งที่ลบไฟล์ไปแล้ว ข้อมูลที่ถูกลบจะยังคงอยู่บนดิสก์ตราบเท่าที่ยังมี snapshot อ้างอิงถึงข้อมูลนั้น ทำให้ค่าที่แสดงใน du และ df ไม่ตรงกัน zfs list -o space -r tank จะแยกการใช้งานออกเป็น USEDDS และ USEDSNAP หากค่า USEDSNAP สูงมากนั่นคือสาเหตุ ให้ลบ snapshot เก่าทิ้งด้วย sudo zfs destroy tank/data@2026-06-01 แล้วพื้นที่ว่างจะกลับคืนมา

ค่า CKSUM เพิ่มขึ้นใน zpool status มีบางอย่างที่อยู่ใต้ ZFS ส่งข้อมูลที่ผิดพลาดกลับมา ในกรณีที่เป็น mirror ค่านี้ถือเป็นคำเตือนและบล็อกข้อมูลนั้นได้รับการซ่อมแซมแล้ว แต่หากเป็น pool ที่มีดิสก์ลูกเดียว ไฟล์นั้นจะสูญหาย zpool status -v จะระบุชื่อไฟล์ดังกล่าว และคุณต้องกู้คืนไฟล์นั้นจากข้อมูลสำรองที่ไม่ได้เก็บไว้ใน pool นี้

เซิร์ฟเวอร์ทำงานช้าและมีการทำ swapping ให้จำกัดขนาด ARC ตามที่ระบุไว้ข้างต้น จากนั้นรัน arc_summary แล้วตรวจสอบอัตรา hit ratio หาก ARC มีขนาดเล็กเกินกว่าจะเก็บ working set ได้ จะทำให้ทุกการอ่านต้องไปที่ดิสก์ ซึ่งในจุดนี้การใช้ระบบไฟล์ทั่วไปที่อาศัย page cache อาจให้ประสิทธิภาพที่ดีกว่า

FAQ

ZFS ต้องการ RAM เท่าไรบน VPS?

ZFS สามารถทำงานได้บนอินสแตนซ์ขนาด 2 GB แต่คำถามที่สำคัญกว่าคือเหลือ RAM เท่าไรสำหรับแอปพลิเคชันของคุณ หากไม่มีการปรับแต่ง OpenZFS 2.3 จะยอมให้ ARC ขยายขนาดได้สูงสุดระหว่าง RAM ลบด้วย 1 GiB กับ 5/8 ของ RAM ทั้งหมด ดังนั้นเครื่องขนาด 4 GB จึงสามารถจัดสรร RAM ได้สูงสุด 3 GiB ให้กับแคช ให้กำหนดค่า zfs_arc_max เป็นตัวเลขที่เหมาะสมกับภาระงานของคุณ จากนั้นตรวจสอบความถูกต้องโดยอ่านบรรทัด c_max จาก /proc/spl/kstat/zfs/arcstats

ZFS snapshot ถือเป็นข้อมูลสำรอง (backup) หรือไม่?

ไม่ถือเป็นข้อมูลสำรอง เนื่องจาก snapshot อยู่ใน pool เดียวกับข้อมูลต้นฉบับ มันสามารถช่วยกู้คืนจาก rm ที่ผิดพลาดหรือการอัปเกรดที่ล้มเหลวได้ แต่หาก pool หรืออินสแตนซ์เสียหาย ข้อมูล snapshot ก็จะสูญหายไปด้วย คุณควรเปลี่ยนให้เป็นข้อมูลสำรองโดยการส่ง (send) ไปยังเครื่องอื่นด้วย zfs send หรือใช้เครื่องมือสำรองข้อมูลที่เขียนข้อมูลลงในพื้นที่จัดเก็บข้อมูลที่เซิร์ฟเวอร์นี้ไม่สามารถควบคุมได้

ZFS ทำงานเหมือนกันบน FreeBSD และ Linux หรือไม่?

ใช้ codebase เดียวกันตั้งแต่ OpenZFS 2.0 ในเดือนธันวาคม 2020 ใช้คำสั่งเดียวกัน รูปแบบข้อมูลบนดิสก์เหมือนกัน และสามารถย้าย pool ระหว่างระบบปฏิบัติการได้ ความแตกต่างอยู่ที่การจัดการแพ็กเกจ FreeBSD รวม ZFS ไว้ในระบบพื้นฐาน ส่วนบน Linux แต่ละ distribution จะตัดสินใจเอง เช่น Ubuntu จะ build โมดูลไว้ในแพ็กเกจ kernel ส่วน Debian จะ build บนเครื่องของคุณด้วย DKMS ดังนั้นการอัปเกรด kernel อาจทำให้คุณไม่มีโมดูลใช้งานจนกว่าการ build ใหม่จะเสร็จสิ้น

ZFS สามารถซ่อมแซมความเสียหายบน VPS ที่มีดิสก์ลูกเดียวได้หรือไม่?

ZFS สามารถตรวจพบความเสียหายและระบุชื่อไฟล์ที่ได้รับผลกระทบได้ แต่ไม่สามารถซ่อมแซมได้เนื่องจากการซ่อมแซมจำเป็นต้องมีสำเนาของบล็อกข้อมูลชุดที่สอง การตั้งค่า zfs set copies=2 บน dataset จะช่วยให้คุณมีสำเนาชุดที่สองโดยใช้พื้นที่เพิ่มขึ้นเป็นสองเท่า ซึ่งช่วยจัดการกับบล็อกที่เสียหายได้ แต่ไม่สามารถแก้ปัญหาในกรณีที่ volume สูญหายได้ การทำ mirror ข้ามสอง volume คือคำตอบที่ช่วยซ่อมแซมข้อมูลได้จริง

การบีบอัดข้อมูลทำให้เซิร์ฟเวอร์ทำงานช้าลงหรือไม่?

lz4 มักจะช่วยให้ทำงานเร็วขึ้น บล็อกที่ถูกบีบอัดหมายถึงจำนวนไบต์ที่เขียนและอ่านน้อยลง และภาระงานของ CPU ต่อบล็อกนั้นถือว่าน้อยมากเมื่อเทียบกับพื้นที่ดิสก์ที่ประหยัดได้ ให้ตั้งค่า compression=lz4 ที่ระดับ root ของ pool เพื่อให้ทุก dataset สืบทอดการตั้งค่านี้ จากนั้นตรวจสอบ zfs get compressratio tank หลังจากที่มีการเขียนข้อมูลจริงลงไปแล้ว