なぜKubernetesはイメージをブロックしているのかローカルで新しいコンテナイメージをビルドし、テストの準備が整いました。時間と帯域を節約するために、マニフェストに imagePullPolicy: Never を設定しました。これはKubernetesに対し、Docker Hubのような外部レジストリをスキップして、マシン上にすでにあるバージョンを使用するように指示するものです。しかし、アプリが起動する代わりに、Podは Waiting 状態のまま、100%の確率で失敗します。
ErrImageNeverPull エラーは、Kubernetesがあなたの指示をあまりにも忠実に守っていることを意味します。クラウドからイメージをプルすることは禁止されていますが、Podがスケジュールされた特定のワーカーノードのローカルストレージ内にもそのイメージが見つからないのです。イメージがKubeletの期待する場所に正確に存在しない場合、デプロイメントは行き詰まってしまいます。
これがあなたの問題ですか?まずはPodのステータスを確認して、エラーを特定しましょう。以下のコマンドを実行してください:
kubectl get pods
STATUS 列に ErrImageNeverPull と表示されている場合は、内部のイベントログを確認する必要があります。describe を使用して、Kubeletが具体的に何を報告しているかを確認します:
kubectl describe pod <pod-name>
下方の Events セクションまでスクロールしてください。おそらく、以下のような警告が表示されているはずです:
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
これにより、ノードがローカルキャッシュを検索したものの何も見つからず、設定によって他を探すことがブロックされたことが確認できます。
よくある根本原因- ノードの不一致: 3ノード構成のクラスターにおいて、node-1 でイメージをビルドしたが、KubernetesがPodを node-3 にスケジュールした場合です。node-3 にはイメージがないため、Podは失敗します。- ローカルクラスターの隔離: MinikubeやKindなどのツールは、独自の仮想マシンやDockerコンテナ内で動作します。ホストマシンにはイメージがあるかもしれませんが、内部のKubernetes環境はホストのDockerストレージから隔離されています。- イメージタグのタイポ: myapp:v1.0.1 をビルドしたのに、YAMLファイルが myapp:latest を指している場合です。わずかなバージョンの不一致でも検索失敗の原因となります。- 設定の消し忘れ: ステージングや本番環境用のマニフェストに、誤って imagePullPolicy: Never を残してしまった場合です。## 解決方法### 1. 柔軟性を高めるために IfNotPresent を使用するNever の代わりに IfNotPresent を使用してください。これにより、ローカルにイメージが存在すればそれを使用し、存在しない場合はレジストリへ取得しに行くようKubernetesに指示できます。ほとんどの開発ワークフローにおいて、これが最も安全なデフォルト設定です。
YAMLを以下のように更新します:
spec:
containers:
- name: my-container
image: myapp:latest
imagePullPolicy: IfNotPresent
2. ローカルクラスターにイメージをサイドロードするMinikube を使用している場合、デフォルトではクラスターからホストOS上のイメージを見ることはできません。手動でイメージをMinikubeの内部キャッシュにプッシュする必要があります:
minikube image load myapp:latest
Kind (Kubernetes in Docker) ユーザーの場合は、特定のロードコマンドを使用してホストのイメージをクラスターノードと同期させます:
kind load docker-image myapp:latest --name your-cluster-name
3. クラスター内部で直接ビルドするターミナルのDocker環境をMinikubeのデーモンに直接向けることで、「ロード」の手順をスキップできます。イメージをビルドする前に、以下のコマンドを実行してください:
eval $(minikube docker-env)
docker build -t myapp:latest .
これで、イメージをビルドするとMinikube環境内に直接作成されます。Never ポリシーが有効であっても、Kubernetesは即座にイメージを見つけることができます。
4. ノード上のイメージの存在を確認するベアメタルクラスターを管理している場合は、失敗しているノードにSSHでログインしてください。ランタイムのキャッシュに実際にイメージが存在するか確認する必要があります。containerd を使用している最近のクラスターでは、ctr または crictl を使用します:
# containerdの場合
sudo ctr -n k8s.io images list | grep myapp
# 古いDockerランタイムの場合
docker images | grep myapp
修正の確認イメージを移動させるかポリシーを更新したら、失敗しているPodを削除してKubernetesに再作成させます:
kubectl delete pod <pod-name>
kubectl get pods -w で新しいPodの進捗を監視します。正常に動作すると、describe のイベントにローカルでの一致に成功したことが表示されます:
Normal Pulled 5s kubelet Container image "myapp:latest" already present on machine

