Cách khắc phục lỗi ErrImageNeverPull trong Kubernetes (imagePullPolicy: Never)

beginner☸️ Kubernetes2026-07-20| Kubernetes (Minikube, Kind, k3s hoặc Managed Clusters), Docker/Containerd runtime

Error Message

Failed to pull image "myapp:latest": rpc error: code = Unknown desc = failed to pull and unpack image: ErrImageNeverPull
#kubernetes#docker#devops#khắc phục sự cố

Tại sao Kubernetes lại chặn Image của bạnBạn vừa build một container image mới ở máy cục bộ và đã sẵn sàng để kiểm tra. Để tiết kiệm thời gian và băng thông, bạn thiết lập imagePullPolicy: Never trong manifest của mình. Điều này yêu cầu Kubernetes bỏ qua các registry bên ngoài như Docker Hub và sử dụng phiên bản đã có sẵn trên máy của bạn. Nhưng thay vì ứng dụng được khởi chạy, Pod lại rơi vào trạng thái Waiting với tỷ lệ thất bại là 100%.

Lỗi ErrImageNeverPull có nghĩa là Kubernetes đang thực hiện đúng theo chỉ dẫn của bạn một cách máy móc. Nó bị cấm kéo image từ cloud, nhưng đồng thời cũng không thể tìm thấy image đó trong bộ nhớ cục bộ của worker node cụ thể nơi Pod được lập lịch. Nếu image không nằm chính xác ở nơi Kubelet mong đợi, việc triển khai sẽ đi vào ngõ cụt.

Đây có phải là vấn đề của bạn?Hãy bắt đầu bằng cách kiểm tra trạng thái pod của bạn để xác nhận lỗi. Chạy lệnh sau:

kubectl get pods

Nếu cột STATUS hiển thị ErrImageNeverPull, bạn cần xem nhật ký sự kiện nội bộ. Sử dụng lệnh describe để xem chính xác Kubelet đang báo lỗi gì:

kubectl describe pod <pod-name>

Cuộn xuống phần Events. Bạn có thể sẽ thấy một cảnh báo như thế này:

Warning  Failed     2s (x2 over 5s)  kubelet  Failed to pull image "myapp:latest": rpc error: code = Unknown desc = failed to pull and unpack image: ErrImageNeverPull

Điều này xác nhận rằng node đã tìm kiếm trong cache cục bộ, không thấy gì, và bị cấu hình của bạn chặn không cho tìm kiếm ở nơi khác.

Các nguyên nhân gốc rễ phổ biến- Lệch Node: Trong một cluster có 3 node, bạn có thể đã build image trên node-1, nhưng Kubernetes lại lập lịch cho Pod của bạn chạy trên node-3. Vì node-3 không có image đó nên Pod sẽ bị lỗi.- Sự cô lập của Cluster cục bộ: Các công cụ như Minikube và Kind chạy bên trong các máy ảo hoặc Docker container riêng của chúng. Máy host của bạn có thể có image, nhưng môi trường Kubernetes nội bộ lại bị cô lập với bộ lưu trữ Docker của máy host.- Sai sót trong Tag Image: Bạn đã build myapp:v1.0.1, nhưng file YAML của bạn lại trỏ đến myapp:latest. Thậm chí một sự sai lệch nhỏ về phiên bản cũng khiến việc tìm kiếm thất bại.- Cấu hình dư thừa: Bạn vô tình để lại imagePullPolicy: Never trong một manifest dành cho môi trường staging hoặc production.## Cách khắc phục### 1. Sử dụng IfNotPresent để linh hoạt hơnThay vì Never, hãy sử dụng IfNotPresent. Điều này yêu cầu Kubernetes sử dụng image cục bộ nếu nó tồn tại, nhưng vẫn cho phép nó tải từ registry nếu không tìm thấy image. Đây là lựa chọn mặc định an toàn nhất cho hầu hết các quy trình phát triển.

Cập nhật file YAML của bạn như sau:

spec:
  containers:
  - name: my-container
    image: myapp:latest
    imagePullPolicy: IfNotPresent

2. Nạp Image vào các Cluster cục bộNếu bạn đang sử dụng Minikube, theo mặc định cluster không thể thấy các image trên hệ điều hành host của bạn. Bạn phải đẩy image vào cache nội bộ của Minikube một cách thủ công:

minikube image load myapp:latest

Đối với người dùng Kind (Kubernetes in Docker), hãy sử dụng lệnh load cụ thể để đồng bộ image từ máy host với các node trong cluster:

kind load docker-image myapp:latest --name your-cluster-name

3. Build trực tiếp bên trong ClusterBạn có thể bỏ qua bước "load" bằng cách trỏ môi trường Docker của terminal trực tiếp vào daemon của Minikube. Chạy lệnh này trước khi bạn build image:

eval $(minikube docker-env)
docker build -t myapp:latest .

Giờ đây, khi bạn build image, nó sẽ được tạo trực tiếp bên trong môi trường Minikube. Kubernetes sẽ tìm thấy nó ngay lập tức ngay cả khi chính sách Never được bật.

4. Xác minh sự hiện diện của Image trên NodeNếu bạn đang quản lý một cluster bare-metal, hãy SSH vào node đang bị lỗi. Bạn cần xác minh image thực sự tồn tại trong cache của runtime. Đối với các cluster hiện đại sử dụng containerd, hãy sử dụng ctr hoặc crictl:

# Cho Containerd
sudo ctr -n k8s.io images list | grep myapp

# Cho Docker runtime cũ hơn
docker images | grep myapp

Xác minh kết quảSau khi bạn đã di chuyển image hoặc cập nhật chính sách, hãy xóa pod đang bị lỗi để Kubernetes có thể tạo lại nó:

kubectl delete pod <pod-name>

Theo dõi tiến trình của pod mới bằng lệnh kubectl get pods -w. Khi thành công, các sự kiện trong describe sẽ hiển thị kết quả khớp cục bộ:

Normal  Pulled     5s  kubelet  Container image "myapp:latest" already present on machine

Mẹo chuyên nghiệp cho phát triển cục bộ- Tránh sử dụng tag 'latest': Theo mặc định, Kubernetes thường coi latest tương đương với imagePullPolicy: Always. Hãy ghi rõ các tag phiên bản (như :dev-1) để tránh nhầm lẫn.- Chú ý đến ngữ cảnh: Luôn kiểm tra kỹ xem Pod của bạn được gán cho node nào. Nếu bạn có nhiều node, bạn phải đảm bảo image có sẵn trên tất cả các node đó.- Dọn dẹp: Việc nạp image (sideloading) tiêu tốn không gian đĩa bên trong các node Minikube hoặc Kind của bạn. Hãy định kỳ chạy minikube ssh "docker image prune -a" để xóa bỏ các bản build cũ.

Related Error Notes