Hướng dẫn thiết lập NFS Server trên Linux: Chia sẻ file nội bộ tốc độ cao và tối ưu Mount

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

Bắt đầu nhanh (5 phút)

Cách đây sáu tháng, đội ngũ phát triển của chúng tôi cần một giải pháp lưu trữ dùng chung cho pipeline CI – nơi tạo ra tới 80GB Docker image và build artifact mỗi ngày. Thay vì phải đau đầu cấu hình Ceph hay GlusterFS, tôi đã dựng một node NFS riêng biệt. Máy chủ duy nhất đó hiện đang xử lý trơn tru khoảng 65.000 giao dịch file mỗi giờ. Dưới đây là cách triển khai một cặp server – client hoàn chỉnh chỉ trong năm phút.

Bước 1: Cài đặt và cấu hình NFS Server

Đầu tiên, hãy cài đặt service server. Trên Ubuntu hoặc Debian:

sudo apt update
sudo apt install -y nfs-kernel-server

Trên AlmaLinux, Rocky Linux hoặc RHEL:

sudo dnf install -y nfs-utils
sudo systemctl enable --now nfs-server

Tạo thư mục chia sẻ (export). Để thử nghiệm, hãy cấp quyền sở hữu cho người dùng không đặc quyền nobody:

sudo mkdir -p /srv/nfs/shared
sudo chown -R nobody:nogroup /srv/nfs/shared
sudo chmod 755 /srv/nfs/shared

Mở file cấu hình exports:

sudo nano /etc/exports

Thêm định nghĩa chia sẻ này vào cuối file, nhớ thay bằng dải mạng client thực tế của bạn (chẳng hạn 192.168.1.0/24):

/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

Xuất các thư mục chia sẻ và làm mới daemon đang chạy:

sudo exportfs -rav
sudo systemctl restart nfs-kernel-server

Bước 2: Kết nối từ Node Client

Cài đặt các tiện ích client trên máy cần truy cập lưu trữ:

# Debian / Ubuntu
sudo apt install -y nfs-common

# RHEL / AlmaLinux
sudo dnf install -y nfs-utils

Truy vấn máy chủ (ví dụ ở đây là 192.168.1.50) để kiểm tra xem thư mục chia sẻ đã hiển thị chưa:

showmount -e 192.168.1.50

Mount thư mục chia sẻ vào một thư mục cục bộ:

sudo mkdir -p /mnt/shared
sudo mount 192.168.1.50:/srv/nfs/shared /mnt/shared

Xác nhận kết nối bằng cách chạy lệnh df -h /mnt/shared. Bạn sẽ thấy ổ đĩa từ xa đã được mount kèm theo tổng dung lượng của nó.

Kiến trúc và các chỉ thị Export

Các bản phân phối Linux hiện đại mặc định sử dụng NFSv4 (cụ thể là v4.1 hoặc v4.2). Khác với NFSv3 vốn phụ thuộc vào rpcbind và phân tán lưu lượng qua các cổng ngẫu nhiên ở dải cao, NFSv4 chỉ giao tiếp qua duy nhất cổng TCP 2049. Điều này giúp cấu hình tường lửa đơn giản hơn rất nhiều. NFSv4 cũng mang đến cơ chế phiên có trạng thái (stateful sessions), pseudo-filesystem và tùy chọn xác thực qua Kerberos.

Chi tiết các chỉ thị trong /etc/exports

Các cờ cấu hình trong /etc/exports quyết định sự cân bằng giữa độ an toàn dữ liệu và tốc độ của hệ thống:

  • rw và ro: Cho phép quyền đọc-ghi (read-write) hoặc ép buộc quyền chỉ đọc (read-only).
  • sync: Chỉ xác nhận yêu cầu ghi sau khi dữ liệu đã thực sự được ghi xuống ổ đĩa vật lý. Cờ này giúp tránh mất mát dữ liệu khi mất điện đột ngột. Hãy luôn bật tùy chọn này trên các hệ thống production.
  • async: Xác nhận ghi ngay khi dữ liệu vào tới bộ nhớ đệm RAM của server. Thông lượng tăng vọt đáng kể, nhưng việc mất điện sẽ làm hỏng các file chưa kịp ghi xuống đĩa.
  • no_subtree_check: Bỏ qua việc kiểm tra thư mục cha khi truy cập vào thư mục con. Nếu bật tính năng kiểm tra này, hệ thống rất dễ bị timeout khi có nhiều thao tác đổi tên file liên tục. Do đó, hãy luôn tắt nó đi.
  • root_squash: Ánh xạ UID 0 (root) của client về tài khoản nobody. Thiết lập này ngăn chặn việc client bị chiếm quyền root có thể xóa sạch hệ thống file root của server. Chỉ sử dụng no_root_squash khi client chạy các tác vụ backup đáng tin cậy cần toàn quyền root.
  • all_squash kết hợp với anonuid / anongid: Gom mọi kết nối từ client về một user ID chỉ định duy nhất. Mô hình này cực kỳ lý tưởng cho các thư mục upload dùng chung của ứng dụng.

Tối ưu tùy chọn Mount phía Client để đạt thông lượng tối đa

Các tùy chọn mount mặc định hoạt động tốt với các tác vụ soạn thảo văn bản nhẹ nhàng. Nhưng nếu bạn chạy backup tuần tự qua đường truyền 10GbE, thiết lập mặc định sẽ bóp nghẹt tốc độ xuống dưới mức băng thông mạng rất nhiều. Việc điều chỉnh bộ đệm truyền tải và các cờ caching sẽ giải quyết triệt để vấn đề này.

Lệnh Mount cho hiệu năng cao

Dưới đây là lệnh mount mà chúng tôi đang áp dụng trên toàn bộ các node production:

sudo mount -t nfs -o proto=tcp,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noatime 192.168.1.50:/srv/nfs/shared /mnt/shared

Ý nghĩa quan trọng của các cờ này

  • rsize=1048576,wsize=1048576: Tăng kích thước chunk lên 1MB. Các giá trị mặc định cũ thường chỉ thương lượng bộ đệm 32KB hoặc 64KB. Trong thử nghiệm thực tế của chúng tôi, việc nâng bộ đệm từ 64KB lên 1MB đã giúp tốc độ truyền file dung lượng lớn qua mạng 1GbE tăng từ 48 MB/s lên thẳng mức kịch trần đường truyền là 112 MB/s.
  • noatime: Ngăn server ghi lại mốc thời gian truy cập (timestamp) mỗi khi có tiến trình đọc file. Trong các pipeline build cần đọc lặp đi lặp lại hàng nghìn file mã nguồn, cờ này giúp giảm khoảng 30% IOPS metadata của ổ đĩa.
  • hard so với soft: Tuyệt đối không dùng soft cho các phân vùng dữ liệu. Nếu mạng bị rớt, mount dạng soft sẽ ném lỗi I/O trực tiếp về ứng dụng, dễ gây hỏng cơ sở dữ liệu SQLite và các file nhị phân. Ngược lại, mount dạng hard sẽ tạm dừng I/O của tiến trình cho tới khi mạng thông trở lại, bảo vệ an toàn cho dữ liệu.
  • timeo=600 và retrans=2: Đặt khoảng thời gian chờ khôi phục là 60 giây (tính theo phần mười giây) trước khi gửi lại các gói tin chưa được xác nhận. Điều này giúp các dàn ổ đĩa NVMe và SATA đang bận rộn có đủ thời gian xử lý trong những đợt xả dữ liệu dồn dập.

Mount tự động và bền vững qua /etc/fstab

Thêm cấu hình mount vào /etc/fstab để hệ thống tự động kết nối lại sau khi khởi động. Tham số _netdev là bắt buộc: nó yêu cầu systemd hoãn việc mount cho đến khi các card mạng đã khởi động hoàn tất.

192.168.1.50:/srv/nfs/shared  /mnt/shared  nfs  nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noatime,_netdev  0  0

Kiểm tra cú pháp fstab ngay lập tức mà không cần reboot máy:

sudo umount /mnt/shared
sudo mount -a
findmnt /mnt/shared

Kinh nghiệm thực tế và xử lý sự cố

1. Siết chặt tường lửa

Lưu lượng NFS tiêu chuẩn không được mã hóa. Hãy giới hạn quyền truy cập nghiêm ngặt chỉ trong các dải IP nội bộ. Nếu dùng UFW trên Ubuntu:

sudo ufw allow from 192.168.1.0/24 to any port 2049 proto tcp
sudo ufw status numbered

Với firewalld trên RHEL hoặc AlmaLinux:

sudo firewall-cmd --permanent --zone=internal --add-service=nfs
sudo firewall-cmd --permanent --zone=internal --add-source=192.168.1.0/24
sudo firewall-cmd --reload

2. Đồng bộ UID và GID

Sự không trùng khớp giữa các User ID là nguyên nhân gây ra 90% lỗi phân quyền trên NFS. NFS truyền các mã định danh số (ID) qua mạng chứ không truyền username. Nếu user runner có UID 1002 trên client, server sẽ áp dụng quyền của bất kỳ tài khoản nào sở hữu UID 1002 ở phía nó. Bạn có hai cách để xử lý vấn đề này:

  • Tạo các cặp UID và GID trùng khớp trên cả hai hệ thống.
  • Ép tất cả lưu lượng về một user dùng chung trong /etc/exports bằng tùy chọn all_squash,anonuid=1001,anongid=1001.

3. Xử lý lỗi Stale File Handle

Nếu ổ đĩa được export bị khởi động lại hoặc đường dẫn export thay đổi, các lệnh trên client sẽ bị treo với lỗi Stale file handle. Lệnh unmount thông thường sẽ bị đơ vô thời hạn. Hãy giải phóng điểm mount bằng lazy unmount:

sudo umount -l /mnt/shared

Sau khi đã tách mount thành công, hãy mount lại bằng lệnh sudo mount -a.

4. Truy tìm điểm nghẽn bằng nfsstat

Kiểm tra xem độ trễ phát sinh do truyền lại gói tin qua mạng hay do ổ cứng server xử lý chậm bằng công cụ nfsstat:

# Thống kê phía client
nfsstat -c

# Thống kê phía server
nfsstat -s

Kiểm tra chỉ số retrans trong phần client RPC. Nếu con số này liên tục tăng trong quá trình truyền dữ liệu, switch mạng hoặc card mạng (NIC) của bạn đang bị rớt gói (drop frame).

Share: