TMCからクラスタを構築する際に自動的にHelm packageとサンプルアプリもデプロイする


デモや検証用の環境を作る時、毎回クラスタ立ち上げてパッケージ入れて、Manifestをapplyして、ってのがなかなか面倒くさい。
これをTanzu Mission Control(TMC)で楽しよう、というのが今回の狙い。
TMCではCluster groupという概念があり、クラスタを複数管理でき、まとめて設定などを入れることが出来る。
この設定の中に
- Helm Chartのインストール
- Kustomizationの設定

があり、これらを事前に設定しておくことで、Cluster groupに属するクラスタ作成時に自動でHelmのデプロイやらKustomizationを利用したリソースのデプロイが出来るので、これを使ってみる。

## 今回のゴール
Workloadクラスタ作成時に以下が最初からクラスタに入っている。
- Gitea（bitnamiのHelm Chartを利用）
- nginx（サンプルアプリ相当）

また、クラスタデプロイや上記の構築にCLIは利用しない。

## 前提
以下は実施済みのものとする。
- TMCへのManagement Clusterの登録
- GitHub上のPrivate RepositoryにCD対象のManifestを登録

なお、今回利用するManifestは[こちらの記事](https://qiita.com/ipppppei/items/8835db7fa45d572c5ced#%E4%BB%98%E9%8C%B2%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89)と同じものを使う。

## Cluster groupの準備
TMCにログインし、`Cluster groups`から`CREATE CLUSTER GROUP`を選択しCluster groupを作成する

![1689205056235.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c537076d-5957-db03-19cf-44f899260f2c.png)

### Helmの準備
作成したCluster groupを選択し、`Git repositories`から`ENABLE CONTINUOUS DELIVERY`を選択し、CDを有効化する。
![1689205298926.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/80e60baa-84ac-b686-7f00-207d44413290.png)

クリックすると画面がリロードされ、`ADD GIT REPOSITORY`がクリックできるようになっているので、これをクリックする。

今回はbitnamiのHelm Chartを利用するため、以下の設定を行う。
- `Repository name`: bitnami
- `Repository URL`: https://github.com/bitnami/charts
- `Repository credential (optional)`: No credentials needed
- `Branch`: main

![1689205652764.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/51387ec4-3e5f-4eab-e742-034a0f3ab931.png)
スクショには入れ忘れたが、`Branch`にmainを設定するのを忘れないこと。
項目を埋めたら`ADD GIT REPOSITORY`をクリックする。問題なければ`Sync status`が`Applied`になる。（しばらく時間が掛かることがあるので、その場合は少し待つこと）
![1689205771648.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/0051adf2-9ad0-83ef-5d90-1bffd166bb29.png)

### Kustomizationの準備
GitHub上のPrivate RepositoryにあるManifestにアクセスするために、リポジトリ参照用の認証情報を登録する。
`Repository credentials`から`CREATE REPOSITORY CREDENTIAL`をクリックする。
![1689206151362.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/93671c7b-6824-544b-a4fb-62a955b13b60.png)

GitHubの認証情報を埋めて`CREATE REPOSITORY CREDENTIAL`をクリックする
- `Credential name`: github
- `SSH Key`: `cat ~/.ssh/id_rsa`の結果
- `Known hosts`: `ssh-keyscan github.com 2> /dev/null | grep ecdsa-sha2-nistp256`の結果

SSH Keyは人によっては異なると思うので、その場合は自分が使っているGitHubの認証で使ってる秘密鍵の中身を指定する。
![1689206721021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/bf2d295b-8d27-af94-f75b-6539048c2582.png)

追加後、`Sync status`が`Processing`になっているが、一旦置いておいて次にManifestがあるリポジトリを追加する。
`Git repositories`から`ADD GIT REPOSITORY`をクリックし、今度はManifestがあるリポジトリを選択する。

- `Repository name`: <リポジトリ名>
- `Repository URL`: ssh://git@github.com/<アカウント名>/<リポジトリ>.git
- `Repository credential (optional)`: github
- `Branch`: <ブランチ名>

![1689208128634.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/5bd092fd-6488-0e86-f61c-4b10aa59f28c.png)
ブランチ名はデフォルトで`master`となっており、最近の`main`の流れとずれてるため、明示的に指定した方が間違いが起きにくい。
こちらも追加すると、`Sync status`が`Applied`になる。
![1689210546159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/dd2236fc-32f1-158a-805a-e624e92dd6cd.png)


次に上記のリポジトリを使ってデプロイするためのKustomizationの設定を行う。
`Installed kustomizaton`から`ADD KUSTOMIZATION`をクリックし、値を入れていく。
- `Kustomization name`: <任意の名前>
- `Repository`: <先程作ったリポジトリ名>
- `Path`: <kustomization.yamlがあるパス>

ここでは以下のように設定した。
![1689214512707.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/6e9db8f7-a1ee-4176-53bd-ef0d1f3284c8.png)

## Helmの有効化
`Installed Helm releases`から`ENABLE HELM SERVICE`をクリックし、画面がリロードされた後に表示される`CREATE HELM RELEASE`をクリックする。
次に以下を入力する。
- `Repository`: bitnami 　※先程作成したもの
- `Chart path`: bitnami/gitea 　※[gitea](https://github.com/bitnami/charts/tree/main/bitnami/gitea)の登録したリポジトリからの相対パス
- `Release name`: <Helmのリリース名>
- `Target namespace`: <展開先Namespace>
- `YAML`: values.yamlの中身
  
今回は以下のように入力した。お試しのため`YAML`は空にした。
![1689211147143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/f2564a33-3499-62f5-2d47-1d50dbbc2c85.png)

以上で準備は完了となる。

## クラスタのデプロイ

左サイドバーから`Create cluster`から`ADD Cluster`をクリックし、クラスタを作成する。
詳細な作成手順は省略するが、Cluster groupの指定は先程設定したものを指定することを忘れないようにする点だけ注意となる。

![1689212034535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/64a1995d-9761-bde4-0c45-dd03f3e47a6a.png)

## 確認
クラスタ構築後、クラスタはHealthyになっているが、Add-onのステータスは`FeatureDisabled`になっている。

![1689213080285.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/0f1106ea-850c-0a36-ad07-eb3176683e37.png)

これはクラスタ構築後に各種コントローラが構築されていない時に表示され、しばらく待てば解消されるので、クラスタ構築完了後もこちらのステータスが変わるまで待つ。

まずはGiteaから確認する。
```sh
$ kubectl get all -n gitea
NAME                               READY   STATUS    RESTARTS   AGE
pod/gitea-gitea-7c87b6d775-qf8k6   1/1     Running   0          2m11s
pod/gitea-gitea-postgresql-0       1/1     Running   0          2m11s

NAME                                TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                     AGE
service/gitea-gitea                 LoadBalancer   100.71.123.61    <pending>     80:32712/TCP,22:32694/TCP   2m11s
service/gitea-gitea-postgresql      ClusterIP      100.71.160.203   <none>        5432/TCP                    2m11s
service/gitea-gitea-postgresql-hl   ClusterIP      None             <none>        5432/TCP                    2m11s

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gitea-gitea   1/1     1            1           2m11s

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/gitea-gitea-7c87b6d775   1         1         1       2m11s

NAME                                      READY   AGE
statefulset.apps/gitea-gitea-postgresql   1/1     2m11s
```
デフォルトで`Service`が`type: LoadBalancer`になっているため`External-IP`が`<pending>`になっているものの、上手く起動しているようにみえる。
curlで念の為起動しているか確認する。
```sh
$ kubectl port-forward -n gitea service/gitea-gitea 8011:80 &
$ curl -s localhost 127.0.0.1:8011 | head
<!DOCTYPE html>
<html lang="en-US" class="theme-auto">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>example</title>
	<link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiZXhhbXBsZSIsInNob3J0X25hbWUiOiJleGFtcGxlIiwic3RhcnRfdXJsIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImljb25zIjpbeyJzcmMiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9hc3NldHMvaW1nL2xvZ28uc3ZnIiwidHlwZSI6ImltYWdlL3N2Zyt4bWwiLCJzaXplcyI6IjUxMng1MTIifV19">

	<meta name="default-theme" content="auto">
	<meta name="author" content="Gitea - Git with a cup of tea">
(23) Failed writing body
```
問題なさそうだ。

次にnginxの方を確認する。なお、Kustomizationのコントローラのチェック感覺が5分毎なので、場合によってはリソース作成まで少し待つことがある。
```
$ kubectl get all -n tmc-cd-demo
NAME                                READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-767b6f87c4-8vrnh   1/1     Running   0          9m53s

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/nginx-deploy   ClusterIP   100.70.21.167   <none>        80/TCP    44s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deploy   1/1     1            1           14m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deploy-767b6f87c4   1         1         1       9m53s
```

```
$ kubectl port-forward service/nginx-deploy -n tmc-cd-demo 8111:80 &
$ curl -s localhost:8111 | head
Handling connection for 8111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
```

こちらも問題なさそうだ。