Ngân sách bộ nhớ pod trên Kubernetes

Memory limit của pod trên Kubernetes nên được hiểu như một ngân sách chung. Mọi phần bộ nhớ nằm trong cgroup của pod đều tiêu vào ngân sách đó: bộ nhớ của tiến trình, cache của runtime, CUDA context, vùng /dev/shm, và các vùng offload xuống host RAM.

Vì vậy, khi pod bị OOMKilled, câu hỏi quan trọng không phải là từng cấu hình riêng lẻ có lớn hay không. Câu hỏi quan trọng là tổng các khoản cùng bị tính vào cgroup có vượt limits.memory hay không.

Request, limit và cgroup

requests.memory là lượng memory mà scheduler dùng để chọn node phù hợp cho pod. limits.memory là mức trần mà kubelet cấu hình bằng cgroup để kernel enforce trong lúc pod chạy.

Khi tổng memory usage trong cgroup vượt limits.memory, kernel có thể kill tiến trình trong pod. Điểm dễ nhầm là limits.memory không chỉ áp lên RSS của tiến trình. Kubernetes cũng tính các volume memory-backed, ví dụ emptyDir dùng medium: Memory, vào memory usage của container.

/dev/shm là một khoản trong ngân sách

Trong pod, /dev/shm thường là một tmpfs nằm trên RAM. Khi /dev/shm được tạo từ emptyDir với medium: Memory, dữ liệu ghi vào /dev/shm cũng tiêu memory của container.

Điều này đặc biệt quan trọng với workload LLM. sharedMemory lớn giúp các tiến trình giao tiếp nhanh hơn, nhưng phần dung lượng thực sự được dùng trong /dev/shm vẫn nằm trong cùng ngân sách với tiến trình Python, CUDA context, runtime inference, UCX/NIXL, và các buffer khác.

Cách cộng bộ nhớ khi chạy LLM

memory limit của pod
  = memory của tiến trình
  + peak host RAM khi load model
  + /dev/shm thực sự được dùng
  + KV cache hoặc buffer offload xuống host RAM
  + overhead của runtime, CUDA, UCX/NIXL

Nếu tổng các khoản này lớn hơn limits.memory, pod có thể bị OOMKilled.

Ví dụ một pod có limits.memory = 512Gi. Nếu cấu hình sharedMemory256Gihost_cache_size256Gi, hai khoản này đã chiếm toàn bộ ngân sách trên giấy. Pod gần như không còn khoảng trống cho Python, CUDA context, UCX/NIXL, buffer tạm, và đỉnh host RAM khi load model.

limits.memory                 = 512 Gi
sharedMemory                  = 256 Gi
host_cache_size               = 256 Gi
còn lại cho phần còn lại       = 0 Gi
nguy cơ OOMKilled              = rất cao

Vì vậy, cách xử lý không phải chỉ nhìn một giá trị rồi tăng hoặc giảm. Cần cộng toàn bộ ngân sách, sau đó quyết định giảm /dev/shm, giảm host KV/offload, giảm peak khi load model, hoặc tăng limits.memory.

Ý nghĩa khi cấu hình inference đa GPU

Với inference đa GPU, /dev/shm thường phục vụ giao tiếp giữa process, tensor parallel, hoặc các transport như UCX/NIXL. NVIDIA Dynamo khuyến nghị sharedMemory.size khoảng 16Gi cho vLLM và 80Gi cho TensorRT-LLM, đồng thời thêm capability IPC_LOCK để NIXL/UCX có thể pin memory cho RDMA.

Các con số khuyến nghị này không thay thế cho bài toán ngân sách. Chúng chỉ là điểm bắt đầu để cấu hình shared memory. Pod vẫn cần đủ memory limit cho toàn bộ phần còn lại của workload.

Trải nghiệm thực tế

Pod worker có thể bị OOMKilled dù từng tham số nhìn riêng có vẻ hợp lý. Nguyên nhân là sharedMemoryhost_cache_size cùng tiêu vào memory limit của pod.

Trong trường hợp sharedMemory = 256Gi, host_cache_size = 256Gi, và limits.memory = 512Gi, ngân sách đã hết trước khi tính phần load model và runtime. Nâng một phần tài nguyên mà không cân lại toàn bộ ngân sách sẽ không giải quyết được OOM. Cần nhìn pod như một bảng cộng memory duy nhất.

Cập nhật: 2026-05-29