Các cơ chế hợp lệ của Kubernetes có thể gây ra sự cố mặt phẳng điều khiển như thế nào
Mặt phẳng điều khiển của Kubernetes phải đối mặt với các đường dẫn lỗi ẩn, nơi những cơ chế hợp lệ như informers, tổng hợp schema và liveness probes khuếch đại các lỗi cục bộ thành sự cố toàn hệ thống.
Được dịch tự động từ bản gốc tiếng Anh.
Mặt phẳng điều khiển của Kubernetes được thiết kế để cô lập các lỗi của từng thành phần riêng lẻ, nhưng tính sẵn sàng tổng thể vẫn dễ bị tổn thương trước cách các thành phần trên đường dẫn quan trọng hoạt động dưới áp lực. Các phân tích gần đây cho thấy ở quy mô cụm lớn (fleet scale), một thành phần không cần phải gặp sự cố crash để gây ra outage; thay vào đó, các cơ chế tiêu chuẩn có thể khuếch đại các lỗi cục bộ thông qua metadata dùng chung hoặc công việc khởi động đồng bộ.
Điều gì đã xảy ra
Ba trường hợp cụ thể minh họa cách các tính năng tiêu chuẩn của Kubernetes vô tình gây mất ổn định cho mặt phẳng điều khiển. Trong trường hợp đầu tiên, một extension API server đã công bố một schema không hợp lệ sau khi nâng cấp dependency. Lỗi này đã chặn các client chưa từng tương tác với extension API đó. Sự cố lan truyền qua metadata dùng chung, cụ thể là một tài liệu schema kết hợp các định nghĩa từ tất cả các API được đăng ký trong cụm. Người dùng cố gắng triển khai Helm cho các chart chỉ chứa các tài nguyên Kubernetes tiêu chuẩn đã gặp lỗi xác thực trước khi yêu cầu của họ thậm chí đến được API server, mặc dù không có mối liên hệ nào với extension bị lỗi.
Trường hợp thứ hai liên quan đến một DaemonSet agent khởi động lại trên một cụm lớn. Mặc dù được dự định là biện pháp phục hồi, việc khởi động lại theo kiểu rolling đã biến công việc khởi động thường nhật thành một cơn bão request mà API server không thể hấp thụ. Mỗi instance agent mới xây dựng lại view cục bộ về trạng thái cụm bằng cách liệt kê tất cả các Pod. Vì nhiều agent khởi động cùng lúc, chúng tạo ra một đợt tăng đột biến đồng bộ hóa các thao tác list. Trên các cụm lớn, các request này trả về hàng chục nghìn object, làm cạn kiệt bộ nhớ và CPU của API server khi nó xây dựng các response khổng lồ cho hàng nghìn client đồng thời.
Trong kịch bản thứ ba, một deep liveness check trên một thành phần nằm trong đường dẫn request API đã coi sự cố của downstream dependency là lỗi process. Probe này liên tục khởi động lại thành phần trong khi dependency bên ngoài vẫn không khả dụng. Chu kỳ này thúc đẩy các lần khởi động lại lặp đi lặp lại mà không giải quyết được vấn đề gốc rễ, làm gián đoạn lưu lượng API và loại bỏ state cache có thể duy trì khả năng dịch vụ một phần trong thời gian suy giảm hiệu suất.
Cách thức hoạt động
Những lỗi này bắt nguồn từ cách Kubernetes cung cấp metadata API và quản lý đồng bộ hóa trạng thái. Kubernetes sử dụng các aggregated API server để mở rộng chức năng mà không cần sửa đổi lõi. Đối với client, các extension này xuất hiện như native. Hệ thống cung cấp các schema contract dưới hai dạng: OpenAPI v2 và v3. OpenAPI v2 cung cấp một tài liệu kết hợp duy nhất chứa các định nghĩa từ cả lõi và tất cả các extension API. Điều này tạo ra một shared failure domain, nơi một định nghĩa không hợp lệ từ một extension có thể ngăn cản client phân tích toàn bộ tài liệu, chặn quyền truy cập vào các tài nguyên không liên quan. OpenAPI v3 tách biệt các schema theo API group, thu hẹp phạm vi ảnh hưởng.
Informers cung cấp cho controllers một view cục bộ về trạng thái cụm, giảm thiểu các query lặp lại tới API server. Tuy nhiên, khi nhiều controllers khởi động lại đồng thời, việc xây dựng lại các view này đặt áp lực đáng kể lên mặt phẳng điều khiển. Informers thường sử dụng resourceVersion=0 để đọc từ watch cache của API server thay vì etcd. Trước đây, đường dẫn này bỏ qua giới hạn pagination, trả về toàn bộ collection object. Khi hàng nghìn agent yêu cầu các danh sách đầy đủ này đồng thời trong một sự kiện phục hồi, API server gặp khó khăn trong việc serialize và gửi hàng trăm megabyte dữ liệu cho mỗi request.
Liveness probes được thiết kế để khởi động lại các process không khỏe mạnh. Tuy nhiên, nếu một probe kiểm tra các dependency bên ngoài thay vì khả năng cục bộ, nó có thể khởi động lại một process vẫn đang hoạt động tốt bằng cách sử dụng state cache. Ví dụ, một KMS provider có thể mất kết nối với dịch vụ quản lý khóa bên ngoài nhưng vẫn phục vụ các yêu cầu mã hóa bằng cách sử dụng key cache. Một probe kiểm tra khả năng tiếp cận bên ngoài sẽ khởi động lại provider không cần thiết, buộc nó phải thiết lập lại kết nối và loại bỏ state cache hữu ích.
Chi tiết chính
- OpenAPI v2 kết hợp tất cả các schema API vào một tài liệu, tạo ra một shared failure domain nơi một schema extension không hợp lệ có thể chặn tất cả các client.
- OpenAPI v3 tách biệt các schema theo API group, giới hạn blast radius của các định nghĩa không hợp lệ đối với người dùng API cụ thể.
- Informers sử dụng
resourceVersion=0đọc từ watch cache, mà trước đây bỏ qua giới hạn pagination, dẫn đến kích thước response rất lớn. - Việc khởi động lại đồng bộ hóa của các DaemonSet agents có thể tạo ra một cơn bão request, làm quá tải API server với các thao tác list đồng thời.
- Liveness probes kiểm tra các dependency bên ngoài có thể khởi động lại các process vẫn có khả năng phục vụ request bằng cách sử dụng state cache.
- Tính đúng đắn ở cấp độ thành phần là cần thiết nhưng không đủ cho tính sẵn sàng của hệ thống; các cơ chế phải được đánh giá về hành vi khi các giả định bị vi phạm.
Tại sao điều này quan trọng
Đối với các đội ngũ xây dựng và vận hành nền tảng Kubernetes, những hiểu biết này nhấn mạnh rằng các mẫu vận hành tiêu chuẩn có thể trở thành bộ khuếch đại lỗi ở quy mô lớn. Các kỹ sư thường giả định rằng health checks và rolling updates là các hành vi mặc định an toàn. Tuy nhiên, khi các thành phần chia sẻ metadata hoặc đồng bộ hóa các task khởi động, những cơ chế này có thể tương tác theo những cách bất ngờ. Hiểu rõ sự khác biệt giữa việc kiểm tra dependency và kiểm tra capability là rất quan trọng để thiết kế các hệ thống resilient. Một probe báo cáo trung thực về sự cố downstream vẫn có thể vi phạm hợp đồng availability của hệ thống bằng cách kích hoạt các lần khởi động lại không cần thiết.
Điều này đặc biệt quan trọng đối với các đội ngũ chạy extension APIs, controllers giám sát các collection object lớn, hoặc các thành phần trong đường dẫn request API. Chi phí xây dựng lại local state hoặc xác thực schemas có thể vượt quá dung lượng của mặt phẳng điều khiển trong các sự kiện tải đỉnh hoặc phục hồi. Các trưởng nhóm nền tảng phải xem xét lại các quy trình nâng cấp, bài tập phục hồi và thiết kế health-check để đảm bảo chúng không vô tình loại bỏ state cache hoặc tạo ra nhu cầu đồng bộ hóa lên các dependency đang bị suy giảm.
Bạn có thể làm gì
- Xác thực các OpenAPI schemas sau khi nâng cấp bằng cách lấy cả tài liệu v2 và v3 và phân tích chúng bằng các thư viện client để phát hiện sớm các định nghĩa không hợp lệ.
- Giới hạn phạm vi của informer đến collection tài nguyên nhỏ nhất cần thiết, chẳng hạn như namespaces cụ thể hoặc views chỉ chứa metadata, để giảm tải khởi động.
- Sử dụng WatchList hoặc các tính năng API Priority and Fairness cập nhật trong Kubernetes 1.31+ để giảm chi phí của các thao tác list ban đầu.
- Thiết kế liveness probes để kiểm tra capability cục bộ và tính hợp lệ của state cache thay vì khả năng tiếp cận dependency bên ngoài.
- Tách biệt các kiểm tra dependency khỏi liveness probes để cảnh báo operator mà không kích hoạt khởi động lại tự động trong các sự cố upstream tạm thời.
- Xem xét lại các chiến lược cập nhật DaemonSet và cài đặt maxUnavailable để ngăn chặn các lần khởi động lại đồng bộ hóa làm quá tải API server trong quá trình phục hồi.



