AWS CNI lessons from a Production Outage
Bài tóm tắt Neon 2025 3. Quy mô lớn Độ khó: Nâng cao
Neon · 2025 · 3. Quy mô lớn · Độ khó: Nâng cao — bài gốc
Bài cuối trong series postmortem về sự cố 16/5 và 19/5/2025 ở region us-east-1 của Neon; bài này chỉ về phần cấp phát IP.
Bối cảnh
- Neon tách storage và compute cho Postgres serverless; mỗi compute là một VM nhẹ trong một pod Kubernetes. Cụm us-east-1 (2025): đỉnh khoảng 6.000 compute chạy mỗi ngày, khoảng 500 pod mới mỗi phút và tốc độ tắt tương đương.
- Là một trong những region đầu, subnet chỉ /20 mỗi AZ, tổng khoảng 12.000 IP (các region khác 24.000), vì load test cho thấy cụm chỉ cần tới 10.000 compute. Dịch vụ tăng nhanh hơn dự kiến.
Diễn biến
- 16/5: job tắt compute rảnh của control plane hỏng; compute tăng từ khoảng 5.000 lên khoảng 8.100 trong vài phút và subnet hết IP dù mới gán khoảng 8.800/12.273 IP cho pod. Lý do nằm ở hành vi mặc định của AWS VPC CNI (
WARM_ENI_TARGET=1): mỗi node giữ dư cả một ENI (49 IP); chỉ trả IP khi cả ENI trống, mà pod được gán ngẫu nhiên vào các ENI (map của Go duyệt ngẫu nhiên) nên ENI hầu như không bao giờ trống. Node cũ hết CPU/RAM vẫn ôm khoảng 3.400 IP không dùng được. Một node có thể chạy 200 pod mà giữ 450 IP. - Để giải phóng IP, đặt
WARM_IP_TARGET=1(vì đọc nhầm tài liệu, tưởng mặc định là 5). IP được trả lại ngay, nhưng khi control plane bắt đầu tắt compute, tốc độ khởi động pod tụt mạnh: IP vừa thu hồi nằm cooldown 30 giây mà vẫn được tính vào "số IP dư", nên mỗi lần xoá pod có thể chặn mọi lần tạo pod trên node đó 30 giây. Control plane retry sau 2 phút timeout còn làm nặng thêm. - Đặt tất cả về 0: thực chất là tắt
WARM_IP_TARGETvà quay về logic ENI; node lại ôm nhiều IP và cụm ổn định. - 19/5: như một việc dọn dẹp sau sự cố, họ revert về
WARM_IP_TARGET=1vì không chắc hành vi của 0. Lỗi lặp lại; đặt về 0 cũng không hết, vì vớiWARM_ENI_TARGET=0, ipamd chỉ cấp thêm IP khi node không còn IP dư nào và 30 giây qua không pod nào bị xoá, điều không xảy ra khi pod churn cao. Giảm ảnh hưởng tới user bằng cách tăng pool compute dựng sẵn. Lỗi tự hết sau nhiều giờ, khi control plane tình cờ ngừng tắt pod 86 giây (vì một query đắt, cũng chính là kiểu lỗi kích hoạt sự cố đầu).
Bài học cho SWE
- Mở rộng một cụm vượt kích thước đã load test làm lộ những giới hạn chưa từng thấy; subnet của region cũ là một giả định ngầm (Sự cố và postmortem).
- Đổi cấu hình trong sự cố dựa trên đọc tài liệu vội có thể tạo sự cố thứ hai; "revert cho chắc" cũng là một thay đổi cần kiểm chứng (Deploy và release an toàn).
- Với plugin hạ tầng quan trọng, đọc mã nguồn để hiểu hành vi thật; Neon đã gửi PR cho AWS CNI.
- Pool tài nguyên dựng sẵn (compute ấm) mua được thời gian khi đường tạo mới đang lỗi.
Liên quan
Được nhắc tới trong
Chủ đề (2)
Công ty (1)