Skip to content

kubelet & containerd Configuration cho Production GKE

Vì sao chủ đề này quan trọng

Nếu node pool là “vỏ hạ tầng”, thì kubelet và containerd là “hành vi thực tế” của node. Hai cluster giống hệt về số node nhưng khác cấu hình kubelet/containerd có thể cho kết quả độ ổn định hoàn toàn khác nhau: một bên êm, một bên eviction và image pull timeout liên tục.

GKE cung cấp Node System Configuration để tùy chỉnh một số thông số node-level và hỗ trợ cấu hình containerd theo hướng được quản lý thay vì hack thủ công trên từng node (Node system configuration, Customize containerd configuration).

Internal model

kubelet là bộ điều khiển cục bộ của node

Kubelet chịu trách nhiệm:

  • Duy trì pod spec tại node.
  • Báo node status/conditions.
  • Quản lý eviction khi áp lực tài nguyên.
  • Phối hợp graceful shutdown theo policy hệ thống.

Cấu hình kubelet tác động trực tiếp tới tính ổn định workload hơn nhiều tham số “đẹp” ở deployment level.

containerd là đường dữ liệu image/runtime

Containerd xử lý:

  • Pull image từ registry.
  • Xác thực TLS/CA.
  • Quản lý snapshot/layer runtime.
  • Khởi tạo container theo CRI.

Bất kỳ nghẽn hoặc trust issue ở containerd đều biểu hiện thành pod pending/image pull backoff.

kubelet configuration: điểm quyết định production

1) Eviction và node pressure behavior

Tuning eviction thresholds quyết định node phản ứng sớm hay muộn khi thiếu tài nguyên. Quá sớm gây churn, quá muộn gây sập node. Không có tham số “chuẩn cho mọi nơi”; bạn cần cấu hình theo class workload và profile node.

2) Image garbage collection

Nếu image GC không phù hợp với tần suất deploy, disk pressure sẽ xuất hiện dù tài nguyên khác còn dồi dào. Đây là root cause thường gặp ở microservices có release cadence cao.

3) cgroup v2 migration

GKE đã có lộ trình chuyển dần sang cgroup v2 cho Linux nodes; tài liệu chính thức nêu rõ yêu cầu tương thích và cách migrate (Migrate nodes to Linux cgroupv2).

Từ góc nhìn vận hành, cgroup v2 mang lại mô hình quản lý tài nguyên hiện đại hơn, nhưng rủi ro chính là ecosystem compatibility:

  • eBPF/security agents cũ.
  • Runtime hooks/custom scripts dựa trên cgroup v1 path.
  • Monitoring dashboards hard-code đường dẫn cgroup cũ.

Chiến lược an toàn:

  1. Canary pool với cgroup v2.
  2. Chạy workload đại diện + soak dài.
  3. Chỉ mở rộng khi toàn bộ agent/phụ trợ tương thích.

4) Graceful node shutdown ở kubelet

Kubernetes hỗ trợ shutdownGracePeriodshutdownGracePeriodCriticalPods để chia ngân sách dừng pod thường và pod critical khi node shutdown (Node shutdowns).

Nếu giá trị này không tương thích với thời gian app cần để flush state, bạn sẽ thấy mất dữ liệu logic khi preemption/reboot dù hệ thống “đã graceful theo config”.

containerd configuration: registry mirrors, custom TLS, image pulling

1) Registry mirrors cho giảm latency và tăng resiliency

Dùng mirror gần cluster giúp giảm thời gian pull và giảm phụ thuộc một endpoint registry duy nhất. Nhưng mirror phải đồng bộ chính sách bảo mật và versioning; mirror stale còn nguy hiểm hơn không mirror.

2) Custom TLS/CA cho private registry

GKE hỗ trợ cấu hình private registry với CA tùy chỉnh thông qua cơ chế quản lý chính thống (ví dụ Secret Manager + runtime config), thay vì copy cert thủ công vào node (Private registries with custom CA, ContainerdConfig reference).

Lợi ích:

  • Không cần daemonset đặc quyền để sửa file hệ thống.
  • Giảm drift giữa nodes.
  • Rollback cấu hình rõ ràng theo IaC.

3) Pull behavior và anti-pattern

Anti-pattern phổ biến:

  • Dùng :latest cho production làm cache/pull không dự đoán được.
  • Không phân biệt image critical và image phụ.
  • Rollout ồ ạt làm “pull storm”.

Khuyến nghị:

  • Image tag bất biến theo digest.
  • Pre-pull chiến lược cho release lớn.
  • Giới hạn concurrency rollout theo năng lực pull của node pool.

Production architecture patterns

Pattern A: Runtime baseline policy theo pool class

Thiết lập baseline khác nhau cho:

  • Pool critical API (eviction bảo thủ, disk profile cao).
  • Pool batch (tối ưu hiệu suất/chi phí, chấp nhận churn cao hơn).
  • Pool platform/system (ưu tiên ổn định agent).

Mục tiêu là tránh “one-size-fits-all” với kubelet/containerd.

Pattern B: Config as code + canary runtime

Mọi thay đổi node system config/containerd:

  1. Commit vào repo IaC.
  2. Rollout pool canary.
  3. Thu thập chỉ số lỗi pull, pod startup latency, eviction rate.
  4. Promote dần sang pool còn lại.

Pattern C: Registry trust domain segmentation

  • Registry nội bộ cho artifact production.
  • Registry ngoài chỉ cho base images đã quét.
  • Containerd trust config tách rõ domain và CA.

Giảm nguy cơ supply chain incident do pull từ nguồn không kiểm soát.

Real-world scenarios

Scenario 1: Pull storm sau incident recovery

Hệ thống vừa mất một nhóm node, autoscaler tạo lại nhiều node cùng lúc, hàng nghìn pod pull image đồng thời. Containerd queue tắc, pod readiness chậm, API timeout dây chuyền.

Cách xử lý:

  • Dùng registry mirror gần vùng chạy.
  • Tối ưu image layers và kích thước.
  • Điều chỉnh rollout/autoscaling burst hợp lý.

Scenario 2: Migrate cgroup v2 làm hỏng observability agents

Nguyên nhân:

  • Agent cũ phụ thuộc đường dẫn cgroup v1.
  • Rollout trực tiếp toàn cụm.

Cách xử lý:

  • Canary trước.
  • Upgrade agent đồng bộ.
  • Có kế hoạch rollback pool nhanh.

Scenario 3: Chứng chỉ private registry hết hạn âm thầm

Nguyên nhân:

  • CA rotation không đi qua quy trình chuẩn.
  • Node mới không trust chain mới.

Kết quả:

  • Pod mới không pull được image.
  • Sự cố chỉ lộ khi scale/upgrade.

Cách xử lý:

  • Quản lý cert qua Secret Manager.
  • Lập lịch kiểm tra hết hạn và drill rotation định kỳ.

Common mistakes / anti-patterns

  1. Tuning kubelet theo cảm tính từ blog không bám docs/version thực tế
  2. SSH sửa containerd config trên từng node
  3. Migrate cgroup v2 đồng loạt không canary
  4. Không đo pod startup latency sau mỗi thay đổi runtime
  5. Coi image pull lỗi là vấn đề ứng dụng thay vì hạ tầng runtime

GCP-native implementation guidance

Cập nhật node system configuration cho node pool

bash
gcloud container node-pools update <node-pool> \
  --cluster=<cluster-name> \
  --region=<region> \
  --system-config-from-file=./node-system-config.yaml

Ví dụ node-system-config.yaml (minh họa):

yaml
kubeletConfig:
  cpuManagerPolicy: "none"
  imageGcHighThresholdPercent: 85
  imageGcLowThresholdPercent: 70
linuxNodeConfig:
  cgroupMode: CGROUP_MODE_V2

Cấu hình containerd với registry hosts

bash
gcloud container clusters update <cluster-name> \
  --region=<region> \
  --containerd-config-from-file=./containerd-config.yaml

Ví dụ containerd-config.yaml (minh họa):

yaml
registryHosts:
  - server: registry.internal.example
    hostConfig:
      capabilities: ["pull", "resolve"]
      caCertSecretRef: projects/<project-id>/secrets/<secret-name>/versions/latest

Quan sát runtime errors

bash
kubectl get events -A --sort-by=.lastTimestamp | grep -Ei "Failed|Evict|ImagePull|BackOff|NodeNotReady"
kubectl describe pod <pod-name> -n <namespace>

Decision checklist trước khi thay kubelet/containerd

  • Đã có canary pool và tiêu chí pass/fail rõ ràng?
  • Đã xác minh tương thích cgroup v2 với toàn bộ agent chưa?
  • Đã chuẩn hóa registry trust và CA rotation runbook chưa?
  • Đã có rollback strategy ở node pool level chưa?
  • Đã đo được tác động lên startup latency/p95 error chưa?

Kết nối với Well-Architected

  • Operational excellence: chuẩn hóa cấu hình runtime thành policy có versioning, tránh thao tác tay trên node (Operational excellence).
  • Reliability: thay đổi runtime phải có rollout chiến lược và rollback nhanh để bảo toàn SLO (Reliability).

References

Phụ lục chuyên sâu: chuẩn hóa runtime policy ở quy mô nhiều cụm

Mục tiêu của runtime governance

Khi số cluster tăng, rủi ro lớn nhất không phải thiếu tính năng mà là drift cấu hình. Hai cluster cùng chạy một workload nhưng kubelet/containerd khác nhau sẽ tạo lỗi khó tái hiện. Runtime governance giúp biến cấu hình node thành hợp đồng rõ ràng giữa platform team và ứng dụng.

Cấu trúc policy đề xuất

  1. Global baseline

    • Quy tắc chung mọi cluster: cgroup mode mục tiêu, chuẩn registry trust, ngưỡng tối thiểu bảo mật.
  2. Environment overlays

    • Staging có thể nới lỏng một số ngưỡng để thử nghiệm.
    • Production giữ cấu hình ổn định hơn.
  3. Pool-class overrides

    • Pool API critical khác pool batch.
    • Pool system agents khác pool business services.

Cách phân tầng này giúp giảm copy-paste config và kiểm soát thay đổi tốt hơn.

Chu trình thay đổi kubelet/containerd an toàn

  • Bước 1: RFC kỹ thuật nêu rõ lý do thay đổi, rủi ro và kế hoạch rollback.
  • Bước 2: Thử nghiệm canary trên pool nhỏ.
  • Bước 3: Soak qua ít nhất một chu kỳ tải đỉnh.
  • Bước 4: Mở rộng theo ring từ ít rủi ro đến cao rủi ro.
  • Bước 5: Post-change review với số liệu cụ thể.

Không nên thay đổi runtime chỉ vì “thấy best practice trên mạng”. Mọi thay đổi phải gắn bối cảnh workload thực tế.

Bộ chỉ số bắt buộc sau mỗi thay đổi runtime

  • Pod startup latency p95/p99.
  • Image pull latency và failure rate.
  • Node eviction rate theo reason.
  • Node NotReady occurrences.
  • CPU throttling và memory reclaim signals.

Nếu không đo các chỉ số này, bạn không thể kết luận thay đổi runtime tốt hơn hay xấu đi.

cgroup v2 migration playbook chi tiết

  1. Inventory dependencies

    • Liệt kê agents/kernel hooks cần cgroup paths.
  2. Compatibility test

    • Chạy smoke tests trên canary pool.
  3. Observability alignment

    • Cập nhật dashboard và alert query cho cgroup v2 metrics.
  4. Progressive rollout

    • Tăng dần phạm vi, theo dõi regression.
  5. Fallback readiness

    • Nếu phiên bản GKE và chính sách cho phép, chuẩn bị đường quay lại tạm thời.

Điểm quan trọng: migration thành công không chỉ là node lên được, mà là toàn bộ hệ sinh thái vận hành vẫn hoạt động đúng.

Registry trust model cho supply chain security

Nên tách rõ:

  • Registry nội bộ đã kiểm soát artifact.
  • Registry upstream cho base image.
  • Chính sách CA và xác thực cho từng domain.

Containerd config phải phản ánh mô hình tin cậy này, tránh việc mọi node tin mọi registry chỉ để “pull cho dễ”.

Incident patterns liên quan containerd

Pattern 1: TLS mismatch sau rotation

  • Node cũ pull được, node mới pull lỗi.
  • Nguyên nhân: chain CA mới chưa đồng bộ cấu hình runtime.

Pattern 2: Mirror endpoint chậm

  • Mirror hoạt động nhưng độ trễ cao làm startup chậm diện rộng.
  • Cần health check định kỳ cho mirror path.

Pattern 3: Registry rate limit

  • Rollout lớn vượt ngưỡng pull từ registry ngoài.
  • Cần cache/mirror và điều chỉnh rollout concurrency.

Kết hợp kubelet policy với workload contracts

Platform team nên công bố “runtime contracts” cho đội ứng dụng:

  • Startup budget kỳ vọng.
  • Termination budget kỳ vọng.
  • Resource request/limit tối thiểu theo loại service.

Khi hợp đồng rõ, ứng dụng và hạ tầng có thể phối hợp để giảm eviction và restart bất ngờ.

Vận hành theo mô hình SRE

  • Định nghĩa SLO cho “node runtime health”.
  • Dùng error budget để quyết định tốc độ rollout thay đổi runtime.
  • Nếu error budget cạn, dừng thay đổi mới và tập trung ổn định.

Đây là cách gắn runtime engineering với mục tiêu dịch vụ, thay vì coi runtime chỉ là bài toán nội bộ hạ tầng.

Anti-pattern tổ chức cần tránh

  • Một đội tự thay runtime config cho tất cả cluster mà không có review chéo.
  • Không có ownership rõ ràng cho file cấu hình node system/containerd.
  • Không lưu lịch sử thay đổi và kết quả sau thay đổi.

Hậu quả là mọi incident đều mất thời gian “đi tìm ai đã đổi gì”.

Khuyến nghị chuẩn hóa tài liệu nội bộ

Mỗi thay đổi runtime nên có:

  • Mô tả thay đổi.
  • Cluster/pool bị ảnh hưởng.
  • Lý do business/technical.
  • Kế hoạch rollback.
  • Chỉ số theo dõi thành công.
  • Kết quả thực tế sau rollout.

Chuẩn tài liệu này giúp giảm phụ thuộc vào trí nhớ cá nhân.

Checklist trước mùa cao điểm

  • Đóng băng thay đổi runtime không khẩn cấp.
  • Kiểm tra hạn dùng cert cho registry trust chain.
  • Xác nhận mirror và fallback path hoạt động.
  • Diễn tập incident image pull failures.
  • Đảm bảo dashboard runtime có cảnh báo đúng ngưỡng.

Bài học thực chiến

  • Runtime issues hiếm khi “kêu to” ngay từ đầu; thường tích lũy thành lỗi lớn vào thời điểm tệ nhất.
  • Kubelet/containerd tuning phải được xem là năng lực nền tảng, không phải thao tác sửa lỗi ad-hoc.
  • Chuẩn hóa policy và rollout có kiểm soát là cách duy nhất để giữ ổn định dài hạn.

References bổ sung

FAQ thực chiến

Có nên tùy chỉnh thật nhiều kubelet flags để tối ưu tối đa?

Không nên bắt đầu theo hướng đó. Chỉ thay các tham số có lý do rõ ràng và đo được tác động. Tuning quá mức làm tăng độ phức tạp vận hành và khó nâng cấp phiên bản.

Vì sao cần tránh chỉnh containerd trực tiếp trên từng node?

Vì chỉnh tay tạo drift, khó audit, khó rollback đồng bộ và thường bị mất khi node thay thế. Nên dùng cơ chế cấu hình được GKE hỗ trợ chính thức để giữ tính tái lập.

cgroup v2 migration thất bại thường do đâu?

Thường do dependency ecosystem: agent quan sát, bảo mật, plugin runtime, script nội bộ chưa tương thích. Lỗi hiếm khi nằm ở cgroup v2 tự thân, mà nằm ở lớp phụ trợ chưa cập nhật.

Private registry đã nội bộ rồi, có cần quan tâm TLS/CA nghiêm ngặt không?

Có. Nội bộ không đồng nghĩa an toàn tuyệt đối. Trust chain rõ ràng giúp giảm rủi ro supply chain và tránh outage do cert rotation không kiểm soát.

Checklist thay đổi runtime không gián đoạn

Trước thay đổi

  • Mô tả rõ mục tiêu kỹ thuật và KPI kỳ vọng.
  • Liệt kê phạm vi cluster/pool bị ảnh hưởng.
  • Chuẩn bị rollback plan theo node pool.
  • Kiểm tra tương thích của agents/sidecars/runtime hooks.

Trong thay đổi

  • Chỉ rollout trên canary pool đầu tiên.
  • Theo dõi pod startup, image pull, eviction, NotReady.
  • Đặt ngưỡng dừng rõ ràng theo error budget.
  • Không chạy song song với thay đổi hạ tầng lớn khác.

Sau thay đổi

  • So sánh KPI trước/sau theo cùng khung giờ tải.
  • Đóng thay đổi nếu không có regression trong khoảng soak.
  • Cập nhật baseline runtime policy và tài liệu vận hành.

Kỷ luật vận hành quan trọng nhất

Không merge thay đổi runtime chỉ dựa trên “test pass”. Runtime thay đổi ở cấp nền tảng cần được xác thực bằng hành vi production thực tế, có số liệu và có người chịu trách nhiệm rõ ràng.

Phụ lục mô hình kiểm soát thay đổi runtime theo rủi ro

Phân loại thay đổi runtime theo 3 mức:

  • Mức thấp: thay đổi không ảnh hưởng path xử lý chính (ví dụ điều chỉnh logging nhỏ).
  • Mức trung bình: thay đổi ngưỡng kubelet, garbage collection, image behavior.
  • Mức cao: thay đổi cgroup mode, trust model registry, runtime core.

Với mức trung bình và cao, bắt buộc:

  • Canary rollout.
  • Soak period.
  • Approval đa vai trò (platform + SRE + security khi cần).
  • Tiêu chí rollback định lượng.

Mô hình này giúp tránh cả hai cực đoan: đổi quá dễ hoặc đóng băng mọi thứ.

Ghi chú triển khai theo môi trường

Không nên áp cùng một nhịp thay đổi runtime cho tất cả môi trường. Staging nên chạy trước và đủ lâu để lộ lỗi ẩn. Production nên ưu tiên nhịp thay đổi ổn định, có cửa sổ quan sát sau mỗi lần rollout. Mục tiêu là giảm thay đổi đồng thời ở lớp nền, đặc biệt trong giai đoạn hệ thống đang tăng trưởng nhanh.

Kết luận mở rộng cho runtime governance

Kubelet và containerd không phải chủ đề tối ưu “một lần là xong”. Đây là miền kỹ thuật cần quản trị liên tục, có đo lường, có kiểm thử và có trách nhiệm rõ ràng. Khi runtime policy được vận hành như sản phẩm nền tảng, cluster sẽ ổn định hơn rõ rệt qua từng quý.

Nhắc lại nguyên tắc then chốt

Mọi thay đổi runtime cần được xem như thay đổi hạ tầng lõi: có đánh giá rủi ro, có canary, có rollback và có đo lường sau triển khai. Kỷ luật này giúp giảm đáng kể số sự cố khó truy vết ở lớp node, nơi nhiều tín hiệu thường bị che khuất bởi triệu chứng ở ứng dụng.

Đầu tư vào runtime governance sớm sẽ trả lại lợi ích lớn ở giai đoạn scale nhanh và nâng cấp phiên bản liên tục.

Phần mở rộng này nhấn mạnh rằng cấu hình kubelet và containerd chỉ tạo giá trị khi được vận hành cùng quy trình kiểm soát thay đổi có trách nhiệm, đo lường đầy đủ và phản hồi liên tục.