Bài học Production: ConfigMap gần 1MB đánh sập Control-plane
Bài học Production: ConfigMap gần 1MB đánh sập Control-plane
Chào các bác, nay tôi muốn chia sẻ lại một sự cố khá khoai mà team tôi từng gặp phải. Vấn đề này nghe thì rất cơ bản nhưng lại có thể oánh sập cả Control-plane của một Cluster Production nếu chúng ta không để ý kỹ các limit ngầm của Kubernetes.
Đó là câu chuyện về việc lạm dụng ConfigMap để chứa dữ liệu lớn và cái giá phải trả của latency. Tôi gặp bài toán này khi một service legacy quyết định đưa toàn bộ file cấu hình routing (định dạng XML) vào một ConfigMap ~950KB (gần chạm ngưỡng 1MB của etcd). Quy trình deploy qua GitOps. Mọi thứ có vẻ bình thường cho đến khi họ update file config lần thứ hai trong giờ cao điểm.
Hiện trạng lúc đó
Tôi hiện làm remote cho một công ty ngoại, hệ thống vận hành Kubernetes Cluster khoảng 50 Nodes trên môi trường Cloud. Kiến trúc chủ yếu là Microservices, nhưng có một service legacy (gọi tắt Service-Legacy) cần load một file cấu hình routing phức tạp. Team Dev đưa file XML (~950KB) vào một ConfigMap để dễ thay đổi mà không build lại image.
Triệu chứng nhận được
- API Server Latency Spike: P99 tăng từ ~50ms lên 2–3s, thậm chí timeout.
- kubectl Sluggish: lệnh đơn giản bị treo hoặc timeout.
- Node Flapping: một số Node chuyển Ready ↔ NotReady.
- etcd Alerts: metric
etcd_disk_wal_fsync_duration_secondstăng cao — disk write latency.
Toàn bộ hoạt động quản trị trên Cluster gần như không thể vận hành.
Hướng điều tra
Ban đầu team nghi nhiều nguyên nhân do triệu chứng nhiễu:
- Nghi vấn 1: Network issue — kiểm tra VPC flow logs và ping, mạng ổn.
- Nghi vấn 2: Resource exhaustion trên control-plane — thử scale up master nhưng không cải thiện nhiều.
- Nghi vấn 3: etcd Disk IOPS — throughput không cao, chỉ có latency cao.
Sau gần 30 phút kiểm tra mạng và VM specs chưa ra vấn đề thực sự.
Root cause và Phương án xử lý
Root Cause:
- etcd không thiết kế để lưu trữ các object lớn. Object gần 1MB chiếm dụng nhiều băng thông xử lý của etcd và làm chậm replication giữa các node etcd.
- Cơ chế LIST/WATCH của Kubernetes: khi ConfigMap thay đổi, API Server phải đẩy bản cập nhật (~1MB) tới tất cả các watchers.
- Service-Legacy có nhiều replicas phân tán trên nhiều node, nên update tạo ra một burst traffic lớn từ API Server.
- API Server bị nghẽn CPU do (de)serialization JSON của payload lớn, khiến các request quan trọng khác bị chậm → Node bị đánh dấu NotReady → kích hoạt eviction → tạo thêm load → hiệu ứng chết chùm.
Phương án xử lý:
- Ngắn hạn: Rollback ConfigMap về version cũ hoặc xóa bớt nội dung để giảm size.
- Dài hạn:
- Chuyển file cấu hình lớn ra khỏi ConfigMap, build trực tiếp vào container image.
- Nếu cần cập nhật động, dùng init container để download file từ object storage (ví dụ S3).
- Thiết lập ResourceQuota cho namespace để giới hạn số lượng và kích thước ConfigMap.
Bài học kinh nghiệm
- etcd is for Coordination, not Storage: không coi etcd là database. Object nên giữ dưới ~100KB.
- Beware of the Watchers: chi phí một object = storage × số watchers (mạng và CPU khi push updates).
- Monitor Control-plane metrics: alert kỹ cho etcd và API Server latency.
- Immutable Infrastructure: config lớn nên được treat như code: build, test và deploy qua image.
Đây là một case study tôi note lại và muốn lan tỏa đến anh em trong cộng đồng. Hy vọng giúp tránh những sự cố tương tự khi dùng ConfigMap để lưu dữ liệu lớn.