Kubernetes上にプライベートなコンテナリポジトリを建てる時の自分用メモ
- https対応
- Ingressでssl/tlsの終端を行う
- 自己署名証明書を使用
- 証明書はcert-managerで発行&管理
- コンテナリポジトリはHarborを使用
前提
- 作業端末にhelmがインストール済み
- k8sクラスタ内にcert-managerがデプロイ済み
- k8sクラスタ内にIngress Controller(筆者環境ではNGINX Ingress Controllerを使用)がデプロイ済み
手順
namespace作成
コンテナリポジトリ(Harbor)をデプロイするnamespaceを準備しておく
kubectl create ns harbor
自己署名証明書の作成
ここではcert-managerを使って作成
cert-managerを使わない場合は、opensslコマンド等でCA証明書作成 → k8s secret化という流れでも同じことができる
まずは自己署名用の認証局(CA)を作成する
cert-managerはIssuer(またはcluster-issuer)というカスタムリソースによって認証局を管理する
# 認証局(自己署名用)のマニフェスト
$ cat issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: harbor-issuer
namespace: harbor
spec:
selfSigned: {}
# 認証局作成
$ kubectl apply -f issuer.yaml
つぎに作成した認証局を使ってCA証明書を発行する
cert-managerはCertificateというカスタムリソースによって証明書を管理する
# CA証明書のマニフェスト
$ cat cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: harbor-cert
namespace: harbor
spec:
secretName: harbor-tls
commonName: core.harbor.yourdomain.com #後ほど作成するingressのホスト名と合わせておく
dnsNames:
- core.harbor.yourdomain.com #後ほど作成するingressのホスト名と合わせておく
issuerRef:
name: harbor-issuer # 前の手順で作成した認証局の名前を指定
kind: Issuer
group: cert-manager.io
# 証明書作成
$ kubectl apply -f cert.yaml
Certificateリソースのspec内で指定した名前で、CA証明書を含むsecretリソースが作成される
$ kubectl get secret -n harbor harbor-tls
NAME TYPE DATA AGE
harbor-tls kubernetes.io/tls 3 65m
Harborのデプロイ
ここではhelmを使ってデプロイする。こちらのドキュメントを参照。
# helmチャートをダウンロードして展開
$ helm repo add harbor https://helm.goharbor.io
$ helm fetch harbor/harbor --untar
$ cd harbor
# パラメータファイルを編集
$ cp values.yaml values-custom.yaml
$ vim values-custom.yaml
$ diff values.yaml values-custom.yaml
19c19
< certSource: auto
---
> certSource: secret # 前の手順にてcert-managerで作成した証明書(secretリソース)を利用するため、"secret"を指定
28c28
< secretName: ""
---
> secretName: "harbor-tls" #Certificateリソースによって作成されたsecretリソース名
36,37c36,37
< core: core.harbor.domain
< notary: notary.harbor.domain
---
> core: core.harbor.yourdomain.com #自環境のドメイン名に書き換え(CertificateリソースのdnsNameに合わせる)
> notary: notary.harbor.yourdomain.com #自環境のドメイン名に書き換え
47c47
< className: ""
---
> className: "nginx" #自環境におけるIngress Classの名称に書き換え
127c127
< externalURL: https://core.harbor.domain
---
> externalURL: https://core.harbor.yourdomain.com #自環境のドメイン名に書き換え(CertificateリソースのdnsNameに合わせる)
# helmを使用してHarborをインストール
$ helm install my-harbor . -n harbor -f values-custom.yaml
# 各podの稼働確認
$ kubectl get pod -n harbor
NAME READY STATUS RESTARTS AGE
my-harbor-chartmuseum-765c5f5845-vq6v8 1/1 Running 0 143m
my-harbor-core-7f6fbdcb7d-82jkm 1/1 Running 0 143m
my-harbor-database-0 1/1 Running 0 143m
my-harbor-jobservice-6f5dc8655b-drkv9 1/1 Running 3 (143m ago) 143m
my-harbor-notary-server-697b5d79d9-m4kfm 1/1 Running 1 (143m ago) 143m
my-harbor-notary-signer-788cf6c74c-tjq9t 1/1 Running 1 (143m ago) 143m
my-harbor-portal-97c89d9b4-tfp5r 1/1 Running 0 143m
my-harbor-redis-0 1/1 Running 0 143m
my-harbor-registry-5886497567-gnltv 2/2 Running 0 143m
my-harbor-trivy-0 1/1 Running 0 143m
# ingressリソースの確認
$ kubectl get ingress -n harbor
NAME CLASS HOSTS ADDRESS PORTS AGE
my-harbor-ingress nginx core.harbor.yourdomain.com 10.128.213.144 80, 443 144m
my-harbor-ingress-notary nginx notary.harbor.yourdomain.com 10.128.213.144 80, 443 144m
デプロイ完了後、https://(my-harbor-ingressのホスト名)にアクセスすると、HarborのGUIが表示される。初期パスはadmin/Harbor12345。
証明書のインストール
この時点でdockerコマンドでのリポジトリへのアクセスや、k8sノードからのイメージプルを試みるとX509エラーが出力される。
$ sudo docker login core.harbor.yourdomain.com
Username: admin
Password:
Error response from daemon: Get "https://core.harbor.yourdomain.com/v2/": x509: certificate signed by unknown authority
回避するために下記のマシンにCA証明書をインストールする。
- docker pushを実行するクライアント
- k8sクラスタ内の各ノード
手順はOSによって異なるが今回の環境では全てUbuntu 20.04 LTSを使用している。
まずはcert-managerで管理されているCA証明書をエクスポートする
# k8s secretからCA証明書をエクスポート
$ kubectl get secret -n harbor harbor-tls -o jsonpath='{.data.ca\.crt}' | base64 -d > harbor.crt
エクスポートしたCA証明書をSCP等で各マシンにコピーした上で、以下を実施
# 証明書を格納
# 格納先は/usr/share/ca-certificatesではないことに注意
$ cp harbor.crt /usr/local/share/ca-certificates
# 証明書を適用
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
# dockerデーモン再起動
$ sudo snap stop docker
$ sudo snap start docker
これで設定は完了。あとは適宜リポジトリへのアクセス確認などを行う。
$ sudo docker login core.harbor.yourdomain.com
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/snap/docker/2343/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded