ETCD: Lỗi 'out of range' - Nhật ký Raft có bị hỏng, cắt ngắn hay mất không?

Lỗi panic dưới đây cho thấy chỉ số commit của Raft vượt quá phạm vi nhật ký hiện tại:

panic: tocommit(12345) is out of range [lastindex(6789)]. Có phải nhật ký Raft bị hỏng, cắt bỏ hay mất không?

Lỗi thường xảy ra khi node Follower khởi động lại hoặc phục hồi, nhận được gói heartbeat từ Leader với giá trị commit lớn hơn nhưng nhật ký cục bộ đã bị xóa hoặc thiếu, dẫn đến không thể thực hiện commit. Dưới đây là phân tích nguyên nhân và các phương pháp khôi phục.

Nguyên nhân chính

  1. Nhật ký bị xóa hoặc mất Khi node gặp sự cố, dữ liệu WAL hoặc thư mục snapshot trên ổ đĩa bị xóa, sửa đổi hoặc hỏng, khiến chỉ số nhật ký cuối cùng nhỏ hơn giá trị commit trên Leader.

  2. Follower khởi động lại mà không có snapshot Nếu không có snapshot khả dụng, Follower sẽ khởi tạo chỉ số nhật ký thành 0 (hoặc bắt đầu từ snapshot cũ nhất), nhưng lại nhận được giá trị tocommit lớn hơn ngoài phạm vi nhật ký hiện tại từ Leader, dẫn đến panic.

  3. Một node gia nhập lại cluster với metadata không khớp Nếu xóa thư mục WAL của một node nhưng vẫn dùng ID thành viên cũ để gia nhập cluster, thông tin metadata (Member ID, Term) sẽ không khớp với cluster, gây lỗi tương tự.

Tình huống điển hình

  • Dgraph Zero khởi tạo lại: Sau khi xóa thư mục dữ liệu và khởi động lại, Zero node nhận được heartbeat nhưng chỉ số nhật ký cục bộ là 1 trong khi Leader là 21, gây panic.
  • Hyperledger Fabric Orderer: Khi Pods Orderer khởi động lại trên Azure, module etcdraft báo lỗi tocommit(8) is out of range [lastIndex(5)] và liên tục khởi động lại.
  • Etcd trên Kubernetes: Pod etcd ở trạng thái CrashLoopBackOff ghi log tocommit(226811495) is out of range [lastIndex(226811263)], cần dùng snapshot hoặc thêm lại thành viên.

Giải pháp khôi phục

1. Phục hồi từ snapshot (khuyến nghị)

  1. Lấy snapshot mới nhất Sử dụng lệnh etcdctl snapshot save backup_snapshot.db để xuất snapshot từ Leader.

  2. Xây dựng lại thư mục dữ liệu trên node lỗi

rm -rf /data/etcd/*
etcdctl snapshot restore backup_snapshot.db \
  --name node-recovered \
  --initial-cluster cluster1=https://node1:2380,cluster2=https://node2:2380 \
  --initial-cluster-token etcd-cluster-01 \
  --initial-advertise-peer-urls https://<node-ip>:2380
  1. Khởi động lại etcd Node sẽ tham gia cluster với trạng thái từ snapshot, tránh panic do thiếu nhật ký.

2. Xây dựng lại thành viên hoàn toàn

Nếu không có snapshot hoặc muốn khôi phục nhanh:

  1. Xóa thành viên lỗi khỏi cluster
etcdctl member remove <member-id>
  1. Xóa dữ liệu trên node lỗi
systemctl stop etcd
rm -rf /data/etcd/*
  1. Thêm lại thành viên mới
etcdctl member add node-recovered --peer-urls=https://<node-ip>:2380
  1. Khởi động etcd Node sẽ tham gia như một thành viên mới, không gây xung đột chỉ số nhật ký.

3. Kiểm tra tính toàn vẹn lưu trữ

  • Đảm bảo các volume lưu trữ (Azure Files, PVC) giữa các node không bị mất dữ liệu sau khi khởi động lại, tránh panic do mất nhật ký vật lý.
  • Trong môi trường thử nghiệm, tránh xóa tay các file WAL trong thư mục dữ liệu, nên dùng etcdctl để đảm bảo an toàn.

4. Điều chỉnh chính sách lưu trữ Raft

  • Tăng tần suất snapshot: Sử dụng tham số --auto-compaction-retention để thiết lập thời gian lưu trữ snapshot ngắn hơn.
  • Theo dõi kích thước nhật ký: Giám sát thư mục /data/etcd/member/wal để tránh xóa nhầm nhật ký do chính sách lưu trữ tự động.

Thực hành tốt để tránh lỗi

  • Định kỳ sao lưu snapshot: Sử dụng etcdctl snapshot save và lưu trữ snapshot tại vị trí an toàn.
  • Cấu hình kiểm tra sức khỏe: Trên Kubernetes, thiết lập readinessProbelivenessProbe cho etcd Pod để tự động phục hồi từ snapshot khi phát hiện panic.
  • Tự động hóa quy trình: Viết kịch bản khôi phục thành viên và đưa vào Runbook vận hành để tránh lỗi do thao tác thủ công.

Các phương pháp trên giúp bạn nhanh chóng xác định và khắc phục lỗi chỉ số nhật ký Raft vượt phạm vi, khôi phục hoạt động bình thường cho cluster.

Thẻ: Etcd Raft Kubernetes etcdctl Hyperledger Fabric

Đăng vào ngày 18 tháng 7 lúc 11:41