ZFS trên Linux cho Production: Xây dựng Pool chịu lỗi, tối ưu Dataset và tự động hóa Snapshot cùng Scrub

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Bối cảnh & Lý do: Xử lý triệt để tình trạng Bit Rot ngầm trong Production

Một node PostgreSQL chịu tải cao bất ngờ gặp lỗi đọc I/O trong đợt chạy batch định kỳ ban đêm. Một số sector trên cặp ổ cứng SAS doanh nghiệp đã gặp phải hiện tượng bit rot (suy thoái dữ liệu ngầm).

Hiện tượng trôi từ tính vật lý làm hỏng dữ liệu ngay trên bề mặt đĩa từ mà card RAID phần cứng không hề ghi nhận bất kỳ cảnh báo nào. Các filesystem tiêu chuẩn như EXT4 hay XFS mặc định tin cậy hoàn toàn các thiết bị block bên dưới. Khi ổ đĩa trả về các bit lỗi, filesystem sẽ chuyển tiếp thẳng dữ liệu hỏng đó tới ứng dụng của bạn cho đến khi xảy ra sự cố sập hệ thống (crash).

OpenZFS xử lý lưu trữ theo cách hoàn toàn khác. Thay vì xếp chồng một filesystem lên trên một trình quản lý volume độc lập, ZFS hợp nhất cả hai tầng này.

ZFS bảo vệ mọi block được ghi bằng checksum 256-bit—mặc định sử dụng thuật toán Fletcher4 cực nhanh. Trong mỗi thao tác đọc, ZFS tính toán lại và xác thực checksum đó. Khi phát hiện một block bị hỏng trên ổ đĩa mirror, ZFS sẽ đọc dữ liệu chính xác từ ổ đĩa còn tốt, tự động sửa chữa block lỗi ở chế độ nền và trả về dữ liệu sạch mà không làm gián đoạn ứng dụng.

Kiến trúc lưu trữ quyết định độ tin cậy lâu dài của hệ thống. Cấu hình storage pool chuẩn xác ngay từ đầu trước khi nạp dữ liệu sẽ giúp bạn tiết kiệm hàng chục giờ di chuyển dữ liệu hàng terabyte đầy rủi ro và phức tạp sau này.

Cài đặt: Chuẩn bị máy chủ cho OpenZFS

Đầu tiên, hãy xác định các ổ đĩa vật lý thô (raw) hoặc ổ NVMe được chỉ định cho storage pool. Tuyệt đối không xây dựng ZFS pool trên các ổ đĩa ảo (virtual disk) của hardware RAID. ZFS cần giao tiếp trực tiếp với phần cứng ổ đĩa thông qua HBA ở chế độ IT mode hoặc các kênh SATA/NVMe trực tiếp. Thiết lập này giúp ZFS kiểm soát toàn quyền bộ nhớ đệm ghi (write cache), trạng thái nguồn và dữ liệu đo đạc sức khỏe SMART của ổ đĩa.

1. Cài đặt các gói ZFS Kernel

Ubuntu và Debian phân phối OpenZFS trực tiếp qua các kho lưu trữ package chính thức.

Dành cho Ubuntu/Debian:

sudo apt update
sudo apt install -y zfsutils-linux

Dành cho RHEL, AlmaLinux và Rocky Linux 9:

sudo dnf install -y epel-release
sudo dnf install -y https://zfsonlinux.org/epel/zfs-release-2-3$(rpm -E %dist).noarch.rpm
sudo dnf config-manager --enable zfs-kmod
sudo dnf install -y zfs

2. Nạp và kiểm tra Kernel Module

sudo modprobe zfs
lsmod | grep -i zfs

3. Xác định Disk ID cố định

Không bao giờ tạo pool bằng các device node động như /dev/sdb. Ký tự ổ đĩa của kernel có thể bị thay đổi thứ tự sau khi thay ổ hoặc khởi động lại máy chủ. Thay vào đó, hãy sử dụng định danh cố định theo số serial từ /dev/disk/by-id/:

ls -l /dev/disk/by-id/

Cấu hình: Zpool, Dataset, Snapshot và tự động hóa Scrub

1. Tạo Mirrored Zpool có khả năng chịu lỗi cao

Để tạo một mirrored pool hiệu năng cao có tên là tank sử dụng hai ổ đĩa 2TB (ata-ST2000DM008_DISK1_ID và ata-ST2000DM008_DISK2_ID), hãy chạy:

sudo zpool create -f -o ashift=12 -O compression=zstd -O acltype=posixacl -O xattr=sa -O relatime=on tank mirror \
  /dev/disk/by-id/ata-ST2000DM008_DISK1_ID \
  /dev/disk/by-id/ata-ST2000DM008_DISK2_ID

Dưới đây là ý nghĩa của các cờ (flag) cấu hình cho môi trường production:

  • ashift=12: Thiết lập số mũ kích thước block của vdev thành 12 (212 = 4096 byte). Cấu hình này giúp căn chỉnh I/O với các sector vật lý 4K trên các ổ HDD chuẩn Advanced Format và SSD NVMe hiện đại, tránh suy giảm hiệu năng ghi nghiêm trọng.
  • compression=zstd: Kích hoạt tính năng nén Zstandard. Với các workload hỗn hợp, Zstandard mang lại tỷ lệ nén từ 1.4x đến 1.8x, đồng thời rút ngắn thời gian ghi đĩa thực tế.
  • xattr=sa: Lưu trữ các thuộc tính mở rộng của file (extended attributes) trực tiếp bên trong inode, giúp tăng tốc độ kiểm tra quyền truy cập trên Linux.

2. Tạo và tối ưu Dataset theo từng Workload

Tránh lưu dữ liệu production trực tiếp trên root pool. Dataset cho phép bạn thiết lập chi tiết recordsize, hạn ngạch (quota) và chính sách caching cho từng ứng dụng cụ thể.

Hãy căn chỉnh recordsize của dataset khớp với page size mặc định của database engine. PostgreSQL sử dụng page size 8 KB, trong khi MySQL InnoDB mặc định là 16 KB. Việc khớp các giá trị này giúp loại bỏ hiện tượng khuếch đại ghi (write amplification) và tránh các chu kỳ read-modify-write tốn kém tài nguyên.

# Dataset được tối ưu cho PostgreSQL (page 8k) hoặc MySQL InnoDB (page 16k)
sudo zfs create tank/databases
sudo zfs set recordsize=16k tank/databases
sudo zfs set logbias=latency tank/databases
sudo zfs set atime=off tank/databases

# Dataset cho lưu trữ container nói chung và web asset
sudo zfs create tank/appdata
sudo zfs set recordsize=128k tank/appdata
sudo zfs set quota=500G tank/appdata

3. Snapshot tức thì với cơ chế Copy-on-Write

ZFS snapshot ghi lại trạng thái dữ liệu của bạn tại một thời điểm nhất định. Nhờ sử dụng các con trỏ copy-on-write, việc tạo snapshot cho một database 2 TB chỉ mất chưa đầy 100 mili-giây và không tốn dung lượng lưu trữ ban đầu.

# Tạo snapshot tức thì trước khi thực hiện migration schema
sudo zfs snapshot tank/databases@pre_migration_2026_10_01

# Kiểm tra dung lượng lưu trữ của snapshot
sudo zfs list -t snapshot

# Rollback tức thì nếu cập nhật schema thất bại
sudo zfs rollback tank/databases@pre_migration_2026_10_01

Bạn cần chạy thử nghiệm trên môi trường staging với dữ liệu production mà không làm ảnh hưởng đến dữ liệu gốc? Hãy clone snapshot thành một dataset độc lập có thể ghi:

sudo zfs clone tank/databases@pre_migration_2026_10_01 tank/db_test_sandbox

4. Tự động hóa quá trình Scrub cho Pool

Quá trình scrub sẽ đọc toàn bộ các block dữ liệu đang hoạt động trong pool một cách có hệ thống, đối chiếu với checksum tương ứng và tự động sửa chữa bit rot ngầm bằng dữ liệu chẵn lẻ (parity) từ ổ mirror. Trên một pool 2 TB, scrub thường hoàn tất trong khoảng 30 đến 60 phút tùy thuộc vào tốc độ ổ đĩa và tải I/O.

Kích hoạt scrub thủ công bất cứ khi nào cần thiết:

sudo zpool scrub tank

Chạy scrub tự động hàng tuần thông qua systemd timer gọn nhẹ:

# 1. Định nghĩa service dạng one-shot
sudo tee /etc/systemd/system/zfs-scrub-tank.service << 'EOF'
[Unit]
Description=Quét và sửa lỗi ZFS Storage Pool (tank)
Documentation=man:zpool-scrub(8)

[Service]
Type=oneshot
ExecStart=/usr/sbin/zpool scrub tank
EOF

# 2. Định nghĩa lịch chạy hàng tuần (mỗi Chủ Nhật lúc 02:00 UTC)
sudo tee /etc/systemd/system/zfs-scrub-tank.timer << 'EOF'
[Unit]
Description=Timer chạy ZFS Scrub hàng tuần cho tank

[Timer]
OnCalendar=Sun *-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
EOF

# 3. Nạp lại cấu hình và kích hoạt timer
sudo systemctl daemon-reload
sudo systemctl enable --now zfs-scrub-tank.timer

Kiểm tra & Giám sát: Đảm bảo sức khỏe ổ đĩa

1. Kiểm tra trạng thái Pool và lỗi I/O

Kiểm tra trạng thái thời gian thực của các ổ đĩa, tiến trình scrub đang chạy và số lượng kiểm tra checksum:

sudo zpool status tank

Hãy theo dõi sát sao cột CKSUM. Giá trị lớn hơn 0 xác nhận rằng ZFS đã phát hiện lỗi dữ liệu ở cấp độ bit và tự động sửa lỗi ngay trong quá trình hoạt động.

2. Theo dõi tỷ lệ nén và dung lượng sử dụng

sudo zfs get compressratio,used,available,mountpoint tank

3. Cấu hình cảnh báo với ZFS Event Daemon (ZED)

Khi ổ đĩa gặp lỗi không thể phục hồi hoặc hỏng hoàn toàn, ZED sẽ gửi thông báo email ngay lập tức:

# Cấu hình file /etc/zfs/zed.d/zed.rc
sudo sed -i 's/#ZED_EMAIL_ADDR="root"/ZED_EMAIL_ADDR="[email protected]"/' /etc/zfs/zed.d/zed.rc
sudo sed -i 's/#ZED_NOTIFY_VERBOSE=0/ZED_NOTIFY_VERBOSE=1/' /etc/zfs/zed.d/zed.rc
sudo sed -i 's/#ZED_EMAIL_PROG="mail"/ZED_EMAIL_PROG="mail"/' /etc/zfs/zed.d/zed.rc

sudo systemctl restart zed

Việc kết hợp mirror pool được căn chỉnh 4K với recordsize tối ưu cho từng dataset, snapshot tức thì, scrub tự động và cảnh báo qua ZED sẽ mang lại cho máy chủ Linux của bạn độ tin cậy lưu trữ chuẩn doanh nghiệp thực thụ.

Share: