Fix Kubernetes ResourceQuota Exceeded: pods is forbidden: exceeded quota

intermediate☸️ Kubernetes2026-03-22| Kubernetes 1.20+, kubectl CLI, mọi cloud provider (GKE, EKS, AKS) hoặc cụm on-premise

Error Message

Error from server (Forbidden): pods "my-pod" is forbidden: exceeded quota: my-quota, requested: cpu=500m, used: cpu=900m, limited: cpu=1
#kubernetes#resourcequota#quota#namespace#resource-limit

Lỗi

Error from server (Forbidden): pods "my-pod" is forbidden: exceeded quota: my-quota, requested: cpu=500m, used: cpu=900m, limited: cpu=1

Namespace của bạn có giới hạn ResourceQuota, và pod này đã vượt quá mức đó. Thông báo lỗi nói rõ: giới hạn quota là 1000m CPU, đã dùng 900m, và bạn đang yêu cầu thêm 500m — tổng cộng là 1400m. Kubernetes từ chối ngay lập tức.

Pod không bao giờ vào trạng thái Pending. Nó bị chặn ngay tại API server trước khi scheduler kịp xử lý.

Bước 1: Kiểm tra mức sử dụng Quota hiện tại

Bắt đầu bằng cách xem chính xác lượng đã dùng so với giới hạn cho phép:

# Thay 'my-namespace' bằng namespace thực tế của bạn
kubectl describe resourcequota -n my-namespace

Kết quả trả về có dạng:

Name:       my-quota
Namespace:  my-namespace
Resource    Used   Hard
--------    ----   ----
cpu         900m   1
memory      512Mi  2Gi
pods        8      10

CPU là nguyên nhân ở đây — đã dùng 900m trên tổng giới hạn cứng 1000m. Chỉ còn 100m, không đủ cho một pod yêu cầu 500m.

Để quét quota trên tất cả namespace cùng lúc:

kubectl get resourcequota --all-namespaces

Bước 2: Tìm thành phần đang tiêu thụ Quota

Trước khi thay đổi bất cứ thứ gì, hãy xác định các pod nào đang chiếm 900m đó:

kubectl get pods -n my-namespace -o custom-columns=NAME:.metadata.name,CPU:.spec.containers[*].resources.requests.cpu

Đã cài metrics-server? kubectl top hiển thị mức sử dụng thực tế, không chỉ là các request đã khai báo:

kubectl top pods -n my-namespace

Chú ý đến sự chênh lệch. Một pod khai báo request 500m CPU nhưng thực tế chỉ dùng trung bình 30m là mục tiêu điều chỉnh lý tưởng.

Bước 3: Các phương án khắc phục

Phương án A — Giảm Resource Request của Pod

Request khai báo quá cao là nguyên nhân phổ biến nhất. Nếu pod thực sự không cần 500m, hãy giảm xuống trong manifest:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: my-namespace
spec:
  containers:
  - name: my-container
    image: my-image:latest
    resources:
      requests:
        cpu: "100m"      # was 500m, reduced to 100m
        memory: "128Mi"
      limits:
        cpu: "200m"
        memory: "256Mi"

Chạy kubectl top pods trước để chọn giá trị thực tế. Đặt request là 100m cho pod có mức trung bình 80m sẽ tạo ra khoảng đệm an toàn mà không lãng phí quota.

Phương án B — Tăng giới hạn ResourceQuota

Đôi khi namespace đơn giản là cần thêm tài nguyên. Kiểm tra định nghĩa quota hiện tại trước:

kubectl get resourcequota my-quota -n my-namespace -o yaml

Patch trực tiếp:

kubectl patch resourcequota my-quota -n my-namespace \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/hard/cpu", "value": "2"}]'

Hoặc nếu bạn quản lý quota bằng file YAML (cách được khuyến nghị), hãy cập nhật và apply:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: my-quota
  namespace: my-namespace
spec:
  hard:
    cpu: "2"        # increased from 1 to 2
    memory: 4Gi
    pods: "20"
kubectl apply -f resourcequota.yaml

Phương án C — Xóa Pod không dùng hoặc Scale Down Deployment

Các pod đã hoàn thành hoặc thất bại vẫn được tính vào quota cho đến khi bị xóa. Hãy dọn sạch những thứ không còn cần thiết:

# Xóa các pod đã hoàn thành/thất bại
kubectl delete pods -n my-namespace --field-selector=status.phase==Succeeded
kubectl delete pods -n my-namespace --field-selector=status.phase==Failed

# Scale down một deployment không còn cần thiết
kubectl scale deployment old-deployment -n my-namespace --replicas=0

Nên kiểm tra điều này trước tiên — một namespace đầy các job Completed cũ có thể âm thầm chiếm hàng trăm millicores. Bạn có thể giải phóng đủ quota mà không cần chạm vào giới hạn.

Bước 4: Xác nhận sau khi sửa

Sau khi thực hiện thay đổi, hãy xác nhận quota còn dư trước khi thử lại:

# Kiểm tra mức sử dụng quota sau khi cập nhật
kubectl describe resourcequota -n my-namespace

# Thử tạo lại pod
kubectl apply -f my-pod.yaml

# Xác nhận pod đang chạy
kubectl get pod my-pod -n my-namespace

Kết quả mong đợi:

NAME     READY   STATUS    RESTARTS   AGE
my-pod   1/1     Running   0          10s

Lưu ý để tránh lỗi lần sau

  • Luôn đặt resource requests và limits — namespace có ResourceQuota sẽ từ chối các pod không khai báo requests/limits. Dùng LimitRange để đặt giá trị mặc định cho toàn namespace nếu bạn không muốn chỉ định trên từng pod.
  • Kết hợp LimitRange với ResourceQuotaLimitRange đặt giá trị mặc định cho từng container; ResourceQuota giới hạn tổng tài nguyên của namespace. Hai thứ này được thiết kế để hoạt động cùng nhau.
  • Tích hợp kiểm tra quota vào CI/CD — thêm bước pre-deploy chạy kubectl describe resourcequota -n $NAMESPACE và fail pipeline nếu CPU còn lại thấp hơn lượng request của deployment.
  • Đặt requests dựa trên số liệu thực tế, không phải ước đoán — dùng kubectl top pods hoặc lấy dữ liệu p95 CPU trong một tuần từ Prometheus. Đó là cơ sở tốt hơn nhiều so với việc cảm tính "500m nghe có vẻ ổn".
  • Quota là chính sách, không phải giới hạn vật lý — lỗi này có nghĩa là bạn đã chạm trần giới hạn quản trị, không phải thiếu tài nguyên thực sự. Node có thể vẫn còn rất nhiều CPU trống. ResourceQuota hoàn toàn là giới hạn quản trị do cluster admin thiết lập.

Related Error Notes