Tanzu Mission ControlでHarborを持ち込みの証明書を使ってインストールする

Tanzu Mission Control(以下TMC)を活用し、なるべくCLIを使わずクラスタ構築からHarborの起動までをやってみる。


最初にHarborで使うドメインを環境変数で定義しておく。
```sh
export MYDOMAIN="harbor.tkg.tanzu"
```
この変数は色々なところで使い回すので、作業を中断してログアウト等した場合は再度設定するのを忘れないこと。

## Harborの証明書の準備
Harborの証明書を持ち込んだ想定で実施するが、とはいいつつ正式な証明書を用意するのは面倒なので、自己署名証明書を手動で作成し、これを持ち込んでHarborを立ち上げる。
Harborの自己署名証明書の作成手順はHarborの[公式サイトの手順](https://goharbor.io/docs/2.8.0/install-config/configure-https/)を参考にした。
証明書の中身の説明は本旨ではないのでここでは省略する。
```sh
mkdir harbor-cert
cd harbor-cert
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -sha512 -days 3650 \
    -subj "/C=CN/ST=Tokyo/L=Tokyo/O=example/OU=Personal/CN=$MYDOMAIN" \
    -key ca.key \
    -out ca.crt
openssl genrsa -out ${MYDOMAIN}.key 4096
openssl req -sha512 -new \
    -subj "/C=CN/ST=Tokyo/L=Tokyo/O=example/OU=Personal/CN=$MYDOMAIN" \
    -key ${MYDOMAIN}.key \
    -out ${MYDOMAIN}.csr
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=$MYDOMAIN
DNS.2=yourdomain
DNS.3=hostname
EOF
openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in ${MYDOMAIN}.csr \
    -out ${MYDOMAIN}.crt
cd -
```

## Workload Clusterをデプロイする
Tanzu Mission ControlからWorkload Clusterを作成する。
証明書を持ち込んでのクラスタ作成は以前書いた以下の記事を参考に実施する。
- [TMCでクラスタ作成時にHarborの証明書を埋め込む](https://qiita.com/ipppppei/items/f917db1633026058227a)

上記の記事でまとめているので、ここでは作成手順は割愛する。

## Harborの前提パッケージのインストール
Harborの前提としてContourが必要であり、Contourの前提としてcert-managerが必要なので、それぞれをTMCでインストールする。
TMCで作成したクラスタを選択後、`Add-ons`->`BROWSE PACKAGES`からcert-managerの下の`INSTALL PACKAGE`を選択する
![1693376172291.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/4a56f707-dcd6-a088-8334-7a685a605206.png) 
次に`kind: PackageInstall`や`kind: App`をインストールするNamespaceを指定する。
右上の`CARVEL SETTINGS`をクリックし、Namespaceを指定する。
![1693379203734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/dbb4bc74-f001-fcc8-6b84-086e97ebcb46.png)
 
なお、Namespaceを指定しない場合はNamespaceが自動で生成される。

`Package name`は`cert-manager`とし、その他は変更せずに`INSTALL PACKAGE`をクリックしてインストールを実行する。
インストールが完了すると、GUI上からcert-managerの状態が緑色✅で表示される。
![1693376420510.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/b7de8822-6b34-8487-e9bc-4d6bf2f087c4.png)
同じ手順でContourもインストールする。
Contourのvalues.yamlは[こちら](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/2.3/using-tkg/workload-packages-contour.html#deploy-contour-into-the-workload-cluster-2)でベースが公開されているのでこれをコピーして`Overlay YAML`のところに貼り付ける。
`NodePort`ではなくLoadbalancerIPで公開するため、貼り付けた後に`envoy.service.type`を`LoadBalancer`に変更している。
![1693377716017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/15cb349f-3174-cc03-3194-831ed46a23aa.png)
`Package name`を`contour`として`INSTALL PACKAGE`をクリックしてインストールを実行する。
インストールが完了すると、GUI上からcontourの状態が緑色✅で表示される。
![1693377550477.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/31f56019-f240-732e-dbfa-0b8bab8f27a2.png)

## Harborのインストール
Harborのインストール画面で、`GENERATE YAML FROM TABLE`からベースとなるvalues.yamlを生成する。（なお、CLIの手順と比べて編集項目が増え、パスワードも自動で生成されないため、編集項目を減らしたい人は[CLIの手順](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.3/tkg-deploy-mc/workload-packages-harbor.html#-harbor--4)でvalues.yamlを作るのを推奨する）
![1693382337074.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/2906aa7a-15b2-82dc-1a53-b295452a03fd.png) 
コピーして、一旦harbor-data-values.yamlという名前で保存する。
保存したものを編集し、以下の項目を編集する。
- generate-passwords.shで設定される項目
  - `core.secret`
  - `core.xsrfKey`
  - `database.password`
  - `harborAdminPassword` ※ログイン時に利用する
  - `jobservice.secret`
  - `secretKey`
- `contourHttpProxy.idleTimeout`: 30m
- `contourHttpProxy.timeout`: 30m
- `hostname`:　環境変数`MYDOMAIN`と同じ値を指定
- `tlsCertificate."ca.crt"`: 作成した自己証明書のca.crt
- `tlsCertificate."tls.crt"`: 作成した自己証明書の${MYDOMAIN}.crt
- `tlsCertificate."tls.key"`: 作成した自己証明書の${MYDOMAIN}.key

作成したharbor-data-values.yamlをContourの時と同じように`Overlay YAML`のところに貼り付けてインストールを実施する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c337d99e-cd8e-32e9-ff5c-b0c3be8e2800.png)
インストールが完了し、$MYDOMAINのアドレスがContourのExternalIPとなるよう名前解決できていれば、Harborにログインできる。
![1693386078484.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/e7610722-563c-dd75-618d-bb7065b967eb.png)

## Harborの利用
### dockerコマンドでpushする
Dockerで利用するために、Harborの証明書をdockerdに読み込ませる。
```sh
sudo mkdir -p /etc/docker/certs.d/${MYDOMAIN}/
sudo cp ./harbor-cert/ca.crt /etc/docker/certs.d/${MYDOMAIN}/
sudo systemctl restart docker
```
docker loginする。
```sh
echo 'xxxx' | docker login -u admin --password-stdin  ${MYDOMAIN}
```

イメージをpushする。
```sh
docker pull nginx
docker tag nginx ${MYDOMAIN}/library/nginx
docker push ${MYDOMAIN}/library/nginx
```

### kubectl runで起動する
せっかくなので、TMCでPodが起動する環境の準備もする。
最初にデプロイ先のNamespaceを作成する。
左サイドバーの`Namespaces`選択後、`CREATE NAMESPACE`をクリックする。
![1693386623257.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/67954c9c-a3fb-ddea-18af-90944c43f4ab.png)
Namespace名やClusterを選択して`CREATE`で作成する。
ここではNamespace名は`demo`とする。
なお、Workspaceが必須となっているので、作っていない場合は作ってから実施すること。
![1693386729304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/8bb9a4b8-8f99-d377-ed67-54978de1c839.png)
次にHarborの認証情報を格納したSecretを作成する。
左サイドバーの`Clusters`から`Add-ons`を選択し、下の方にある`Kubernetes secrets`を選択して`CREATE SECRET`をクリックする。
クリック後、Secret名(ここではharbor-credとした)とHarborの認証情報を入力する。また、先程作ったNamespaceも指定する。
![1693386982549.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/2f2033a4-51d0-3015-1ae0-8d00bcbb68c1.png)
 
`CREATE`をクリック後、今回はSecretの他Namespaceへの流用は実施しないため、そのまま`FINISH`をクリックして終了する。

次に、先程のnginxを起動する。
ターミナルに戻り、先程作成したSecretをdefaultのServiceAccountが利用するよう、ServiceAccountの`imagePullSecret`を編集する。
```sh
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-cred"}]}' -n demo
```

nginxを起動する。
```sh
kubectl run --image ${MYDOMAIN}/library/nginx nginx -n demo
```
起動したことを確認する。
```sh
$ kubectl get pod -n demo
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          24s
```
問題なさそうだ。