
Trong môi trường container orchestration, việc quản lý tài nguyên một cách hiệu quả không chỉ giúp tối ưu chi phí mà còn đảm bảo tính ổn định và hiệu suất của hệ thống. Kubernetes cung cấp hai cơ chế quan trọng để kiểm soát tài nguyên cho pods và containers: requests (yêu cầu) và limits (giới hạn). Hiểu rõ sự khác biệt và cách sử dụng chúng là chìa khóa để triển khai ứng dụng thành công trên Kubernetes.
Requests và Limits là gì?
Khi bạn định nghĩa một container trong Kubernetes pod, bạn có thể chỉ định mức tài nguyên mà container đó cần (requests) và mức tối đa mà nó được phép sử dụng (limits). Hai loại tài nguyên chính thường được cấu hình là CPU và memory (RAM), mặc dù Kubernetes cũng hỗ trợ các loại tài nguyên khác như ephemeral-storage và hugepages.
- Requests: Là lượng tài nguyên mà Kubernetes đảm bảo sẽ có sẵn cho container. Điều này giúp kube-scheduler quyết định node nào phù hợp để đặt pod. Nếu node không đủ tài nguyên để đáp ứng tổng requests của tất cả containers, pod sẽ không được lên lịch.
- Limits: Là ngưỡng tối đa mà container được phép sử dụng. Nếu container forsøi vượt quá limit, Linux kernel sẽ can thiệp thông qua cgroups (Control Groups) để ngăn chặn.
CPU requests và limits: Cách thức hoạt động
Đối với CPU, việc enforce limits được thực hiện thông qua CPU throttling. Khi container sử dụng lượng CPU gần đạt tới limit, kernel sẽ giới hạn thời gian CPU mà container có thể sử dụng trong mỗi khoảng thời gian (thường là 100ms). Điều này có nghĩa là:
- CPU limit là một hard limit – container sẽ không bao giờ sử dụng vượt quá lượng CPU này được cấp phép.
- Tuy nhiên, container vẫn có thể sử dụng nhiều hơn mức request nếu có tài nguyên dư trên node (do không có upper bound ngoài limit).
- CPU được đo bằng đơn vị “cpu” (core), với 1 cpu = 1 CPU core. Các giá trị phân số được cho phép (ví dụ: 0.5 cpu = 500m cpu).
Memory requests và limits: Cách thức hoạt động
Đối với memory,is different. Memory limits được enforce bằng cơ chế Out of Memory (OOM) killing của Linux kernel. Khi container sử dụng memory vượt quá limit:
- Kernel sẽ terminate container nếu hệ thống gặp memory stress (không có đủ RAM còn lại).
- Nếu node còn nhiều memory trống, container có thể tạm thời sử dụng vượt quá limit mà không bị giết ngay lập tức.
- Điều này khiến memory limit trở thành một reactive limit – chỉ được áp dụng khi hệ thống thực sự cần giải phóng memory.
- Memory được đo bằng bytes, với hỗ trợ các tiền tố như Ki, Mi, Gi (binary) hoặc k, M, G (decimal).
Pod-level resource management
Từ Kubernetes v1.34 (beta), có khả năng chỉ định resource requests và limits ở mức pod (ngoài mức container này). Khi sử dụng tính năng PodLevelResources:
- Pod-level requests/limits được áp dụng cho tổng tài nguyên của tất cả containers trong pod.
- Containers không có explicit requests/limits sẽ chia sẻ tài nguyên còn lại trong pod sau khi trừ đi lượng tài nguyên đã được cấp cho các container có cấu hình rõ ràng.
- Tính năng này đặc biệt hữu ích cho pods có nhiều containers (sidecar pattern) nơi việc cấu hình tài nguyên từng container riêng lẻ trở nên phức tạp.
Best practices để cấu hình requests và limits
Để tối ưu hiệu suất và chi phí, hãy tham khảo các hướng dẫn sau:
- Xác định request dựa trên nhuattan thực tế: Sử dụng công cụ monitoring (như Prometheus + Grafana) để đo lường mức tài nguyên trung bình và mức sử dụng cao nhất (peak) của ứng dụng trong thời gian chạy bình thường.
- Đặt limitcao hơn request 1.5-2 lần: Để có buffer cho các đợt tăng tải tạm thời mà không gây OOM kill hoặc throttling quá mức.
- Luôn đặt cả request và limit: Nếu chỉ đặt limit mà không có request, Kubernetes sẽ tự động đặt request = limit (từ v1.26), điều này có thể dẫn to việcover-allocate resources.
- Sử dụng ResourceQuota và LimitRange ở mức namespace: Để đặt mặc định và giới hạn tổng tài nguyên mà tất cả pods trong namespace có thể sử dụng.
- Giám sát và điều chỉnh định kỳ: Sử dụng metrics như container_cpu_usage_seconds_total và container_memory_usage_height để xem mức utilizations và tinh chỉnh cấu hình theo thời gian.
Ví dụ cấu hình thực tế
Dưới đây là ví dụ manifest cho một web application pod với 2 containers (app chính và sidecar logging):
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- name: app
image: myapp:latest
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
- name: log-agent
image: fluent/fluentd:v1.14-debian-1
resources:
requests:
memory: "128Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "100m"
Trong ví dụ này:
- Pod tổng request: 640Mi RAM và 300m CPU
- Pod tổng limit: 1.25Gi RAM và 600m CPU
- Log sidecar có thể ‘mượn’ tài nguyên từ app container nếu có sẵn, nhưng sẽ không bao giờ vượt quá 256Mi RAM và 100m CPU của riêng nó.
Common mistakes to avoid
- Setting limits too low: Dẫn đến frequent throttling (CPU) hoặc OOM kills (memory), gây ra degraded performance hoặc downtime.
- Ignoring requests: Làmให้ scheduler không thểตัดสินใจ placement tốt, có thể dẫn đếnoverloaded nodes or resource waste。
- Using same values for all environments: Phát triển, staging, và production thường có mức tải khác nhau – cần cấu hình tương ứng.
- Not monitoring actual usage: Làmให้ bạn không biết cấu hình hiện tại có phù hợp không và có thể lãng phí tài nguyên hoặc gây ra vấn đề ổn định.
Kết luận
Việc hiểu đúng sự khác biệt giữa requests và limits trong Kubernetes là nền tảng để triển khai ứng dụng ổn định, hiệu quả và chi phí tối ưu. Nhờ chính xác cấu hình hai tham số này, bạn sẽ:
- Đảm bảo các ứng dụng quan trọng luôn có đủ tài nguyên để hoạt động (nhờ requests)
- Ngăn ngừa một ứng dụng tiêu thụ quá nhiều tài nguyên và làm ảnh hưởng đến các ứng dụng khác trên cùng node (nhờ limits)
- Tối ưu sử dụng tài nguyên cluster và giảm chi phí vận hành
- Dễ dàng mở rộng (scale) ứng dụng khi có nhu cầu


