Logicky Blog

Logickyの開発ブログです

k8sでローカル環境でイメージがあるのにpullエラーになるときはimagePullPolicyがデフォルトになっているかもしれない

今k8sとTiltを使っているのですが、結構な頻度で、再起動時にトラブルが起きます。あるPODがうまく起動しないのです。 イメージはありますが、ErrImgaePullになるのです。

ここからは実験をしていきます。

まず問題のPODのイメージを削除します。このイメージは、TiltのダミーのDeploymentの起動時にビルドされます。 なので、tiltを再起動しないで、起動しようとすると、pull errorみたいなやつになります。やってみましょう。

ErrImagePullでした。あれ、いつもとエラーが違う。いつもはImagePullBackoffみたいなやつだったような。。

ここで、ErrImagePullの意味を調べましょう。

これは勉強になります。ありがとうございます。

sysdig.jp

KubernetesがPod内のコンテナ用のイメージをプルしようとすると、うまくいかないことがあります。ErrImagePull ステータスは、 kubelet が Pod 内のコンテナを起動しようとしたが、Pod、デプロイ、または ReplicaSet マニフェストに指定されたイメージに何か問題があった場合に表示されます。

ではログを見てみます。

> kubectl logs hoge-pod
Error from server (BadRequest): container "hoge" in pod "hoge-podl" is waiting to start: trying and failing to pull image

これはPod の起動時にイメージの pull (取得) に失敗していることを示しているそうです。まあ、イメージないですからね。

ImagePullBackOff は Kubernetes における Pod のステータスの一つで、コンテナイメージの pull (取得) に失敗し、再試行している状態 を示します

なるほど。これはGeminiさんの発言ですが、要するに再試行中の状態ってことですね。どっちにしてもイメージのpullに失敗したことが分かるわけですね。 さて、では、イメージをビルドしましょう。

私はTiltを使っており、tilt upで自動的にビルドするようになっています。やってみます。

> minikube image ls
imageないです
> tilt up
> minikube lmage ls
imageありました

さあこれでpull自体はできるはずですね。もう一度POD起動してみましょう。

結果は、ErrImagePullでした。これはつまりイメージが壊れている、エラーが出ているってことですかね。 ログを見てみましょう。

あれ、同じログですね。。。おわた。。 つまり、minikube image lsで存在が確認できているのに、イメージのpullに失敗するケースがあるってことでしょうか?

describeというのをやってみます。

> kubectl describe po hoge-pod
....
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  10m                  default-scheduler  Successfully assigned default/hoge-pod to minikube
  Normal   Pulling    8m56s (x4 over 10m)  kubelet            Pulling image "hoge/hoge-image:latest"
  Warning  Failed     8m53s (x4 over 10m)  kubelet            Failed to pull image "hoge/hoge-image:latest": Error response from daemon: pull access denied for hoge/hoge-image, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
  Warning  Failed     8m53s (x4 over 10m)  kubelet            Error: ErrImagePull
  Warning  Failed     8m39s (x6 over 10m)  kubelet            Error: ImagePullBackOff
  Normal   BackOff    22s (x41 over 10m)   kubelet            Back-off pulling image "hoge/hoge-image"

上記について、Claude3.7様によりますと

ここで重要なポイントは:
"repository does not exist or may require 'docker login'" - これは Docker Hub などの外部レジストリを探しに行っている証拠です
"pull access denied" - 外部レジストリへのアクセス権がないか、そもそもそのリポジトリが存在しないことを示しています
"requested access to the resource is denied" - 外部リソースへのアクセスが拒否されています
つまり、Kubernetes は minikube のローカルイメージを見に行くのではなく、Docker Hub などの外部レジストリから hoge/hoge-image を pull しようとして失敗しているんです 🔍

だそうです。なるほど。。。 ここで既に3回目位なことに気づきました。

        self.k8s.create_deployment(
            name=deployment_name,
            namespace="default",
            labels=labels,
            container_image=container_image,
            container_name=container_name,
            container_port=container_port,
            env_vars=env_vars,
            image_pull_policy=image_pull_policy,
        )

上記のimage_pull_policyを設定しておりませんでした。その結果デフォルトのAlwaysになっていて、これは毎回外部をチェックする的な意味のようです。 そこでimage_pull_policyを追加して、値は「Never」にしました。これはローカルイメージしか見ないそうです。

はて、これで再度試したら、正常起動(Running)しました。

一応、image_pull_policyを「IfNotPresent」にして、試してみます。 これでもいけました。これなら本番感動時もよさげなので、こっちにしておきます。

まとめ

多分結構な頻度でエラーになっているのは、tiltの再起動をせずにpod起動をしようとして純粋にイメージがない場合と、上記のようにコードを修正した結果imagePullPolicyが消えて外部を見に行っているのと、イメージにエラーがあって起動できないのと、があるのかなあと思った。全てにおいて kubectl get po からの kubectl logs {pod name}kubectl describe po {pod name} によって、明確になるはずなので、これをps1ファイルにしておこうと思いました。