Giải pháp · 16/10/2026

Kubernetes Topology Spread Constraints: Dàn Pod đúng fault domain

Nhiều replica không tự động tạo high availability. Nếu scheduler đặt tất cả Pod lên cùng node hoặc cùng availability zone, một sự cố duy nhất vẫn có thể làm service biến mất. Kubernetes Topology Spread Constraints cho phép mô tả mức phân bố mong muốn theo zone, node hoặc fault domain tùy chỉnh—nhưng hiệu quả phụ thuộc vào label chính xác, selector đúng, capacity thật và lựa chọn rõ giữa “không được schedule” với “schedule dù chưa cân bằng”.

Kubernetes Topology Spread Constraints: Dàn Pod đúng fault domain

Nhiều replica không tự động tạo high availability. Nếu scheduler đặt tất cả Pod lên cùng node hoặc cùng availability zone, một sự cố duy nhất vẫn có thể làm service biến mất. Kubernetes Topology Spread Constraints cho phép mô tả mức phân bố mong muốn theo zone, node hoặc fault domain tùy chỉnh—nhưng hiệu quả phụ thuộc vào label chính xác, selector đúng, capacity thật và lựa chọn rõ giữa “không được schedule” với “schedule dù chưa cân bằng”.

Bài viết dựa trên tài liệu chính thức về Pod Topology Spread Constraints và kube-scheduler configuration. Một số field nâng cao phụ thuộc phiên bản/feature gate; hãy dùng kubectl explain và tài liệu đúng minor version của cluster.

1. Fault domain là gì?

Một topology domain là một giá trị của node label. Với topology.kubernetes.io/zone, các node cùng giá trị zone thuộc một domain; với kubernetes.io/hostname, mỗi node thường là một domain.

Mục tiêuTopology key thường dùngSự cố muốn chịu
Rải qua regiontopology.kubernetes.io/regionMất region, cần kiến trúc dữ liệu/mạng tương ứng
Rải qua zonetopology.kubernetes.io/zoneMất availability zone
Rải qua nodekubernetes.io/hostnameNode reboot, drain hoặc hỏng
Rải qua rackLabel tổ chức quản lýMất rack, nguồn hoặc switch

Label chỉ có giá trị nếu phản ánh hạ tầng thật và được gắn nhất quán. Tự đặt label zone-a cho node cùng một phòng máy không tạo khả năng chịu lỗi vật lý.

2. Manifest hai tầng zone và node

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments-api
spec:
  replicas: 6
  selector:
    matchLabels:
      app: payments-api
  template:
    metadata:
      labels:
        app: payments-api
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          minDomains: 3
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: payments-api
          matchLabelKeys:
            - pod-template-hash
          nodeAffinityPolicy: Honor
          nodeTaintsPolicy: Honor
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: payments-api
          matchLabelKeys:
            - pod-template-hash
      containers:
        - name: app
          image: registry.example.com/payments/api@sha256:<digest>
          resources:
            requests:
              cpu: 250m
              memory: 256Mi

Ví dụ này yêu cầu revision hiện tại trải qua ít nhất ba zone với skew tối đa 1; trong mỗi zone scheduler ưu tiên rải qua node nhưng vẫn có thể schedule khi capacity node không đủ cân bằng. Đây là policy minh họa: cluster hai zone không thể dùng nguyên minDomains: 3.

3. Hiểu đúng maxSkew và global minimum

Với hard constraint, scheduler so số Pod matching trong domain mục tiêu với global minimum của các domain đủ điều kiện. Nếu ba zone có số Pod 2, 2 và 1, global minimum là 1; đặt Pod tiếp vào một zone đang có 2 làm skew thành 2 và vi phạm maxSkew: 1, còn đặt vào zone có 1 tạo 2, 2, 2.

minDomains khai báo số domain tối thiểu kỳ vọng và chỉ dùng cùng DoNotSchedule. Khi số eligible domain thấp hơn giá trị này, global minimum được coi là 0, khiến scheduler không âm thầm xem một cluster thiếu zone là “đã cân bằng”. Nó có thể để Pod Pending—đúng nếu availability quan trọng hơn việc chạy bằng mọi giá.

4. DoNotSchedule hay ScheduleAnyway?

Chế độHành viKhi phù hợp
DoNotScheduleLọc node làm constraint bị vi phạmKhông chấp nhận co cụm vào ít fault domain
ScheduleAnywayVẫn schedule, ưu tiên node giảm skewCapacity/availability của workload quan trọng hơn cân bằng tuyệt đối

Hard constraint có thể biến thiếu capacity thành Pending Pod và làm rollout đứng. Soft constraint có thể làm toàn bộ replica chạy nhưng cùng zone khi cluster mất zone. Chọn theo failure policy và SLO, không theo việc manifest nào “xanh” nhanh hơn. Zone thường hard, node có thể soft là điểm khởi đầu hợp lý cho nhiều stateless service, nhưng không phải quy luật phổ quát.

5. Selector phải đếm đúng chính workload

labelSelector xác định Pod nào được đếm. Nếu selector quá rộng, workload khác làm sai skew; nếu quá hẹp hoặc không khớp label của chính Pod mới, Pod đó trở thành “ghost pod”: được đặt nhưng không làm thay đổi phép đếm như mong đợi, nên nhiều Pod có thể tiếp tục dồn vào một domain.

Kiểm tra selector của Deployment, label trong Pod template và constraint cùng một contract. Scheduler chỉ đếm matching Pod trong cùng namespace với Pod đang schedule.

6. matchLabelKeys và rolling update

matchLabelKeys lấy giá trị label từ Pod mới và ghép vào selector. Dùng pod-template-hash giúp tính skew riêng cho revision của Deployment, tránh revision cũ và mới can thiệp phép đếm theo cách khó đoán trong rollout.

Đây là lựa chọn semantics: nếu yêu cầu toàn bộ old+new Pod luôn cân bằng chung, selector/revision strategy có thể khác. Test maxSurge, maxUnavailable và rollback. Không dùng cùng một key đồng thời trong labelSelector và matchLabelKeys; xác minh support trên phiên bản cluster.

7. Eligible domain phụ thuộc node policy

Scheduler không đếm mọi zone tồn tại trên sơ đồ cloud. Eligible domain đến từ node có topology label và phù hợp với node affinity/taint policy của Pod. Field nodeAffinityPolicy và nodeTaintsPolicy cho biết các ràng buộc đó được honor hay ignore khi tính tập domain.

  • Node thiếu topologyKey bị bỏ qua và Pod không được schedule lên đó.
  • Label typo có thể làm cả node pool “biến mất” khỏi constraint.
  • Taint không có toleration có thể làm một zone không còn eligible.
  • Node affinity khóa workload vào một instance type chỉ có ở một zone.

Audit label, taint, affinity và capacity cùng nhau. Một constraint đúng cú pháp vẫn có thể bất khả thi.

8. Nhiều constraint được kết hợp bằng AND

Khi có zone constraint và hostname constraint, node ứng viên phải thỏa cả hai. Điều này mạnh hơn một danh sách preference độc lập và có thể tạo xung đột. Ví dụ zone cần nhận thêm Pod nhưng mọi node trong zone đó đều vi phạm hard hostname skew hoặc thiếu resource request.

Dùng scheduler event để tìm constraint nào chặn placement. Không sửa bằng cách tăng maxSkew ngay lập tức; kiểm tra resource, volume topology, taint, affinity, quota và image architecture trước.

9. Autoscaler không nhìn thấy domain đã scale về zero theo mọi cấu hình

Scheduler xác định topology domain từ node hiện hữu. Nếu node group của một zone đã scale về zero, domain có thể không xuất hiện để tính spread; autoscaler phải hiểu topology và node group tiềm năng mới có thể mở capacity đúng chỗ.

Test từ trạng thái zero, không chỉ scale-down từ cluster đang đủ node. Đảm bảo node template của autoscaler có label/taint tương ứng, resource request đúng và storage class có volume topology khả dụng trong zone mới.

10. Scheduler không tự tái cân bằng Pod đang chạy

Constraint được xét khi schedule Pod mới. Nếu scale-down hoặc node recovery làm phân bố lệch, scheduler không tự di chuyển Pod đang chạy chỉ để đẹp lại. Một rollout, reschedule tự nhiên hoặc Descheduler có policy phù hợp mới có thể tái cân bằng; mọi eviction phải tôn trọng disruption budget và capacity.

Đừng chạy Descheduler chỉ vì histogram không đều. Mỗi eviction làm mất cache, tạo load startup và có thể tác động SLO. Đặt ngưỡng, maintenance window và rate limit.

11. Topology spread không thay thế PDB và anti-affinity

  • Topology spread điều khiển phân bố lúc placement.
  • PodDisruptionBudget giới hạn voluntary disruption đồng thời, không ngăn node/zone hỏng.
  • Pod anti-affinity đẩy Pod khỏi nhau theo quan hệ label, có thể rất strict và tốn scheduler hơn.
  • Resource requests bảo đảm scheduler nhìn thấy nhu cầu capacity.
  • Storage topology quyết định Pod stateful có thực sự chạy được ở zone khác.

High availability cần cả health probe, nhiều endpoint, load balancer, database replication và dependency đa zone. Rải frontend không giúp nếu mọi replica dùng một database single-zone.

12. Quan sát và rollout

  1. Inventory node label theo zone/node pool và phát hiện label thiếu.
  2. Chạy soft constraint trong staging, xem placement theo revision.
  3. Thử scale replica, rolling update và node drain.
  4. Mô phỏng mất zone/capacity và node group từ zero.
  5. Canary hard constraint, alert Pending Pod và rollout stalled.
  6. Đo replica theo domain, ready endpoint theo domain và traffic/error theo zone.
kubectl get nodes -L topology.kubernetes.io/zone,kubernetes.io/hostname
kubectl get pods -n payments -l app=payments-api \
  -o wide
kubectl describe pod <pending-pod>

Checklist production

  • Topology label phản ánh fault domain thật và có trên mọi node cần dùng.
  • Pod template tự khớp labelSelector của constraint.
  • maxSkew và minDomains khớp số zone/capacity thực.
  • Hard/soft constraint được chọn theo SLO và failure policy.
  • Rolling update semantics của matchLabelKeys đã được test.
  • Node affinity, taint/toleration, volume topology và resource request tương thích.
  • Autoscaler đã test khi một domain scale về zero.
  • PDB và rollout settings không tạo deadlock với hard spread.
  • Dashboard/alert phát hiện imbalance, Pending Pod và thiếu ready endpoint theo zone.
  • Đã diễn tập drain node và mất zone, không chỉ đọc placement tĩnh.

Kết luận

Topology Spread Constraints biến ý định “đừng đặt hết trứng vào một giỏ” thành policy scheduler có thể kiểm tra. Nhưng YAML chỉ đúng khi selector đếm đúng, node label phản ánh hạ tầng, cluster có capacity và đội vận hành chấp nhận rõ lúc nào Pod nên Pending. Kết hợp spread theo zone/node với PDB, autoscaling, storage topology và diễn tập failure mới tạo high availability có thể chứng minh.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.