LoginSignup
1
0

自分で作ったコンテナレジストリにdocker pushし、KubernetesのPodをデプロイする

Last updated at Posted at 2024-03-29

はじめに

Dockerのコンテナイメージを、自分で作ったコンテナレジストリにpushしてDockerやKubernetesからpullして運用する方法について本記事にまとめます。Docker Hubやクラウドのコンテナレジストリを使う手もあると思いますが、多くの場合はそれなりの費用が掛かります。なので既存のコンテナレジストリサービスを使わず、自分でコンテナレジストリを作ってコストを節約したい方などの参考になれば幸いです。

本記事に記載する内容は以下です。

  • Dockerを使ってコンテナレジストリを作成する方法
  • 作成したコンテナレジストリにDockerからpushおよびpullする方法
  • KubernetesのPodに自作コンテナレジストリのイメージをpullしてデプロイする方法

前提条件

  • OS : Linux
    • 動作確認したのはUbuntuとDebian
  • インストールが必要なツール
    • Docker
    • Kubernetesクラスター
      • 筆者が作成したものですが、k8s-setup等を使って構築可能です
      • 尚、K8sクラスターが使うコンテナランタイムはcontainerdであることを想定しています

コンテナレジストリの作成

コンテナイメージを格納するためのコンテナレジストリを作成します。

docker run -d --name docker-registry -p 5000:5000 registry

コンテナが起動しているのを確認します。

$ docker ps -f "name=registry"
CONTAINER ID   IMAGE        COMMAND                   CREATED         STATUS         PORTS                                       NAMES
cadcd49f9a3a   registry     "/entrypoint.sh /etc…"   7 minutes ago   Up 7 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   docker-registry

また、HTTPでコンテナレジストリのサービスが提供されているのを確認します。
[hostname]の部分は実際には、コンテナレジストリを起動したマシンのホスト名やIPアドレスを記入します。

$ curl -k http://[hostname]:5000/v2/_catalog
{"repositories":[]}

コンテナレジストリにpushできる状態にする

docker pushが"できない"ことを確認

まずは「作成したコンテナレジストリにpushできない」ことを、busyboxのコンテナイメージで確認してみます。

以下のコマンドで、Docker Hubからbusyboxのコンテナイメージを取得後、自分で作ったコンテナレジストリにpushするために別名をつけます。

docker pull busybox:1.36.1
docker tag busybox:1.36.1 [hostname]:5000/busybox:1.36.1

このままコンテナレジストリにpushしようとすると、敢えなく失敗します。

$ docker push [hostname]:5000/busybox:1.36.1
The push refers to repository [[hostname]:5000/busybox]
Get "https://[hostname]:5000/v2/": http: server gave HTTP response to HTTPS client

ログより、DockerはレジストリのデフォルトのプロトコルはHTTPSを想定しているようです。今回pushしたいレジストリはHTTPなので、HTTPのレジストリにpushできるようにDockerの設定を変更する必要があります。

docker pushとpullを可能にするための設定

/etc/docker/daemon.jsonを編集して、insecure-registriesにコンテナレジストリのホスト名とポートを追記します。

/etc/docker/daemon.jsonの一部
{
  "insecure-registries": ["[hostname]:5000"]
}

Dockerサービスを再起動します。

sudo systemctl restart docker

サービス再起動によりコンテナレジストリも止まってしまった場合は、以下のコマンドでコンテナレジストリを再起動させる必要があります。

docker start docker-registry

docker pushできる事を確認

再びコンテナイメージのpushを試みると、問題なくpushできるはずです!

$ docker push [hostname]:5000/busybox:1.36.1
The push refers to repository [[hostname]:5000/busybox]
95c4a60383f7: Pushed
1.36.1: digest: sha256:db16cd196b8a37ba5f08414e6f6e71003d76665a5eac160cb75ad3759d8b3e29 size: 527

コンテナレジストリのHTTPサービスにアクセスして、busyboxのイメージが追加されていることも確認できます。

$ curl -k http://[hostname]:5000/v2/_catalog
{"repositories":["busybox"]}

一旦ローカルのコンテナイメージを消して、pushしたコンテナイメージがpullできることも確認してみましょう。

docker rmi [hostname]:5000/busybox:1.36.1
docker rmi busybox:1.36.1

問題なくpullできました!

$ docker pull [hostname]:5000/busybox:1.36.1
1.36.1: Pulling from busybox
3a2e9cc4b126: Pull complete
Digest: sha256:db16cd196b8a37ba5f08414e6f6e71003d76665a5eac160cb75ad3759d8b3e29
Status: Downloaded newer image for [hostname]:5000/busybox:1.36.1
[hostname]:5000/busybox:1.36.1

KubernetesのPodをデプロイしてみる

続いて、自作のコンテナレジストリにpushしたbusyboxのコンテナイメージを使って、KubernetesのPodを立ち上げるための設定を行なっていきます。

コンテナイメージがpullできないことの確認

まずは何も設定せずにbusyboxのコンテナイメージでPodをデプロイしてみましょう。

kubectl run busybox-tmp -n default \
--image=[hostname]:5000/busybox:1.36.1 \
--command -- tail -f /dev/null

現状だと上手くpullできません。

$ kubectl get pod -n default
NAME          READY   STATUS         RESTARTS   AGE
busybox-tmp   0/1     ErrImagePull   0          8s

詳細を見ると、「https://[hostname]:5000にアクセスできない」とメッセージが出ていることを確認できます。

$ kubectl describe pod -n default busybox-tmp | grep -A 32 ^Event
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  85s                default-scheduler  Successfully assigned default/busybox-tmp to livaz
  Normal   Pulling    45s (x3 over 84s)  kubelet            Pulling image "[hostname]:5000/busybox:1.36.1"
  Warning  Failed     45s (x3 over 84s)  kubelet            Failed to pull image "[hostname]:5000/busybox:1.36.1": failed to pull and unpack image "[hostname]:5000/busybox:1.36.1": failed to resolve reference "[hostname]:5000/busybox:1.36.1": failed to do request: Head "https://[hostname]:5000/v2/busybox/manifests/1.36.1": http: server gave HTTP response to HTTPS client
  Warning  Failed     45s (x3 over 84s)  kubelet            Error: ErrImagePull
  Normal   BackOff    15s (x4 over 83s)  kubelet            Back-off pulling image "[hostname]:5000/busybox:1.36.1"
  Warning  Failed     15s (x4 over 83s)  kubelet            Error: ImagePullBackOff

pull可能にするための設定

上記の問題を解消して、自作コンテナレジストリのイメージをKubernetesで使えるための設定をしていきます。

本記事では、K8sのコンテナランタイムにcontainerdを使っていることが前提となります。dockerdやcri-o等の他のコンテナランタイムを使っている場合は、各コンテナランタイムに応じた設定を行なってください。

/etc/containerd/config.toml に以下を追記します。

/etc/containerd/config.tomlの一部
[plugins."io.containerd.grpc.v1.cri".registry]
   config_path = "/etc/containerd/certs.d"

次のように、[hostname]:5000という名前のディレクトリを作成します。

sudo mkdir -p /etc/containerd/certs.d/[hostname]:5000

作成したディレクトリ内に、hosts.tomlというファイルを作成します。

sudo touch /etc/containerd/certs.d/[hostname]:5000/hosts.toml

hosts.tomlは次のような内容になるように編集します。

hosts.toml
server = "http://[hostname]:5000"

[host."http://[hostname]:5000"]
  capabilities = ["pull", "resolve"]
  skip_verify = true

設定を反映させるために、containerdを再起動します。

sudo systemctl restart containerd

一旦Podを消して、再び同じPodを作ります。
(本当は消さなくてもいいかもしれないですが、なるべく早くpullできることを確認するためにそうしました。)

kubectl delete po -n default busybox-tmp
kubectl run busybox-tmp -n default \
--image=[hostname]:5000/busybox:1.36.1 \
--command -- tail -f /dev/null

今度は問題なくPodを起動できました!

$ kubectl get pod -n default
NAME          READY   STATUS    RESTARTS   AGE
busybox-tmp   1/1     Running   0          14s
$ kubectl describe pod -n default busybox-tmp | grep -A 32 ^Event
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  34s   default-scheduler  Successfully assigned default/busybox-tmp to livaz
  Normal  Pulling    33s   kubelet            Pulling image "[hostname]:5000/busybox:1.36.1"
  Normal  Pulled     32s   kubelet            Successfully pulled image "[hostname]:5000/busybox:1.36.1" in 873ms (873ms including waiting)
  Normal  Created    32s   kubelet            Created container busybox-tmp
  Normal  Started    32s   kubelet            Started container busybox-tmp

おわりに

今回書いた内容は、約一年半前に筆者が書いた以下の記事にも実は出てきます。

この記事は「KubernetesのOperator作成を自分で作ったコンテナレジストリで実現する」ために書いたものですが、当時一番やりたかったのはKubernetesのOperator作成で、自作レジストリに関する設定はそれを実現するために必要になってしまったから仕方なくやったという位置づけでした。
そして最近になって自作レジストリ周りの設定をやり直す機会があったのですが、過去に上の記事に書いてまとめたのをすっかり忘れている自分がいました。「確かどこかにその記録をしていたはず」と思い、自分のメモやQiitaの記事を時間をかけて探してもなかなか見つからず。。。自分のメモの中に「KubernetesのOperator作成の記事に前に書いた」みたいな一言が書かれていたおかげて、ようやく設定ができたという顛末でした。
「自分が書いたものでも見つからないんだから、他の人が見つけるのはなおさら困難だろうなあ」と思い、自作コンテナレジストリの部分だけ切り出して改めて本記事にまとめてみました。お役に立てれば幸いです。

参考にしたサイト

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0