Kubernetes 1.32 giới thiệu tính năng stream API để khắc phục tình trạng tăng đột biến bộ nhớ khi thực hiện yêu cầu list
Kubernetes 1.32 nâng cấp tính năng watch lists lên beta, cho phép các client stream các bộ sưu tập tài nguyên lớn và ngăn chặn sự cố hết bộ nhớ (out-of-memory) trên máy chủ API.
Được dịch tự động từ bản gốc tiếng Anh.
Trong một bài đăng trên Kubernetes Blog vào tháng 12 năm 2024, các kỹ sư từ Upbound, Google và Red Hat đã trình bày chi tiết về một cải tiến quan trọng về hiệu quả sử dụng bộ nhớ cho máy chủ API của Kubernetes. Bản cập nhật này giải quyết cách các cụm lớn xử lý việc truy xuất dữ liệu hàng loạt, bằng cách giới thiệu cơ chế stream giúp ngăn ngừa tình trạng cạn kiệt bộ nhớ đột ngột trong điều kiện tải cao.
Chuyện gì đã xảy ra
Việc quản lý các cụm Kubernetes lớn thường dẫn đến gánh nặng bộ nhớ đáng kể khi các thành phần gửi đi các yêu cầu list. Trong cách triển khai truyền thống, kube-apiserver phải lắp ráp toàn bộ phản hồi trong bộ nhớ trước khi gửi bất kỳ dữ liệu nào đến client. Nếu kích thước phản hồi lên tới hàng trăm megabyte, hoặc nếu nhiều yêu cầu đến cùng lúc sau một sự cố mạng, quy trình này có thể nhanh chóng tiêu thụ toàn bộ RAM khả dụng. Mặc dù các cơ chế API Priority and Fairness hiện có bảo vệ chống lại quá tải CPU, chúng chỉ cung cấp sự bảo vệ hạn chế trước những đợt tăng đột biến bộ nhớ không giới hạn này.
Quá trình điều tra cho thấy việc cấp phát bộ nhớ này xảy ra vì máy chủ lấy dữ liệu từ cơ sở dữ liệu, giải mã hóa (deserialize) nó, và sau đó xây dựng định dạng phản hồi cuối cùng tất cả cùng một lúc. Chuỗi thao tác này tạo ra một lượng bộ nhớ tạm thời khổng lồ mà cả cơ chế thu gom rác (garbage collection) của Go lẫn các giới hạn bộ nhớ được cấu hình đều không thể quản lý hiệu quả trong các đợt tăng đột biến. Trong các thiết lập sẵn sàng cao (high-availability), điều này có thể dẫn đến lỗi dây chuyền, nơi một máy chủ API bị sập do tình trạng hết bộ nhớ (OOM), chuyển các yêu cầu nặng nề tương tự sang các node khác và khiến chúng cũng thất bại.
Để giải quyết vấn đề này, nhóm Kubernetes đã nâng cấp tính năng watch list lên beta trong phiên bản 1.32. Điều này cho phép các client chọn tham gia streaming danh sách bằng cách chuyển từ các yêu cầu list tiêu chuẩn sang một dạng đặc biệt của các yêu cầu watch. Bằng cách phục vụ các yêu cầu này từ watch cache, máy chủ sẽ stream từng mục riêng lẻ thay vì đệm toàn bộ bộ sưu tập. Thay đổi này đảm bảo rằng gánh nặng bộ nhớ vẫn không đổi, chỉ bị giới hạn bởi kích thước tối đa của một đối tượng đơn lẻ cộng với một số phân bổ nhỏ, cải thiện đáng kể độ ổn định cho các cụm chứa nhiều đối tượng lớn.
Cách thức hoạt động
Cơ chế cốt lõi dựa trên việc chuyển từ xử lý theo lô (batch processing) sang streaming. Các yêu cầu list truyền thống đòi hỏi máy chủ phải giữ toàn bộ tập dữ liệu trong RAM trong quá trình mã hóa (serialization). Ngược lại, phương pháp tiếp cận watch list mới tận dụng watch cache hiện có, đây là một bộ nhớ đệm trong bộ nhớ được thiết kế để mở rộng các thao tác đọc. Khi một client sử dụng phương pháp này, máy chủ API gửi các đối tượng từng cái một khi chúng được truy xuất từ bộ nhớ đệm, tránh nhu cầu cấp phát bộ nhớ cho toàn bộ nội dung phản hồi cùng một lúc.

Sự thay đổi kiến trúc này tách rời mức sử dụng bộ nhớ khỏi tổng số đối tượng trong một bộ sưu tập. Thay vì mức tiêu thụ bộ nhớ tăng tuyến tính theo kích thước của danh sách, nó vẫn phẳng bất kể số lượng mục được trả về là bao nhiêu. Điều này làm cho máy chủ API trở nên bền bỉ ngay cả khi xử lý hàng nghìn tài nguyên lớn, chẳng hạn như các Secret với payload đáng kể, mà không gặp rủi ro bị giết do OOM.
Chi tiết chính
- Tính năng watch list đạt trạng thái beta trong Kubernetes 1.32.
- Các client phải bật rõ ràng feature gate
WatchListClienttrong client-go để sử dụng streaming lists. - Các bài kiểm tra tổng hợp cho thấy mức sử dụng bộ nhớ ổn định ở mức 2 GB khi bật streaming, so với 20 GB khi tắt.
- Tính năng này yêu cầu các phiên bản etcd 3.4.31+ hoặc 3.5.13+.
- Trong Kubernetes 1.33, các feature gate mới
StreamingCollectionEncodingToJSONvàStreamingCollectionEncodingToProtobufđã được giới thiệu để hỗ trợ streaming phía máy chủ mà không cần thay đổi client. - Feature gate
WatchListbị tắt theo mặc định trong Kubernetes 1.33, mặc dù nó được bật theo mặc định cho kube-controller-manager trong phiên bản 1.32.
Tại sao điều này quan trọng
Đối với các kỹ sư nền tảng và SRE quản lý các cụm quy mô lớn, bản cập nhật này giải quyết một điểm yếu trong sự ổn định của control plane. Tình trạng cạn kiệt bộ nhớ trên máy chủ API rất khó chẩn đoán và khôi phục, thường dẫn đến mất điện hoàn toàn của control plane. Bằng cách áp dụng streaming lists, các đội ngũ có thể chạy các cụm lớn hơn với các tài nguyên phức tạp hơn mà không lo sợ rằng một vòng lặp reconciliation thông thường hoặc một lần đồng bộ sau sự cố sẽ làm sập lớp quản lý của họ.
Thay đổi này cũng có tác động đến cách tính toán chi phí API trong các phiên bản tương lai. Hiện tại, API Priority and Fairness gán chi phí thấp cho các yêu cầu list để duy trì tính song song cho các trường hợp sử dụng điển hình. Khi hệ sinh thái chuyển hướng sang watch lists, hệ thống có thể an toàn tăng mức ước tính chi phí cho các yêu cầu list truyền thống. Điều này sẽ cung cấp sự bảo vệ tốt hơn chống lại các client cũ hoặc các công cụ bị cấu hình sai tiếp tục đưa ra các yêu cầu hàng loạt tốn kém, đảm bảo phân phối tài nguyên công bằng hơn trên toàn cụm.
Những gì bạn có thể làm
- Nâng cấp cụm của bạn lên Kubernetes 1.32 hoặc mới hơn để truy cập tính năng watch list beta.
- Xác minh rằng phiên bản etcd của bạn ít nhất là 3.4.31 hoặc 3.5.13 để đảm bảo tính tương thích.
- Cập nhật các client dựa trên Golang để bật feature gate
WatchListClienttrong client-go. - Giám sát mức sử dụng bộ nhớ trên các máy chủ API của bạn trong giờ cao điểm để xác định xem các yêu cầu list lớn có còn gây ra các đợt tăng đột biến hay không.
- Khuyến khích các controller và operator của bên thứ ba trong môi trường của bạn áp dụng API streaming trong giai đoạn beta.
- Lên kế hoạch cho các bản nâng cấp tương lai lên Kubernetes 1.33 để tận dụng các tính năng mã hóa streaming phía máy chủ không yêu cầu thay đổi mã client.


