DevOps 31/08/2026 8 phút

Pod báo CrashLoopBackOff nhưng container chưa từng chạy một giây nào — cột STATUS của Kubernetes đang mô tả việc nó đang làm, không phải việc đã hỏng

Dựng bảy sự cố thật rồi đo xem công cụ nào nói thật. CrashLoopBackOff che hai nguyên nhân hoàn toàn khác nhau — ứng dụng chết (đọc logs) và lệnh khởi động không tồn tại (logs rỗng, exit 128, phải đọc events). ContainerCreating nghe như đang tiến triển nhưng đứng đó vĩnh viễn vì thiếu Secret. Quy tắc dùng ngay: nhật ký rỗng mà restarts>0 thì container không crash, nó không khởi động nổi — và bảng mã thoát 128/137/143 nói container chết thế nào.

DevOps 31/08/2026 9 phút

Hai pod cùng một dòng mã, đồ thị CPU vẽ y hệt nhau — nhưng một cái chậm gấp 23 lần, và cái chỉ số ai cũng nhìn không hề thấy điều đó

Pod chạy được nhưng chậm khó lần hơn pod hỏng hẳn, vì mọi thứ đều xanh. Hai pod khác nhau đúng mỗi limits.cpu: p50 gần như bằng nhau (4,9 so 3,9 ms) mà p95 chênh 23 lần — và ~96 ms không ngẫu nhiên, đó chính là chu kỳ 100 ms của CFS. Đồ thị 'CPU usage' vẽ hai pod trùng khít vì usage giống nhau; bằng chứng nằm ở cpu.stat: 36/50 chu kỳ bị bóp, 3,28 giây bị treo. Và từ K8s 1.33, đổi limit không cần khởi động lại pod nên p95 rơi từ 95,9 xuống 4,1 ms ngay trong lúc gỡ.

DevOps 31/08/2026 8 phút

Ba lỗi mạng hoàn toàn khác nhau trong Kubernetes cho ra đúng một thông báo và đúng một thời gian — và một lệnh duy nhất phân biệt được cả ba

Nhãn sai, cổng sai, pod chưa sẵn sàng — ba nguyên nhân khác hẳn nhau nhưng đều ra ConnectionRefused ~0 ms, và DNS thì phân giải tốt ở cả ba nên nslookup chẳng chứng minh gì. Đo cách một bảng endpointslices tách được ba bệnh cùng triệu chứng, và vì sao khác biệt Refused-ngay-lập-tức so với Timeout-đúng-hạn-chờ (3004 ms khi bật NetworkPolicy) là phép chia đôi tốt nhất khi lần lỗi mạng.

DevOps 31/08/2026 8 phút

Tôi xoá tay một Service do Helm tạo, rồi hỏi helm status — nó vẫn thản nhiên báo 'deployed', vì Helm chỉ đọc lại biên nhận của chính mình chứ không nhìn vào cụm

Đo hai thứ ở Helm: nó thêm gì vào manifest, và nó KHÔNG biết gì. 380 dòng chart nguồn chỉ sinh ra 100 dòng YAML — giá trị của Helm không nằm ở viết ít mà ở tham số hoá. Trạng thái release là một Secret base64 hai lần rồi gzip, giữ cả mã nguồn chart nên 1,9 KB manifest phình thành 12 KB. Nhưng chỗ đáng nhớ nhất: xoá tay một Service thì helm status vẫn báo deployed, vì Helm không phải bộ điều khiển — nó đọc lại cái nó ĐÃ làm, không phải cái đang CÓ. Và uninstall để lại PVC của StatefulSet lẫn CRD, vì Helm chỉ dọn được thứ chính nó tạo.

DevOps 31/08/2026 8 phút

Tôi từng nói Kustomize gọn hơn Helm — đo lại thì 41 dòng so 37 dòng, gần như hoà; khác biệt thật nằm ở chỗ Kustomize không nhớ nó đã tạo ra gì

Đo Kustomize trên đúng bài toán đã đo Helm, và phát hiện phép so 380-dòng ở phần trước là so nhầm chart mẫu với overlay tối giản. Đo cho công bằng: Helm 37 dòng, Kustomize 41 dòng — đếm dòng là hoà. Khác biệt thật ít ai nói tới: Kustomize không có trạng thái release (0 Secret trong namespace), nên bỏ một tài nguyên khỏi khai báo thì nó vẫn còn nguyên trong cụm — Helm xoá được vì nhớ lần trước, Kustomize phải mượn --applyset. Cùng lúc configMapGenerator băm nội dung nên đổi cấu hình là Deployment tự cuộn lại, thứ Helm phải tự gắn checksum mới có.

DevOps 31/08/2026 9 phút

30 dòng YAML mua được kiểm tra dữ liệu và cột hiển thị riêng cho Kubernetes — nhưng nó tạo ra 0 pod, vì một CRD là danh từ còn Operator mới là động từ

Tự viết cả CRD lẫn Operator rồi đo. 30 dòng YAML cho validation, giá trị mặc định và cột hiển thị mà không viết dòng mã nào — nhưng tạo xong TrangWeb thì namespace vẫn 0 Deployment, 0 pod. 38 dòng Python biến nó thành Operator thật (soBan 2→4 sau ~5 giây, xoá là Deployment tự biến mất nhờ ownerReferences). Chi phí thật lộ ra ở chỗ khác: vòng lặp quét 20 đối tượng gọi 660 lệnh API trong 60 giây, 11 lệnh/giây kể cả khi không có gì đổi — và với 200 đối tượng là 110 lệnh/giây không bao giờ nghỉ.