9 phút đọc
Insights /

Mindset

Kubernetes không làm hệ thống mặc định High Availability

Thi Duong
Thi Duong Tác giả
Đăng ngày 13/08/2026 Senior DevOps Engineer
Kubernetes không làm hệ thống mặc định High Availability

Kubernetes của bạn đã thực sự High Availability, hay chỉ đang nhìn có vẻ HA? Mấy hôm trước mình ngồi review một cụm Kubernetes của bên khác.

  • 3 replicas cho service quan trọng.
  • Có HPA.
  • Có PodDisruptionBudget.
  • Node chạy multi-AZ.
  • Ingress có nhiều replica.
  • Database dùng managed service.
  • v.v… đại khái nhìn qua thì khá đẹp

Nếu chỉ nhìn dashboard thì đúng kiểu HA rồi còn gì nữa?

Xong mình hỏi đúng câu trước đây mình được hỏi khi đi phỏng vấn senior là:

Nếu tối nay mất nguyên một AZ thì hệ thống này còn phục vụ được bao nhiêu % traffic?

Và không bác nào trong team trả lời.

Đây là cái mình thấy khá nhiều sau những năm đụng Kubernetes: Kubernetes làm cho việc chạy workload có tính resilient dễ hơn rất nhiều. Nhưng Kubernetes không tự biến architecture thành High Availability.

Thậm chí có những hệ thống nhìn bên ngoài rất cloud native, rất Kubernetes, nhưng chỉ cần chọc đúng một failure domain là nằm nguyên cụm.

1. Ba replicas chưa chắc đã là HA

Đây chắc là thứ dễ gây hiểu nhầm nhất.

Deployment:

replicas: 3

Nhìn vào thấy yên tâm hẳn =)))

Nhưng 3 pod đấy đang nằm ở đâu?

Nếu scheduler nhét cả 3 lên cùng một node thì node chết là hết. Các bác đều biết, cái này thêm anti-affinity. Ok.

Rồi nếu 3 node đó lại nằm cùng AZ? AZ có vấn đề thì vẫn hết.

Thêm topology spread constraint. Đến đây mới bắt đầu nói chuyện nghiêm túc về availability.

Mình từng gặp một hệ thống có 6 replicas. Nhưng check ra thì phần lớn workload quan trọng tập trung vào cùng một node group vì resource request của pod khá lớn, mà những node còn lại không fit được.

Nhìn bằng số replica thì: 6

Nhìn bằng failure domain thì gần như: 1

Đây là lý do mình không hỏi: Service chạy mấy pod?

Mà hỏi chính xác vào kết quả:

“Một node chết thì chuyện gì xảy ra?”

“Một AZ chết thì sao?”

“Một dependency phía dưới chết thì mấy pod kia còn có nghĩa gì?”

Hai cách hỏi nghe gần giống nhau, nhưng tư duy hệ thống khác hẳn.

2. PodDisruptionBudget cũng không phải bùa hộ mệnh

PDB là một thứ rất hay bị hiểu thành:

Có PDB thì Kubernetes sẽ giữ service của tôi sống.

Không hẳn.

PDB chủ yếu giúp kiểm soát voluntary disruption.

Ví dụ drain node khi maintenance. Nhưng node tự nhiên chết cứng, kernel panic, mất network, AZ có sự cố… thì PDB không đứng ra thương lượng với vũ trụ rằng:

“Khoan, service nhà em yêu cầu minAvailable: 2.” =)))

Hệ thống vẫn phải tự chịu failure. Và có một case khác khá vui.

Anh em set:

minAvailable: 80%

Nghe thì an toàn.

Cho đến ngày muốn drain node để upgrade cluster và phát hiện workload không evict được vì PDB quá chặt. Thế là một cơ chế được tạo ra để tăng availability lại khiến maintenance khó hơn. PDB tốt.

Nhưng nó là một constraint trong bài toán availability, không phải bản thân availability.

3. Liveness probe đôi lúc là thứ giết service nhanh nhất

Ngày mới làm Kubernetes mình cũng thích probe lắm.

  • /health.
  • /ready.
  • /live.

Nhìn rất chuẩn chỉnh. Sau này mình mới biết probe viết ngu thì Kubernetes giết app còn nhanh hơn incident.

Một case khá thực tế:

Service Java bị downstream database chậm. Thread pool bắt đầu nghẽn. Endpoint liveness cũng check database. DB trả lời chậm -> liveness fail.

Kubelet restart container. Container mới lên bắt đầu warm JVM, mở connection pool mới, connect lại DB. Trong lúc DB vốn đã quá tải. Thêm vài pod cùng restart. Connection storm. DB càng nghẽn. Thêm probe fail. Thêm restart. Một vòng lặp rất đẹp =)))

Trong case đấy Kubernetes không cứu hệ thống.

Kubernetes đang làm đúng chính xác những gì mình bảo nó làm.

Sai nằm ở việc mình không phân biệt:

  • App còn sống hay không.
  • App có sẵn sàng nhận traffic hay không.
  • Dependency phía dưới có khỏe hay không.

Một service không truy cập được database không có nghĩa process của nó phải bị kill. Nhiều trường hợp chỉ nên fail readiness để ngừng nhận traffic, chứ đừng restart app như điên. Đây là những thứ tutorial Kubernetes rất khó dạy.

Phải có hôm production tự biến thành máy restart pod thì mới nhớ lâu =)))

4. HPA đôi khi scale đúng… và vẫn làm production chết nhanh hơn

Một kiểu incident khác mình cực kỳ thích vì nó phản trực giác.

  • API latency tăng.
  • CPU tăng.
  • HPA thấy CPU vượt target.
  • Scale:
    • 10 pod -> 20 pod -> 40 pod.

Nhìn HPA: Đúng hoàn toàn. Nhưng bottleneck thật nằm ở PostgreSQL. Mỗi pod có connection pool tối đa 30 connections.

10 pod:

300 connections.

40 pod:

1.200 connections.

Anh em hiểu đoạn sau rồi đấy.

  • App đang chậm vì database bắt đầu căng.
  • Autoscaler nhìn thấy app căng nên thêm app.
  • Thêm app lại tạo thêm load lên database.
  • Database càng chậm.
  • Latency tăng.
  • Autoscaler càng scale.

Đây không phải lỗi Kubernetes. Nó chỉ chứng minh một điều:

Scale một layer không đồng nghĩa với scale cả system.

Muốn autoscaling tử tế thì ít nhất phải hiểu saturation point của dependency phía dưới. CPU 70% chưa nói được gì nhiều nếu service của anh em I/O bound. Queue consumer cũng vậy. Scale consumer từ 10 lên 100 mà database chỉ chịu nổi concurrency 30 thì chẳng qua anh em chuyển bottleneck từ Kafka sang DB.

Kubernetes làm chuyện scale quá dễ nên đôi khi nó khiến engineer quên mất câu hỏi quan trọng hơn: Thứ gì thực sự đang giới hạn throughput?

5. StatefulSet không biến database thành distributed database

Cái này mình từng tranh luận khá nhiều.

Có thể có người bảo:

Database chạy StatefulSet, PVC đầy đủ rồi mà.

Nhưng PVC giúp data của pod tồn tại qua việc pod reschedule.

Nó không tự giải quyết:

  • replication
  • leader election
  • consistency
  • split brain
  • backup
  • restore
  • replication lag
  • corruption
  • failover correctness

Anh em chạy một PostgreSQL pod trên StatefulSet + PVC vẫn có thể đang vận hành một single point of failure rất đẹp mắt bằng YAML.

Node chết, pod được schedule lại. Volume attach lại. Database lên lại.

Đấy là recovery. Không nhất thiết là HA.

HA thường đòi hỏi hệ thống vẫn phục vụ được hoặc degradation nằm trong giới hạn chấp nhận được trong lúc failure đang xảy ra, chứ không phải:

“Nó chết xong 5 phút sau Kubernetes dựng lại được.”

Hai chuyện khác nhau hoàn toàn.

6. Service mesh cũng không cứu được dependency đang chết

Có Istio rồi. Retry rồi. Timeout rồi. Circuit breaker rồi. Rất enterprise. Nhưng retry là một trong những thứ mình thấy gây incident thứ cấp khá nhiều.

Ví dụ downstream đang chịu được 1.000 request/s. Nó bắt đầu chậm. Upstream timeout và retry 2 lần. Một request của user bây giờ có thể tạo thành 3 request phía dưới. Downstream vốn đang hấp hối lại được tặng thêm traffic.

Retry storm.

Mesh làm retry rất dễ.

Nhưng “có retry” và “retry đúng” là hai chuyện khác nhau.

Phải nghĩ tới:

  • retry budget
  • exponential backoff
  • jitter
  • idempotency
  • timeout hierarchy
  • deadline propagation

Không thì service mesh chỉ giúp anh em tự DDoS chính hệ thống mình chuyên nghiệp hơn.

7. Cái mình hay hỏi khi review Kubernetes không còn là cluster có gì?

Nếu ngày xưa khi mới dùng hay hỏi:

  • Có Prometheus chưa?
  • Có HPA chưa?
  • Có PDB chưa?
  • Ingress dùng gì?
  • Storage class gì?

Khi trải nghiệm mình thường hỏi.

  • Nếu node này mất ngay bây giờ thì sao?
  • Nếu cả AZ này biến mất thì workload nào không lên được?
  • Nếu DNS trong cluster latency thêm 300ms thì biểu hiện đầu tiên nằm ở đâu?
  • Nếu database chỉ còn 30% capacity thì autoscaler của app sẽ cứu hay bỏ nó?
  • Nếu deploy version mới nhưng migration DB không backward-compatible thì rollback image có thật sự rollback được không?
  • Nếu secret rotate nhưng một nửa pod chưa reload credential thì chuyện gì xảy ra?
  • Nếu control plane tạm thời unavailable nhưng worker node vẫn chạy thì business còn hoạt động được bao lâu?

Theo mình đây mới là những câu engineer vận hành Kubernetes nên quan tâm.

Không phải vì YAML không quan trọng. Mà vì YAML chỉ mô tả desired state.

Production lại sống trong một thế giới đầy undesired state.

8. Kubernetes mạnh nhất ở chỗ nào?

Viết cũng dài mà nghe cứ lủng củng nhỉ, lần đầu chia sẻ =))

Sau tất cả những gì vừa nói, mình vẫn thích Kubernetes. Và nhiều hệ thống mình vẫn chọn Kubernetes. Vì nếu team đủ khả năng vận hành nó, Kubernetes cho mình một bộ primitive cực mạnh:

  • Scheduling.
  • Self-healing.
  • Service discovery.
  • Declarative deployment.
  • Resource isolation.
  • Rollout.
  • Autoscaling.
  • Policy.
  • Extensibility.

Nhưng chính vì nó cung cấp quá nhiều primitive nên engineer rất dễ nhầm:

“Tôi đã bật các cơ chế HA”

với:

“Hệ thống của tôi HA.”

Hai câu này cách nhau khá nhiều luôn.

Chốt lại

Nếu ngày mai có bạn bảo mình:

“System em Kubernetes rồi nên HA anh ạ.”

Mình chắc vẫn hỏi lại:

“HA trước failure nào?”

  • Node failure?
  • AZ failure?
  • Application failure?
  • Database failure?
  • Network partition?
  • Dependency degradation?
  • Human error?
  • Bad deployment?
  • Data corruption?

Bởi vì HA không phải một thuộc tính bật bằng Helm values. Nó là kết quả của việc anh em xác định failure domain, thiết kế redundancy, hiểu dependency, test failover và chấp nhận những trade-off cụ thể.

Kubernetes giúp mình thực hiện những thứ đó tốt hơn. Nhưng nó không suy nghĩ hộ mình.

Và đôi khi hệ thống Kubernetes nguy hiểm nhất lại chính là hệ thống nhìn dashboard xanh lè, 3 replicas đầy đủ, HPA chạy ngon…

…nhưng chưa ai trong team từng thử tắt một node xem chuyện gì xảy ra =)))

Tiện có anh em hỏi trả lời vào đây luôn, nâng trình Kubernetes thì thật sự mình rất recommend anh em học CKACKS của KodeKloud và thi lấy chứng chỉ CNCF.

Chia sẻ bài viết

Theo dõi
Thông báo của
0 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Đã sao chép liên kết vào bộ nhớ tạm!