Fix Kubernetes Pod Bị Stuck ở Pending: "0/3 nodes are available: 3 Insufficient cpu"

intermediate☸️ Kubernetes2026-03-18| Kubernetes 1.20+, kubectl CLI, bất kỳ cloud provider nào (GKE, EKS, AKS) hoặc cluster on-premise

Error Message

0/3 nodes are available: 3 Insufficient cpu
#kubernetes#scheduling#resources#node

Chuyện gì đang xảy ra

Pod của bạn đã bị kẹt ở trạng thái Pending một lúc rồi. Khi kiểm tra bằng kubectl describe, bạn thấy nội dung tương tự như sau:

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----                -------
  Warning  FailedScheduling  30s   default-scheduler  0/3 nodes are available: 3 Insufficient cpu.

Kubernetes scheduler đã kiểm tra toàn bộ 3 node. Không node nào có đủ CPU trống để đáp ứng yêu cầu của pod. Vì vậy nó từ bỏ và để pod tiếp tục chờ.

Lỗi này khác với CrashLoopBackOff (pod khởi động nhưng bị crash) hay ImagePullBackOff (không kéo được image). Ở đây pod chưa bao giờ được khởi động — nó bị kẹt ngay ở bước lên lịch, trước khi bất kỳ container nào chạy.

Tái hiện và chẩn đoán

Bước 1: Xác nhận lỗi

kubectl describe pod <pod-name> -n <namespace>

Cuộn xuống phần Events ở cuối. Bạn sẽ thấy cảnh báo FailedScheduling:

0/3 nodes are available: 3 Insufficient cpu.

Bước 2: Kiểm tra lượng CPU pod đang yêu cầu

kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[*].resources}'

Hoặc xem trực tiếp trong file YAML Deployment của bạn:

resources:
  requests:
    cpu: "2000m"   # ← đây là giá trị scheduler dùng để tìm node phù hợp
  limits:
    cpu: "4000m"

Scheduler dùng requests, không phải limits, để đưa ra quyết định đặt pod. Một request 2000m nghĩa là mỗi node phải có 2 core trống — đó là yêu cầu khá lớn.

Bước 3: Kiểm tra dung lượng thực tế và CPU có thể phân bổ của node

kubectl describe nodes | grep -A 5 'Allocatable\|Allocated resources'

Để xem gọn hơn:

kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEMORY:.status.allocatable.memory

Sau đó đi sâu vào từng node để xem những gì đã được phân bổ:

kubectl describe node <node-name> | grep -A 10 'Allocated resources'

Ví dụ kết quả đầu ra:

Allocated resources:
  (Total limits may be over 100 percent, i.e., no guarantee)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                1850m (92%)  3200m (160%)
  memory             1Gi (55%)    2Gi (110%)

Với 92% đã được phân bổ, một pod mới yêu cầu dù chỉ 200m cũng sẽ không vừa. Đơn giản là không còn chỗ nữa.

Giải pháp

Tùy chọn 1: Giảm CPU request của pod (cách sửa nhanh)

Hầu hết các trường hợp, request chỉ đơn giản là được đặt quá cao. Hãy giảm xuống mức thực tế theo mức ứng dụng thực sự dùng khi khởi động.

resources:
  requests:
    cpu: "100m"    # giảm từ 2000m
    memory: "256Mi"
  limits:
    cpu: "1000m"
    memory: "512Mi"

Một lỗi thường gặp: đặt requests.cpu: "2" (2 core đầy đủ) trong khi ứng dụng chỉ đạt đỉnh 200m. Limit có thể giữ cao. Request chỉ cần là ước tính trung thực về mức sử dụng thông thường — không phải trường hợp xấu nhất, không phải kỳ vọng lý tưởng.

Áp dụng thay đổi:

kubectl apply -f your-deployment.yaml

Tùy chọn 2: Scale up cluster (thêm node)

Đôi khi request thực sự đúng và bạn chỉ cần thêm dung lượng. Thêm node là cách sửa trực tiếp nhất.

GKE:

gcloud container clusters resize <cluster-name> \
  --node-pool <pool-name> \
  --num-nodes 5 \
  --region <region>

EKS (managed node group):

aws eks update-nodegroup-config \
  --cluster-name <cluster-name> \
  --nodegroup-name <nodegroup-name> \
  --scaling-config minSize=2,maxSize=10,desiredSize=5

On-premise: cấp phát một VM mới và thêm vào cluster bằng kubeadm join.

Tùy chọn 3: Bật Cluster Autoscaler

Người dùng cloud có một lựa chọn thông minh hơn: Cluster Autoscaler. Nó tự động cấp phát node mới mỗi khi scheduler không thể đặt pod — không cần can thiệp thủ công.

# Kiểm tra xem autoscaler đã chạy chưa
kubectl get pods -n kube-system | grep cluster-autoscaler

Chưa cài đặt? Triển khai nó (ví dụ cho GKE với Workload Identity):

kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/gce/examples/cluster-autoscaler-autodiscover.yaml

Sau đó annotate node group của bạn để autoscaler biết nó đủ điều kiện để scale.

Tùy chọn 4: Evict hoặc scale down các workload khác

Tìm hiểu xem cái gì đang chiếm CPU trên toàn cluster:

kubectl top nodes
kubectl top pods --all-namespaces --sort-by=cpu | head -20

Các deployment nhàn rỗi hoặc replica quá mức thường là thủ phạm. Scale chúng xuống để giải phóng tài nguyên:

kubectl scale deployment <other-deployment> --replicas=1 -n <namespace>

Tùy chọn 5: Kiểm tra LimitRange có đang áp dụng giá trị mặc định lớn không

Một pod không có block resources sẽ nhận request bằng không từ Kubernetes — điều đó tự nó không gây ra lỗi này. Nhưng một LimitRange trong namespace có thể tự động inject một giá trị mặc định lớn.

kubectl get limitrange -n <namespace>
kubectl describe limitrange <name> -n <namespace>

Đặt request tường minh trong pod spec để ghi đè bất cứ thứ gì LimitRange đang inject.

Xác minh bản sửa lỗi

Sau khi áp dụng thay đổi, theo dõi pod trực tiếp:

kubectl get pods -n <namespace> -w

Bạn sẽ thấy: PendingContainerCreatingRunning — thường trong vòng một đến hai phút.

Xác nhận không còn lỗi scheduling nữa:

kubectl describe pod <pod-name> -n <namespace> | grep -A 10 Events

Không có sự kiện FailedScheduling nào nghĩa là bạn đã xong.

Bài học rút ra

  • Đặt request thực tế, không phải trường hợp xấu nhất. Scheduler đưa ra quyết định đặt pod thực sự dựa trên requests. Yêu cầu 4 core trong khi bạn chỉ dùng 200m lãng phí dung lượng được dự trữ trên mỗi node trong cluster.
  • Requests và limits có vai trò khác nhau. requests = những gì scheduler dự trữ lúc đặt pod. limits = ngưỡng cứng được áp dụng lúc runtime. Giữ request thấp và thực tế; đặt limit ở mức tối đa thực tế bạn có thể chấp nhận.
  • kubectl top nodes hiển thị mức sử dụng, không phải phân bổ. Một node có thể hiển thị 30% CPU usage nhưng có tới 95% CPU được request. Scheduler làm việc dựa trên requests, không phải mức sử dụng thời gian thực. Luôn kiểm tra kubectl describe node và xem phần Allocated resources — đó mới là con số quan trọng.
  • Cluster Autoscaler hoàn vốn rất nhanh. Nếu bạn đang dùng hạ tầng cloud và gặp lỗi này nhiều hơn một lần, autoscaler loại bỏ hoàn toàn nút thắt cổ chai thủ công. Hãy thiết lập nó trước khi cần đến.

Related Error Notes