Leader Election, Addon và Node Autoscaling
Cụm có ba control plane (Bài 8) cho cao sẵn sàng. apiserver thì cả ba cùng phục vụ — request nào tới máy nào cũng được. Nhưng controller-manager và scheduler khác: nếu cả ba cùng hoạt động, ba scheduler sẽ cùng gán một pod vào ba node, ba controller-manager cùng tạo pod cho một ReplicaSet. Phải có cơ chế đảm bảo chỉ một bản hoạt động tại một thời điểm, hai bản kia chờ. Đó là leader election. Bài này xem nó, chứng minh failover thật, rồi khép Part XIII bằng addon và node autoscaling.
Leader election qua Lease
Cơ chế dựa trên một object Lease trong kube-system: bản nào giữ lease thì là leader, hai bản kia liên tục thử giành nhưng thất bại chừng nào lease còn hiệu lực. Xem ai đang giữ:
kubectl -n kube-system get lease kube-controller-manager kube-scheduler
NAME HOLDER AGE
kube-controller-manager controller-0_b27ab883-b893-434e-9feb-6023a9998b07 10h
kube-scheduler controller-0_0b8e4b14-44cc-4c01-9a8f-8b4e8b07b647 10h
Cả hai leader đang ở controller-0. Leader phải gia hạn lease đều đặn; nếu nó chết và ngừng gia hạn, lease hết hạn và một bản khác giành được. Mỗi instance mang một định danh ngẫu nhiên (phần sau dấu _) để phân biệt.
Chứng minh failover
Hạ leader xuống và xem chuyện gì xảy ra. Dừng controller-manager trên controller-0:
ssh controller-0 'sudo systemctl stop kube-controller-manager'
# chờ lease hết hạn + bầu lại (~15s)
kubectl -n kube-system get lease kube-controller-manager -o jsonpath='{.spec.holderIdentity}'
controller-1_4076e3a4-c151-444a-b724-fffffb24544e
Leader chuyển sang controller-1 — không cần can thiệp gì. controller-0 ngừng gia hạn, lease hết hạn sau vài giây, và controller-1 (vốn đang thử giành liên tục) chiếm được rồi bắt đầu làm việc của controller-manager. Đây là HA thật: mất node giữ leader thì một node khác lên thay trong khoảng bằng thời hạn lease, cụm không gián đoạn điều phối. Khởi động lại controller-0:
ssh controller-0 'sudo systemctl start kube-controller-manager'
Nó lên lại nhưng không đòi lại leadership — controller-1 đang giữ lease hợp lệ, nên controller-0 vào vai chờ. Leader chỉ đổi khi leader hiện tại ngừng gia hạn; không có chuyện tranh giành qua lại khi cả hai đều khỏe. (Lý do scheduler ở Bài 34 ghi holder=controller-0 cũng là cơ chế này.)
Addon: cụm tự dựng quản tay
"Addon" là những thành phần chạy trong cụm nhưng thuộc hạ tầng chứ không phải ứng dụng người dùng: CoreDNS (Bài 15), Cilium (Bài 46), metrics-server (Bài 39). Câu hỏi vận hành: ai cài và cập nhật chúng?
Cụm dựng từ đầu này quản addon bằng tay — ta kubectl apply manifest hoặc helm install, và tự chịu trách nhiệm nâng cấp. Không có thành phần nào tự đồng bộ chúng. Một số bản phân phối (kubeadm, hay các cụm managed) có "addon manager" tự áp lại manifest trong một thư mục, nhưng đó là tiện ích thêm chứ không phải lõi Kubernetes. Đánh đổi giống mọi thứ trong series này: làm tay thì kiểm soát từng chi tiết và hiểu rõ cái gì chạy, nhưng phải tự nhớ cập nhật — không có ai vá CoreDNS hộ khi có CVE.
Node autoscaling
Bài 39 đã có HPA — thêm pod khi tải cao. Nhưng nếu thêm pod mà không node nào còn chỗ, pod mới kẹt Pending (như Bài 34). Node autoscaling lấp chỗ đó: tự thêm node khi có pod không xếp được, và bớt node khi thừa.
Cụm này chạy đúng sáu EC2 cố định, không có autoscaler, nên phần này là khung chứ không demo được:
pod Pending (không node nào đủ chỗ)
│ watch
▼
Cluster Autoscaler ──► gọi API cloud (AWS ASG...) ──► thêm EC2 ──► node mới Ready
│ │
└────────── ngược lại: node ít tải lâu ──► drain + bớt EC2 ◄────────┘
Hai cách tiếp cận chính: Cluster Autoscaler theo dõi pod Pending, khi thấy pod kẹt vì thiếu tài nguyên thì phóng to một node group của cloud (AWS Auto Scaling Group, GCP MIG...), và thu nhỏ khi node rảnh lâu (drain rồi xóa — đúng quy trình Bài 63). Karpenter (gốc AWS, nay rộng hơn) làm tinh hơn: thay vì node group định sẵn, nó chọn loại instance hợp nhất với pod đang chờ và phóng thẳng. Cả hai đều là thành phần ngoài lõi Kubernetes, chạy như Deployment trong cụm, cần quyền gọi API cloud. Trên cụm EC2 tự dựng cố định, ta không bật — nhưng nguyên lý nối thẳng với scheduling (Bài 34) và drain (Bài 63): autoscaler chỉ là vòng lặp đọc pod Pending và tác động lên hạ tầng cloud.
🧹 Dọn dẹp
Bài này chỉ đọc Lease và làm một lần failover có kiểm soát (đã khởi động lại controller-manager trên controller-0; leader giờ là controller-1, hoàn toàn bình thường). Không tạo gì. Lệnh dùng trong bài ở github.com/nghiadaulau/kubernetes-from-scratch, thư mục 67-leader-election.
Tổng kết
Trong control plane HA, apiserver chạy song song cả ba, nhưng controller-manager và scheduler dùng leader election để chỉ một bản hoạt động — tránh ba bản giẫm chân nhau. Cơ chế là một Lease trong kube-system: bản giữ lease là leader và phải gia hạn đều; ta chứng minh failover bằng cách dừng controller-manager trên controller-0, và sau vài giây leader chuyển sang controller-1 mà không cần can thiệp, rồi controller-0 khởi động lại vào vai chờ (không tranh lại). Addon (CoreDNS, Cilium, metrics-server) trên cụm tự dựng được quản tay qua apply/helm — kiểm soát hoàn toàn, đổi lại phải tự nhớ cập nhật. Node autoscaling (Cluster Autoscaler theo node group, hay Karpenter chọn instance trực tiếp) tự thêm node khi pod Pending vì thiếu chỗ và bớt khi rảnh, là thành phần ngoài lõi nối scheduling (Bài 34) với drain (Bài 63); cụm EC2 cố định này không bật.
Part XIII khép lại — cụm giờ được sao lưu (62), biết nâng cấp (63), quản tài nguyên node (64), và quan sát được (65–67). Bài 68 mở Part XIV, dùng cụm đầy đủ này thử những tính năng vừa graduate ở chính phiên bản v1.36 nó đang chạy: admission bằng CEL, in-place pod resize, storage mới, và quan sát/bảo mật kubelet.