趣旨
- 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 なら設定でどうにかなるんだけど。