Xây dựng cụm lưu trữ phân tán GlusterFS chịu lỗi trên Linux: Hướng dẫn cấu hình Replicated Volume

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

Điểm lỗi đơn lẻ (Single Point of Failure) trong hệ thống lưu trữ chia sẻ

Lưu trữ chia sẻ thường là mắt xích yếu nhất trong các kiến trúc có lưu lượng truy cập lớn. Dù bạn đang quản lý một dàn Nginx web worker, một cụm Kubernetes hay các node chuyển mã (transcoding) media, các đội ngũ kỹ thuật thường bắt đầu với một ổ chia sẻ Network File System (NFS) tiêu chuẩn. Nó hoạt động trơn tru ngay từ đầu.

Thế nhưng NFS lại là một quả bom nổ chậm trong vận hành: khi cỗ máy NFS đơn lẻ đó bị hỏng ổ cứng, dính lỗi kernel panic hoặc phải khởi động lại để vá lỗi kernel định kỳ, mọi client đang mount thư mục đều sẽ bị treo. I/O bị nghẽn dồn ứ chỉ trong vài giây. Các worker pool của PHP-FPM và Node bị bão hòa, load balancer kích hoạt cảnh báo health check thất bại, và toàn bộ ứng dụng của bạn sụp đổ.

Phần cứng SAN doanh nghiệp có thể loại bỏ điểm lỗi đơn lẻ này, nhưng các thiết bị chuyển mạch fiber-channel chuyên dụng dễ dàng ngốn tới hàng chục nghìn USD. Lưu trữ dạng khối (block storage) trên đám mây như AWS EBS hay GCP Persistent Disk giải quyết được độ tin cậy của ổ cứng, nhưng tùy chọn multi-attach lại đắt đỏ, bị khóa theo vùng (region-locked) và rất phức tạp khi cấu hình. Thứ bạn cần là một giải pháp lưu trữ định nghĩa bằng phần mềm (software-defined storage) chạy trực tiếp trên các máy chủ Linux thông thường, gộp các ổ SSD NVMe hoặc SATA nội bộ và đồng bộ hóa thao tác ghi theo thời gian thực—mà không phải phụ thuộc vào một máy chủ metadata trung tâm mỏng manh.

GlusterFS thực sự hoạt động như thế nào

GlusterFS tập hợp các hệ thống tập tin cục bộ trên nhiều node mạng thành các volume mạng hợp nhất và co giãn linh hoạt. Nếu từng làm việc với Ceph, bạn sẽ hiểu rõ gánh nặng vận hành khi phải duy trì các monitor node chuyên dụng, OSD daemon và các trình quản lý metadata (MDS). GlusterFS loại bỏ hoàn toàn những phức tạp đó.

Không cần máy chủ Metadata: Thuật toán Elastic Hash (DHT)

GlusterFS không có bảng tra cứu trung tâm. Khi một ứng dụng ghi tệp /uploads/avatar_9482.jpg, Gluster client sẽ tính toán mã băm Davies-Meyer 32-bit của đường dẫn tệp. Giá trị băm đó ánh xạ trực tiếp tới một brick cụ thể trong bản đồ volume của cụm. Nhờ việc client định vị tệp hoàn toàn bằng thuật toán toán học thay vì truy vấn metadata qua mạng, thao tác tra cứu thư mục sẽ không bao giờ bị nghẽn tại một máy chủ chỉ mục đơn lẻ. Tầng lưu trữ của bạn có thể mở rộng theo chiều ngang lên đến hàng trăm terabyte mà không lo độ trễ metadata tăng đột biến.

Các thành phần cốt lõi

  • Brick: Thành phần khối cơ bản nhất. Một brick đơn giản là một thư mục được chia sẻ (export) trên một hệ thống tập tin POSIX đã mount (luôn định dạng với XFS).
  • Trusted Storage Pool: Cụm các máy chủ Linux được ghép nối (peer) và xác thực lẫn nhau để quản lý các volume lưu trữ.
  • Replicated Volume: GlusterFS sao chép đồng bộ các thao tác tập tin trên hai hoặc nhiều brick. Nếu node A gặp sự cố nghiêm trọng, node B sẽ tiếp quản các yêu cầu đọc/ghi mà không làm ngắt kết nối mount của client.
  • Arbiter Node: Một brick quorum đặc biệt chỉ lưu trữ metadata của tệp và các thuộc tính mở rộng (xattr) thay vì toàn bộ dữ liệu nội dung. Nó giúp ngăn chặn tình trạng split-brain chỉ với khoảng 0,1% dung lượng đĩa thực tế.

Hiện tượng Split-Brain và lý do bạn cần Quorum

Cấu hình nhân bản 2 node mà không có quorum tiềm ẩn rất nhiều rủi ro. Nếu đường truyền mạng nội bộ giữa hai node lưu trữ bị đứt trong khi các client vẫn kết nối được tới cả hai, từng máy chủ sẽ tưởng rằng máy kia đã chết. Cả hai sẽ tiếp nhận các thao tác ghi khác nhau vào cùng một tệp. Khi đó, tình trạng split-brain xảy ra: dữ liệu bị phân kỳ thành hai trạng thái xung đột mà không có công cụ tự động nào có thể hòa giải an toàn.

Để tránh việc phải khắc phục dữ liệu thủ công, hãy luôn bật client-side quorum hoặc bổ sung một arbiter node thứ ba gọn nhẹ. Một thao tác ghi chỉ được coi là thành công khi chiếm đa số tuyệt đối các node xác nhận. Không đạt đồng thuận? Thao tác ghi sẽ báo lỗi an toàn thay vì làm hỏng dữ liệu trong volume của bạn.

Từng bước triển khai một Replicated Volume

Chúng ta sẽ cấu hình một cụm lưu trữ nhân bản gồm hai node cùng một application client độc lập. Môi trường thử nghiệm chạy Ubuntu 22.04 LTS trên dải mạng riêng 10.0.10.0/24:

  • gluster01.lab.local: 10.0.10.11 (Node lưu trữ 1)
  • gluster02.lab.local: 10.0.10.12 (Node lưu trữ 2)
  • appclient01.lab.local: 10.0.10.20 (Application Client)

Bước 1: Chuẩn bị mạng và phân giải tên miền

Các node GlusterFS nhận diện lẫn nhau qua hostname. Việc phân giải DNS chập chờn sẽ khiến cụm bị rớt heartbeat, do đó hãy cấu hình IP nội bộ tĩnh trực tiếp trong /etc/hosts trên cả ba máy chủ:

cat << 'EOF' | sudo tee -a /etc/hosts
10.0.10.11 gluster01.lab.local gluster01
10.0.10.12 gluster02.lab.local gluster02
10.0.10.20 appclient01.lab.local appclient01
EOF

Mở các cổng tường lửa cần thiết. Gluster sử dụng cổng TCP 24007 cho quản trị, 24008 cho RDMA, và gán các cổng động bắt đầu từ 49152 cho mỗi brick đang hoạt động:

sudo ufw allow 24007:24008/tcp
sudo ufw allow 49152:49156/tcp
sudo ufw reload

Bước 2: Phân vùng và định dạng đĩa lưu trữ chuyên dụng

Không bao giờ được đặt các brick môi trường production trên phân vùng root. Nếu ổ root bị đầy dung lượng, hệ điều hành sẽ bị treo và bảng inode của phân vùng root xử lý các thao tác ghi song song đồng thời rất kém. Hãy chuẩn bị một ổ đĩa vật lý hoặc đĩa cloud riêng biệt—ở đây là /dev/sdb (SSD 500GB).

Chạy các lệnh sau trên cả gluster01 và gluster02:

# Định dạng với kích thước inode 512 byte để lưu trữ các thuộc tính mở rộng của Gluster
sudo mkfs.xfs -f -i size=512 /dev/sdb

# Tạo thư mục mount và cấu hình mount cố định trong fstab
sudo mkdir -p /data/glusterfs/brick1
echo "/dev/sdb /data/glusterfs/brick1 xfs defaults,noatime,nodiratime,inode64 0 2" | sudo tee -a /etc/fstab
sudo mount -a

# Tạo thư mục brick bên trong phân vùng vừa mount
sudo mkdir -p /data/glusterfs/brick1/gv0

Bước 3: Cài đặt GlusterFS và tạo Trusted Storage Pool

Cài đặt các gói GlusterFS 10 LTS được duy trì chính thức trên cả hai node lưu trữ:

sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:gluster/glusterfs-10
sudo apt update
sudo apt install -y glusterfs-server

sudo systemctl enable --now glusterd

Kiểm tra dịch vụ đã hoạt động hay chưa bằng lệnh systemctl status glusterd. Tiếp theo, thiết lập liên kết peer. Chỉ chạy lệnh này trên gluster01:

sudo gluster peer probe gluster02.lab.local

Kiểm tra trạng thái kết nối từ một trong hai node:

sudo gluster peer status

Kết quả trả về phải xác nhận State: Peer in Cluster (Connected). Nếu hiển thị disconnected, hãy kiểm tra lại khả năng phân giải DNS và kiểm tra kết nối TCP trên cổng 24007 bằng lệnh nc -zv gluster02.lab.local 24007.

Bước 4: Tạo và khởi động Replicated Volume

Bây giờ hãy tạo replicated volume có tên vol_shared. Từ gluster01, thực thi:

sudo gluster volume create vol_shared replica 2 \
  gluster01.lab.local:/data/glusterfs/brick1/gv0 \
  gluster02.lab.local:/data/glusterfs/brick1/gv0

sudo gluster volume start vol_shared

Kiểm tra trạng thái hoạt động của volume:

sudo gluster volume info vol_shared

Bạn sẽ thấy Status: Started và cả hai brick đều được liệt kê trong nhóm bản sao (replica set).

Bước 5: Tối ưu hiệu năng cho môi trường Production

Các thiết lập mặc định ban đầu của Gluster ưu tiên mức độ an toàn tối đa hơn là tốc độ. Trong môi trường có mức đồng thời cao—như phục vụ tệp media của người dùng hoặc ghi log microservice—tốc độ ghi thô có thể khá chậm chạp. Hãy áp dụng các tùy chọn tinh chỉnh volume sau trên gluster01:

# Đệm các thao tác ghi nhỏ vào RAM và xả (flush) bất đồng bộ
sudo gluster volume set vol_shared performance.write-behind on
sudo gluster volume set vol_shared performance.write-behind-window-size 4MB

# Đọc trước (prefetch) các khối dữ liệu liền kề để tăng tốc đọc tuần tự
sudo gluster volume set vol_shared performance.read-ahead on
sudo gluster volume set vol_shared performance.read-ahead-page-count 4

# Mở rộng bộ nhớ đệm cho các thao tác tra cứu thư mục thường xuyên truy cập
sudo gluster volume set vol_shared performance.cache-size 512MB

# Giảm network timeout từ 42 giây xuống 10 giây để kích hoạt failover nhanh hơn
sudo gluster volume set vol_shared network.ping-timeout 10

# Bắt buộc sử dụng quorum để ngăn chặn split-brain
sudo gluster volume set vol_shared cluster.quorum-type auto

Trong các thử nghiệm của chúng tôi với 100 worker đồng thời đẩy các tệp tài nguyên dung lượng 25KB, các thông số tinh chỉnh này đã giúp giảm iowait từ 38% xuống còn 6% và hạ độ trễ ghi từ 45ms xuống dưới 8ms.

Bước 6: Mount thư mục chia sẻ trên Node Client

Chuyển sang appclient01. Mặc dù bạn có thể mount các ổ chia sẻ Gluster qua NFS thông thường, nhưng tốt nhất hãy luôn ưu tiên dùng GlusterFS FUSE client gốc. Client gốc truy vấn trực tiếp sơ đồ topo của cụm. Nó ghi dữ liệu đồng thời tới tất cả các brick bản sao và tự động xử lý failover ngầm mà không cần load balancer bên ngoài hay IP ảo như Keepalived.

sudo apt update
sudo apt install -y glusterfs-client

sudo mkdir -p /mnt/distributed-storage

# Mount ổ chia sẻ bằng cách dùng gluster01 làm điểm kết nối ban đầu
sudo mount -t glusterfs gluster01.lab.local:/vol_shared /mnt/distributed-storage

Thiết lập để tự động mount mỗi khi client khởi động lại. Chỉnh sửa /etc/fstab và thêm chỉ thị backup-volfile-servers. Nếu gluster01 ngoại tuyến khi client khởi động, driver sẽ tự động kết nối sang gluster02:

echo "gluster01.lab.local:/vol_shared /mnt/distributed-storage glusterfs defaults,_netdev,backup-volfile-servers=gluster02.lab.local 0 0" | sudo tee -a /etc/fstab

Bước 7: Kiểm thử tính năng Failover và Self-Healing

Tiến hành kiểm thử cụm. Ghi 50 tệp thử nghiệm từ appclient01:

cd /mnt/distributed-storage
for i in {1..50}; do echo "Checksum dữ liệu $i" > "file_$i.txt"; done
ls -1 | wc -l

Bây giờ hãy mô phỏng tình huống một node sập hoàn toàn. Trên gluster01, hãy ngắt kết nối mạng hoặc dừng cả daemon điều khiển lẫn tiến trình brick:

# Trên gluster01
sudo systemctl stop glusterd
sudo pkill -9 -f glusterfsd

Quay lại ngay appclient01. Đọc và ghi dữ liệu mà không cần tạm dừng:

cat /mnt/distributed-storage/file_1.txt
echo "Ghi dữ liệu mới khi node 1 đã chết" >> /mnt/distributed-storage/file_failover_test.txt

Lệnh thực thi mượt mà. Client chuyển hướng lưu lượng sang gluster02 chỉ trong chưa đầy hai giây. Không có lỗi input/output, không bị khóa mount point.

Tiếp theo, khôi phục lại gluster01:

# Trên gluster01
sudo systemctl start glusterd

Daemon tự phục hồi của Gluster (glustershd) sẽ xử lý việc đồng bộ hóa ngầm dưới nền. Kiểm tra hàng đợi phục hồi từ gluster01:

sudo gluster volume heal vol_shared info

Bạn sẽ thấy các mục chờ phục hồi giảm về 0 chỉ trong vài giây. Cụm lưu trữ đã trở lại trạng thái khỏe mạnh.

Kinh nghiệm thực chiến quý báu cho môi trường Production

  • Tách biệt lưu lượng replication: GlusterFS nhân đôi lưu lượng ghi qua mạng do client phải sao chép dữ liệu đến từng brick. Hãy chuyển lưu lượng lưu trữ sang một VLAN riêng biệt hoặc card mạng (NIC) 10GbE chuyên dụng để tránh việc đồng bộ dữ liệu làm nghẽn băng thông của các API công khai.
  • Sử dụng mô hình 2 Node + 1 Arbiter: Cụm chỉ gồm 2 node thuần túy buộc bạn phải đánh đổi quorum rất nan giải. Hãy chi khoảng 5 USD/tháng cho một VPS nhỏ 1 vCPU với 10GB dung lượng đĩa để làm arbiter node (replica 3 arbiter 1). Nó sẽ tham gia biểu quyết quorum và lưu metadata của tệp, mang lại khả năng chống split-brain vững chắc mà không cần đầu tư thêm một dàn máy chủ lưu trữ thứ ba hoàn chỉnh.
  • Tuyệt đối không can thiệp trực tiếp vào backend brick: Không thêm, sửa hoặc xóa tệp trực tiếp trong /data/glusterfs/brick1/gv0 trên máy chủ. Gluster dựa vào các thuộc tính mở rộng (trusted.gfid và trusted.afr.*) để theo dõi các phiên bản của tệp. Việc sửa đổi tệp trực tiếp sẽ bỏ qua tầng chuyển đổi, làm hỏng đồng bộ ngay lập tức và gây ra split-brain.
  • Để mắt tới tình trạng cạn kiệt inode: Việc lưu trữ hàng triệu tệp nhỏ (như ảnh thumbnail) sẽ làm cạn kiệt inode của hệ thống tập tin rất lâu trước khi dung lượng đĩa thực tế bị đầy. Hãy định dạng với tham số -N hoặc tỷ lệ inode lớn hơn nếu khối lượng công việc của bạn chủ yếu xử lý các tệp nhỏ.

Tổng kết

GlusterFS mang lại giải pháp lưu trữ định nghĩa bằng phần mềm đáng tin cậy mà không tốn phí bản quyền doanh nghiệp hay đòi hỏi kiến trúc cụm phức tạp. Bằng cách kết hợp các phân vùng XFS chuyên dụng với các tham số bộ nhớ đệm hợp lý và quy tắc quorum chặt chẽ, bạn sẽ có được khả năng tự động failover và tự phục hồi (self-healing) mạnh mẽ ngay trên các máy chủ Linux thông thường. Hãy xây dựng cụm của bạn với các giao diện mạng chuyên dụng, thường xuyên theo dõi trạng thái self-heal, và những cơn đau đầu về điểm lỗi đơn lẻ trong hệ thống lưu trữ sẽ hoàn toàn lùi vào dĩ vãng.

Share: