KubernetesでDocker Registryを構築する。
前提
Dockerでコンテナを構築する場合、コンテナイメージを持っていない場合自動的にDocker Hub等からダウンロードする。
これはKubernetesでも同様で、動くワーカノード上でコンテナイメージを持っていなければ自動でダウンロードする。(デフォルト定義の場合)
なので、クローズ環境でKubernetesを動かしたい場合は事前にすべてのワーカノード上に動作させるコンテナイメージを事前にロードしておく必要がある。
docker load -i xxx.tar
ワーカノードが1台とかそんな話であれば問題はないけど、Kubernetes構築する以上○台インストールはあり得る上、それぞれに○個のコンテナイメージロードとか面倒です。
というわけで、KubernetesにDocker Hub的なもの(正式名称:Registry)を立ててそこからアクセスさせようというのが今回の目的です。
環境
Ubuntu 18.04.4 LTS
Docker version 19.03.6, build 369ce74a3c
Kubernetes v1.18(Kubeadm v1.8で3台ノード構築済み)
Rook+Ceph v1.4 (永続ボリューム用)
Rook+Cephの構築については追々書きます。
Docker Registryについて
細かい話は公式に記載しているので、とりあえず置いておいて、DockerでDocker Registryを構築するだけなら次のコマンドで問題ありません。
docker run -d -p 5000:5000 -v /home/user0/registry:/var/lib/registry registry
これでdocker pull localhost:5000/httpd:latest
のように使用することができる。
なお、コンテナにタグlocalhost:5000/xxx
をつけておく必要がある。
しかし、これはlocalhostで接続する場合の話。
ドメイン(またはIPアドレス)で指定する場合、docker pull 192.168.200.5:5000/httpd:latest
のように指定すれば解決かと思いきや、必ずHTTPS通信をするのでregistryコンテナに証明書を設定し起動する必要がある。
もし、registryコンテナ側に証明書の設定がないと次のようにエラーとなる。
マニュアルに証明書の設定方法が記載されているのでそれを参照に設定したところで、適当な証明書では通信してくれない。
めんどくさいことに、自己署名の証明書を入れてもダメ。
ちゃんとした証明書があれば次の章は解決しますが、試験環境など正規な証明書が準備できない場合は次の通り証明書を作成します。
Docker用の証明書を作る
解決法としてはルート証明書をクライアント(Dockerのホスト側)にインストールし、ルート証明書で署名されたサーバ証明書をサーバ(registryコンテナ側)にインストールする方法をとります。
ここではドメインの証明書なので、hostsファイルか(ローカルの)DNSでドメイン名が解決できるようにしておきます。
ルート証明書を作る
ルート証明書の作り方はよく出てるのでコマンドだけ。なお、チャレンジパスワードは空欄でないとエラーになります。
openssl genrsa 2048 > ca.key
openssl req -new -key ca.key > ca.csr
openssl x509 -days 365 -req -signkey ca.key < ca.csr > ca.crt
サーバ証明書を作る
サーバ証明書を作る前に、opensslの作業ファイル等を作ります。
mkdir demoCA
cd demoCA
mkdir private crl certs newcerts
echo "01" > serial
touch index.txt
cd ../
(21.11.28追記)サーバ証明書にSANを追加するため、次のテキストファイルを作ります。
subjectAltName = DNS:*.example.local, IP:192.168.0.1
それで、サーバ証明書を作成しルート証明書で署名します。
この時、サーバ証明書とルート証明書の項目に不一致があるとエラーが発生する項目があります。
openssl genrsa 2048 > server.key
openssl req -new -key server.key > server.csr
openssl ca -days 365 -cert ca.crt -keyfile ca.key -in server.csr -extfile san.txt > server.crt
ルート証明書をDockerのホストに追加する
この項目は、OSによって違うのでUbuntuの場合のみ記載します。
ルート証明書を指定のディレクトリにコピーし、/etc/ca-certificates.conf
ファイルに相対パスで追記します。(この場合はca.crt
と追記)
最後に再読み込みして完了です。
sudo cp ca.crt /usr/share/ca-certificates
sudo nano /etc/ca-certificates.conf
sudo update-ca-certificates
KubernetesでDocker Registryを構築
Kubernetesで構築する場合の説明。
事前準備
・すべてのワーカノードのDockerにコンテナイメージ(registry)を入れておく
・前章の通りサーバ証明書とルート証明書を作る
・ルート証明書を全てのワーカノードに反映しておく
永続ボリュームの作成
Registryのコンテナイメージの保存先(/var/lib/registry/)を作成します。
Webサーバと同じ扱いで特にコンテナごとにPVを分ける必要性もないため、今回の永続ボリュームはrook+cephのファイルストレージで作成します。なお、NFSのPVでも支障はないと思います。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvcregistry
labels:
pvc: registry
spec:
storageClassName: rook-ceph-fs
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
保存したら、kubernetesに読み込ませます。
kubectl apply -f pvc.yaml
サービスの作成
この後Pod(Deployment)を作ったところで、IPアドレスを固定させないとめんどくさいことになるのでサービスで半固定のIPアドレスを発行させます。
サービスでは、LoadBalancer、NodePort、ClusterIPの3種類が選べると思います。Kubernetesクラスタ外部にregistryを公開するのであればLoadBalancer型でいいと思いますが、今回はクラスタ内部だけに使えるregistryとして公開します。(=ClusterIPとして構築)
apiVersion: v1
kind: Service
metadata:
name: srvregistry
spec:
ports:
- name: http
port: 443
protocol: TCP
targetPort: 443
selector:
app: registry
type: ClusterIP
保存したら、kubernetesに読み込ませます。
kubectl apply -f services.yaml
次のコマンドでClusterIPを確認します。
kubectl get services
Kubernetes内の全ノードでドメインがこのIPアドレスへ解決できるようにDNSまたはhostsファイルを設定します。
証明書の保存
kubernetesのsecretにサーバ証明書を保存します。
サーバ証明書ファイルが保存されているディレクトリで次のコマンドを実行します。
kubectl create secret generic scregistry --from-file=server.crt --from-file=server.key
Deploymentの作成
最後にregistryのコンテナを作成します。
ポート番号が443になるように設定変更を行っています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: depregistry
labels:
dep: registry
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry
imagePullPolicy: IfNotPresent
ports:
- containerPort: 443
volumeMounts:
- name: vol
mountPath: /var/lib/registry
- name: conf
mountPath: /certs/
env:
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: /certs/server.crt
- name: REGISTRY_HTTP_TLS_KEY
value: /certs/server.key
- name: REGISTRY_HTTP_ADDR
value: 0.0.0.0:443
volumes:
- name: vol
persistentVolumeClaim:
claimName: pvcregistry
- name: conf
secret:
secretName: scregistry
保存したら、kubernetesに読み込ませます。
kubectl apply -f deployment.yaml
Registryを使ってみる
Dockerで使用する場合
Dockerでpushやpullを使うときは、docker pull (ドメイン名):(ポート番号)/(コンテナ名)
のように定義します。(ただしポート番号が443の場合はポート番号を省略できます)
なお、pushをする場合は事前に(ドメイン名):(ポート番号)/(コンテナ名)
というタグを定義する必要があります。
docker tag ubuntu www.example.co.jp/ubuntu
docker push www.example.co.jp/ubuntu
docker pull www.example.co.jp/ubuntu
Kubernetesで使用する場合
Kubernetesで使用する場合は、yamlファイル内のimage: を(ドメイン名):(ポート番号)/(コンテナ名)
と定義します。
前章のようにregistryを作成した場合(ドメイン名www.example.co.jp、ポート番号443)にPodを作る場合は次のようになります。
apiVersion: v1
kind: Pod
metadata:
name: testpod
spec:
containers:
- name: test
image: www.example.co.jp/httpd:latest
ports:
- containerPort: 80
なお、registryを立ち上げた直後はコンテナイメージがないため、Deployment等でイメージ展開する前に前章の通りコマンドを実行し、registry上にイメージをpushしておく。
(参考)そもそもKubernetesのDeploymentとして構築しない場合
Docker本体でHTTPS通信対応registryを起動させる場合は、以下のコマンドで実行する。または、以下のコマンドを参照し、docker-compose経由で起動する。
docker run -d \
-p 443:443 \
-v /home/user0/registry:/var/lib/registry \
-v /home/user0/certs:/certs/ \
-e REGISTRY_HTTP_TLS_CERTIFICATE:/certs/server.crt \
-e REGISTRY_HTTP_TLS_KEY:/certs/server.key \
-e REGISTRY_HTTP_ADDR:0.0.0.0:443 \
registry
参考文献
レジストリ・サーバのデプロイ — Docker-docs-ja 17.06 ドキュメント
Sanwa Systems Tech Blog | OpenSSLコマンドでオレオレ証明書を作り、ルート認証局としてサーバー証明書を発行する
Author And Source
この問題について(KubernetesでDocker Registryを構築する。), 我々は、より多くの情報をここで見つけました https://qiita.com/amax/items/dc5dd9eaa988dd813ec7著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .