趣旨
- k8s(kind) から k8s(minikube) にデプロイした Docker Registry へアクセスしてみようとした
- k8s(kind) の kubelet から利用する
containerdが自己署名証明書を許容しなかった - 設定で回避することもできず諦めた
やったこと
- TLS 通信のための自己署名証明書を作る
- ベーシック認証のための秘密情報ファイルを作る
registry:2をデプロイするためのマニフェストを作成するregistry:2をデプロイするdockerを構成するkindを構成するkindでイメージを実行する
1. TLS 通信のための自己署名証明書を作る
外部から参照可能な名前を指定する。
ローカルネットワークだけで完結する場合は xip.io を利用すると便利。
myhost.<private ip address>.xip.io とすると <private ip address> に解決してくれる。
cn="registry.10.0.0.1.xip.io"
openssl req -newkey rsa:2048 -nodes -x509 -days 3650 \
-subj "/C=JA/ST=Tokyo/L=Shinjuku/CN=${cn}" \
-keyout ./certs/tls.key \
-out ./certs/tls.crt
2. ベーシック認証のための秘密情報ファイルを作る
こちらのイメージを利用する。
docker run --rm -ti xmartlabs/htpasswd testuser pass01 > ./auth/htpasswd
3. registry:2 をデプロイするためのマニフェストを作成する
次のような注意点がある。
## registry.yaml --- apiVersion: apps/v1 kind: Deployment metadata: name: registry labels: app: registry spec: replicas: 1 selector: matchLabels: app: registry template: metadata: labels: app: registry spec: containers: - name: registry image: registry:2 ports: - name: registry containerPort: 5000 volumeMounts: - name: auth mountPath: "/auth" - name: data mountPath: "/var/lib/registry" env: - name: REGISTRY_AUTH_HTPASSWD_REALM value: "basic" - name: REGISTRY_AUTH_HTPASSWD_PATH value: "/auth/htpasswd" volumes: - name: auth secret: secretName: registry-auth - name: data emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: registry labels: app: registry spec: selector: app: registry ports: - name: registry protocol: TCP port: 5000 targetPort: 5000 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: registry annotations: kubernetes.io/ingress.class: "nginx" ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/proxy-body-size: "999m" spec: tls: - hosts: - ${cn} secretName: registry-tls rules: - host: ${cn} http: paths: - path: / backend: serviceName: registry servicePort: 5000
4. registry:2 をデプロイする
名前空間を作る。
kubectl create ns registry
Ingress から参照する secret を作る。
kubectl -n registry create secret tls registry-tls --cert=./certs/tls.crt --key=./certs/tls.key
マニフェストから参照する secret を作る。
kubectl -n registry create secret generic registry-auth --from-file=htpasswd=./auth/htpasswd
マニフェストをデプロイする。
$ cn="registry.10.0.0.1.xip.io" envsubst < ./manifest/registry.yaml | kubectl -n registry apply --dry-run -f - deployment.apps/registry created (dry run) service/registry created (dry run) ingress.extensions/registry created (dry run) $ cn="registry.10.0.0.1.xip.io" envsubst < ./manifest/registry.yaml | kubectl -n registry apply -f - deployment.apps/registry created service/registry created ingress.extensions/registry created
https でアクセスしてみる。
$ curl -k https://${cn}/v2/_catalog
{"repositories":[]}
5. docker を構成する
docker hostの設定./certs/tls.crtを/etec/docker/certs.d/${cn}/ca.crtへ配置する。docker daemonの再起動は不要。
docker clientの設定docker login ${cn}する
docker image push ${cn}/name:tag が成功すれば OK。
Z. minikube の場合に必要なこと
起動するときに minikube start --insecure-registry ${cn}:443 が必要。
insecure-registryオプションはdockerdに直接指定されるsystemdのunitファイルでExecStartに反映されてた
docekrdはsystemdのdocker.serviceとして実行されている
6. kind を構成する
こちらを参照。
minikube で kind を動かす - yujioramaの日記
7. kind でイメージを実行する
レジストリの認証情報を登録する。
kubectl --context=kind create secret docker-registry local-registry \
--docker-server=${cn} \
--docker-username=testuser \
--docker-password=pass01 \
--docker-email=testuser@registry
サービスアカウントに imagePullSecrets を追加。
kubectl --context=kind patch serviceaccount default -p '{"imagePullSecrets": [{"name":"local-registry"}]}'
前の手順で push したイメージを実行。
kubectl --context=kind run d --rm -it ${cn}/debian:buster-slim
ここから上手くいってない。
いろいろ確認した結果
原因は containerd が自己署名証明書による TLS 通信に対応してないことだった。
中間証明局の証明書を OS の証明書チェインに追加するとかそういう方法はあるけど、設定ではどうにもならなそう。
TLS 通信をしない insecure registry なら設定でどうにかなるんだけど。