はじめに
Kubernatesクラスタを構成する場合には、どこのノードからも同一のDocker イメージの参照が できるように、Docker イメージの照会及び登録するレジストリが必要になります。 (KubernatesのPodは、原則どこのノードでも動作する可能性があるため)
一般的には、利用するクラウドサービス(Google/AWS/IBM..)が提供しているレジストリサービ スを利用することが普通であると思いますが、学習のために自前でレジストリサービスを構築 することにチャレンジします。
作業環境
- ハードウエア Raspberry Pi 3B x 3台、4B x 2台
- Kubernates version 1.18.2
レジストリの選択
Dockerイメージのレジストリとしては、クラスタ内外を含めたの様々な構成ができますが、以 下の3パターンが一般的な構成になります。
- パブリックレジストリを利用(Docker Hub)
- クラウドサービスの提供するプライベートレジストリを利用(Google/IBM/AWSのContainer Registory等)
- 自前でプライベートレジストリを構築
可用性、運用・保守性、移行性等々を考慮すれば、1. または 2. から選択することが望ましい ですが、Kubernatesの構築を通じて、Kubernatesを理解することが目的であるので、ここでは、 「3. 自前でプライベートレジストリを構築」 を選択します。
作業ステップ概要
作業が間違っていないことを確認して進めるために、以下の作業手順でレジストリサービスを構築していきます。
- 設計する
- レジストリをDockerコマンドで実行し、ローカル接続ができることを確認
- レジストリをDockerコマンドで実行し、リモート接続ができることを確認
作業ステップ
設計する
作成するレジストリに対して、想定している設定内容を以下で記述する。
設定 | 内容 | 補足 |
---|---|---|
通信方式 | TLS 1.2 | HTTPのみではノード間での通信ができない |
サーバー認証 | 自己証明書 | 無料で済ませるため |
サーバー名 | レジストのサーバー名 | 実行例は rasp-registry |
ポート番号 | レジストのポート番号 | 実行例は 5000 |
TLS 1
通信をTLSと自己証明書で構築する理由は、それしか選択肢がないからです。
ローカル接続
Dockerの機能のみを利用して、ローカル接続ができるレジストリの構築ができることを確認します。
$ sudo mkdir -p /var/local/volume
$ docker run -d -p 5000:5000 --name registry --hostname registry --restart on-failure:10 -v /var/local/volume:/var/lib/registry registry:2
/var/local/volume を Docker イメージを登録するレジストリのディレクトリになります。 docker ps として、registry:2 イメージが稼働していれば、完了です。
# パブリックリポジトリからイメージを入手
$ docker pull hello-world
# タグを追加する
$ docker tag hello-world localhost:5000/hello-world
# プライベートリポジトリにイメージを登録
$ docker push localhost:5000/hello-world
# プライベートリポジトリにからイメージが入手
$ docker pull localhost:5000/hello-world
docker image でイメージが入手できたことを確認することができます。 ノード内で利用可能なレジストリであるため、localhost を利用してイメージを参照します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 851163c78e4a 6 months ago 4.85kB
localhost:5000/hello-world latest 851163c78e4a 6 months ago 4.85kB
ノード内で実行できることが確認できたので、コンテナーを削除しておきます。
# CONTAINER ID を確認する
$ docker ps | grep registry
# コンテナを停止させ、削除します。
$ docker stop [CONTAINER ID]
$ docker rm [CONTAINER ID]
リモート接続
Dockerの機能のみを利用して、リモート接続ができるレジストリの構築ができることを確認し ます。
TLS通信で利用するための証明書を生成します。今回は外部に公開せず、Kubernatesのテスト環 境であるため自己証明書を利用します。
以下のコマンドでは、x509自己署名証明書を4096ビットのRSA秘密鍵を生成しています。
自己署名証明書作成時に、Common Nameを聞いてくるので、このサーバーにアクセスする際の 名前と一致させて置く必要があります。
domain.key が秘密鍵ファイル、domain.crtが証明書ファイルになります。
mkdir -p ~/tmp/certs
cd ~/tmp/certs
openssl req -newkey rsa:4096 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
自己証明書を利用して、レジストリの実行を確認します。秘密鍵と証明書ファイルとは先ほど 作成したファイルパスを指定します。以下では、ホスト側のファイルパス ~/tmp/certs を コ ンテナ側の /ファイルパス certs で参照できるようにして、起動をしています。
REGISTRY_HTTP_TLS_CERTIFICATE、REGISTRY_HTTP_TLS_KEY の環境変数には、それぞれ、証明書 ファイル、秘密鍵ファイルの指定をします。コンテナ側のプロセスが参照するために、コンテナ側のファイルパスで指定をします。
docker run -d -p 5000:5000 \
-v ~/tmp/certs:/certs \
-v /var/local/volume:/var/lib/registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
--restart=always --name registory registry:2
各ノードの設定
各ノードからレジストリに接続するためには、レジストリの証明書を各ノード上のDockerサーバーに登 録する必要があります。そのためには、以下の作業をする必要があります。
- Docker サーバーが管理する証明書のディレクトリ(/etc/docker/certs.d/レジストリのホ スト名:ポート番号)を作成する。
- 作成した証明書のディレクトリに、証明書ファイルを ca.crt の名称で複写する
- Docker サーバーの再起動をします。
# Docker サーバーの証明書のディレクトリを作成する
$ sudo mkdir -p /etc/docker/certs.d/rasp-registry:5000
$ cd /etc/docker/certs.d/rasp-registry:5000
# 証明書のコピーとサーバーの再起動
$ sudo scp pi@証明書を作成したホスト:証明書の生成パス/domain.crt ca.crt
$ sudo service docker restart
レジストリが各ノードからアクセスできることを確認しています。 お馴染みの hello-world が pull できることを確認します。 (hello-worldは、事前に push しなくても登録されている様でした)
$ docker pull rasp-registry:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
4ee5c797bcd7: Pull complete
Digest: sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
Status: Downloaded newer image for rasp-registry:5000/hello-world:latest
$ docker run rasp-registry:5000/hello-world
確かに実行をすることもできました。
参考情報
- Dockerの日本語サイト
- Dockerの英語サイト
- privateなdockerレジストリを構築する - Qiita
Docker Private Registryの構築 on Kubernetes https://qiita.com/khk-h/items/c4bf26d771f5a4a78ae6
Test an insecure registry https://docs.docker.com/registry/insecure/
Footnotes
1 Transport Layer Securit