こんにちは。お久しぶりです。
私事で恐縮ですが、12 月より新しい会社様にお世話になることとなりました。
学生の頃からずっと憧れていた企業様ですので、精一杯頑張ろうと思います。
さて、本題ですが、ローカルの VM に構築した Kubernetes ( CR: containerd ) 環境にて、同じくローカルに用意した Docker Registry に保存されているイメージから Pod を起動しようとしたところ、下記のようなエラーが発生しました。
Failed to pull image "xxx.xxx.xxx.xxx:5000/hoge": failed to pull and unpack image "xxx.xxx.xxx.xxx:5000/hoge:latest": failed to resolve reference "xxx.xxx.xxx.xxx:5000/hoge:latest:latest": failed to do request: Head "xxx.xxx.xxx.xxx:5000/hoge:latest:5000/v2/hoge/manifests/latest": http: server gave HTTP response to HTTPS client Error: ErrImagePull
どうも、TLS 通信周りの問題から、イメージの pull に失敗しているようです。
コンテナランタイムに containerd を使っているのもあり、中々参照できる情報がなかったため、ココに備忘録を残しておきます。
TL;DR
単純に Docker Registry が HTTPS での通信に対応していないだけ。
containerd の設定ファイルを下記のように書き換えて、containerd を再起動すれば OK。
※ xxx.xxx.xxx.xxx は Docker Registry の IP に差し替える。
/etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.configs] [plugins."io.containerd.grpc.v1.cri".registry.configs."xxx.xxx.xxx.xxx:5000".tls] insecure_skip_verify = true [plugins."io.containerd.grpc.v1.cri".registry.headers] [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."xxx.xxx.xxx.xxx:5000"] endpoint = ["http://xxx.xxx.xxx.xxx:5000"]
/etc/containerd/config.toml 差分
[root@verienv ~]# diff /etc/containerd/config.toml /etc/containerd/config.toml.org 150,151d149 < [plugins."io.containerd.grpc.v1.cri".registry.configs."xxx.xxx.xxx.xxx:5000".tls] < insecure_skip_verify = true 156,157d153 < [plugins."io.containerd.grpc.v1.cri".registry.mirrors."xxx.xxx.xxx.xxx:5000"] < endpoint = ["http://xxx.xxx.xxx.xxx:5000"]
やってみる ( 構築 )
・環境
Role | IP address | OS | supplement |
k8s Control | 192.168.33.11 | AlmaLinux 9 | Name: verienv01 |
Docker Registry | 〃 | 〃 | 〃 |
k8s Node | 192.168.33.12 | AlmaLinux 9 | Name: verienv02 |
k8s Control と Docker Registry は同じ VM に同居させるとします。
・構築 ( k8s )
k8s の主要な導入は Ansible Playbook の Role にまとめました。
Playbook を流し終えた後は、README の Memo.Initialization ( Commands after provisioning ) と Node での kubeadm join を実行すれば完了するかと思います。
[root@verienv01 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION verienv01 Ready control-plane 162m v1.28.4 verienv02 Ready <none> 159m v1.28.4
・構築 ( Docker Registry )
Docker Registry はコンテナが用意されているので、公式の通りに導入。
※ nerdctl で入れてしまってもいいかもしれません。
dnf -y install docker-ce docker-ce-cli systemctl enable --now docker docker run -d -p 5000:5000 --name registry registry:2
やってみる ( 検証 )
※ verienv01 で実施します。
※ TL;DR に記載の containerd の設定を全 Node で実施済みとします。
・検証用のコンテナイメージを作成
簡単な HTTP レスポンスを返すコンテナイメージを hello_k8s という名称でビルドします。
cat > ./Dockerfile << EOF FROM python:slim WORKDIR /app EXPOSE 8000 COPY index.html . CMD ["python", "-m", "http.server", "8000"] EOF cat > ./index.html << EOF "Hello from k8s!" EOF docker build -t hello_k8s .
・コンテナイメージを Docker Registry に登録
localhost:5000 のタグを付与してイメージを push します。
※ 他 PC 等から Docker Registry の IP を指定して push する場合は、Docker に insecure-registries の設定が必要です。
docker tag hello_k8s:latest localhost:5000/hello_k8s docker push localhost:5000/hello_k8s
・マニフェスト作成 & apply
Pod を起動する Deployment と NodePort 30080 で接続を受け付ける Service を定義して apply します。
cat > ./deployment.yaml << EOF apiVersion: apps/v1 kind: Deployment metadata: name: hello-k8s spec: replicas: 1 selector: matchLabels: app: hello-k8s template: metadata: labels: app: hello-k8s spec: containers: - name: hello-k8s image: 192.168.33.11:5000/hello_k8s imagePullPolicy: IfNotPresent ports: - containerPort: 8000 EOF cat > ./service.yaml << EOF apiVersion: v1 kind: Service metadata: name: hello-k8s-service spec: selector: app: hello-k8s type: NodePort ports: - protocol: TCP port: 80 targetPort: 8000 nodePort: 30080 EOF
kubectl apply -f deployment.yaml kubectl apply -f service.yaml
・確認
Pod が正常に起動し、レスポンスが返ってくれば成功です!
[root@verienv01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE hello-k8s-77b86d6c8-4mbm2 1/1 Running 0 6m52s [root@verienv01 ~]# curl http://192.168.33.11:30080/ "Hello from k8s!"