The feedback loops behind Kubernetes

Bài tóm tắt PlanetScale 2026 3. Quy mô lớn Độ khó: Khó

PlanetScale · 2026 · 3. Quy mô lớn · Độ khó: Khó — bài gốc

Bài giải thích của một kỹ sư PlanetScale viết operator cho Postgres/MySQL; nửa đầu là ví dụ dựng dần, nửa sau là cách operator của họ làm. Nhận định là theo tác giả.

Bối cảnh

  • Tác giả mở bằng việc chạy Postgres bằng tay: chọn node, gắn EBS, format, mount; dựng 1 primary + 2 replica trên ba máy; sửa /etc/hosts khi IP đổi; đổi tham số qua ssh. Mỗi bước có thể hỏng giữa chừng. Để khỏi bị gọi đêm, viết một script lặp vài giây một lần, nhìn từng node và sửa cái sai.
  • Script đó đã là một feedback controller (như thermostat, cruise control). Làm cứng tiếp thì cần kho trạng thái mong muốn, watch thay vì poll, work queue, retry, leader election: tức là dựng lại Kubernetes.

Cơ chế (theo bài)

  • Edge-triggered notification, level-triggered logic. Hành động theo sự kiện ("replica tăng 2") là mong manh: controller tắt 30 giây là mất sự kiện và lệch mãi; nhận hai lần thì làm hai lần (1 → 5 replica thay vì 3); thứ tự lộn thì xử lý lộn. Level-triggered đọc trạng thái hiện tại ("đang có 1, cần 3") nên bỏ lỡ một vòng thì vòng sau bù, chạy hai lần vẫn ra một kết quả. Kubernetes dùng sự kiện chỉ để biết khi nào xem lại; Reconcile chỉ nhận một key, framework cố ý làm khó việc viết logic theo sự kiện. Vì vậy controller crash 10 phút rồi chạy lại vẫn hội tụ, không cần code phục hồi.
  • spec và status là setpoint và giá trị đo. Status ghi cuối cùng, sau khi đã hành động và quan sát lại; trong operator của họ không được ghi status giữa chừng.
  • Tự lành nhờ ownerReference: con trỏ về cha vừa để dọn rác theo tầng vừa để biến thay đổi của con thành yêu cầu reconcile cho cha. Node chết → Pod mất (sự kiện) → cha reconcile, thấy thiếu, tạo Pod mới → scheduler thấy Pod chưa có node → kubelet khởi động. Nhiều vòng chồng nhau, không ai điều phối tổng: cascade control (đầu ra của vòng ngoài là setpoint của vòng trong; operator ghi spec của PVC, CSI hội tụ theo spec đó).
  • Quan sát trong operator thật: cache của Kubernetes (Pod, PVC, PV, Node, ConfigMap); cấu hình thực sự server đã nạp (không phải cái vừa ghi) để phát hiện drift; trạng thái tự báo của database (vai trò, độ trễ follower, có nhận ghi); một collector nền cho tín hiệu đắt hay bị rate limit (dung lượng đĩa, thao tác volume đang chờ cooldown). Gom một snapshot ở đầu vòng, mọi quyết định đọc từ đó, không hỏi lại giữa chừng (nếu không, đầu vòng thấy leader, giữa vòng thấy replica). Lỗi một phần (không nối được DB) là một sự thật được ghi vào status, không phải lý do bỏ vòng.
  • Sự kiện không chỉ từ API server: reconcile hàng nghìn database mỗi vài giây chỉ để thấy "vẫn 40%" là phí CPU; đó là cái giá thật của level-triggered. Collector poll metric chậm, giữ giá trị cuối và chỉ phát sự kiện khi vượt ngưỡng (ví dụ 80%), đưa vào cùng work queue. Vì sự kiện có thể mất, có resyncer xếp mọi object vào reconcile khoảng mỗi phút; RequeueAfter để chờ thao tác chậm bên ngoài mà không giữ worker.
  • Chu kỳ lấy mẫu: nhanh hơn tốc độ thay đổi của thứ đang theo dõi nhưng không nhanh hơn tốc độ nó phản ứng được. Coalescing delay gộp bão sự kiện của một object thành một lần reconcile. Leader election: chỉ một bản operator chạy vòng; hai controller cùng ghi một object không "tin cậy hơn" mà chỉ xung đột và requeue.

Giới hạn (theo bài)

  • Eventual consistency và tách đọc cache/ghi API: object vừa tạo có thể chưa hiện với chính bên tạo ra nó. Khi lỗi, phải gỡ đồng thời object Kubernetes, trạng thái DB, metric, thao tác volume, có khi cả cloud.
  • Mô hình khai báo gặp khó với thao tác vốn mệnh lệnh và có trạng thái: failover, nâng major version, migrate dữ liệu; phải biến hành động chặn, không idempotent thành idempotent.
  • "Operator không gỡ bỏ độ phức tạp, chúng dời nó vào code mà ai đó phải hiểu." Không cần quy mô, chấp nhận mất availability thì có thể không cần bộ máy này.

Bài học cho SWE

  • Viết automation như vòng điều khiển: đọc trạng thái hiện tại, so với mong muốn, làm bước tiếp theo, lặp lại; sự kiện chỉ để đánh thức (Tự động hoá vận hành và auto-remediation).
  • Quan sát một lần, quyết định trên cùng snapshot; ghi kết quả đo sau cùng.
  • Tín hiệu đắt thì đưa về dạng sự kiện qua ngưỡng, kèm resync định kỳ làm lưới an toàn.
  • Nền tảng tốt là nhiều vòng nhỏ cùng đọc ghi object chung, mỗi vòng lo một tầng (Nền tảng nội bộ cho service (đường ray chung)).

Liên quan