Tanzu Mission ControlのContinuous Delivery機能を試す


Tanzu Mission Control（以下TMC）を触っていたところ、"Continuous Delivery"という見慣れない文字があった。
確認したところ、[今年の7/6にリリースされた新機能](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/services/rn/vmware-tanzu-mission-control-release-notes/index.html#whats-new-july-6-2022)のようだった。\
このドキュメントはこの機能を触ってみた時のメモ。

なお、公式ドキュメントは[こちら](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/services/tanzumc-using/GUID-851CF6DF-682A-466D-889E-D9A187647A48.html)となる。

※追記：
本文中にブランチがｍaster縛りである旨が記載されているが、現状のTMCでは縛りは解消されてmainやその他ブランチは利用可能。
その点は適宜読み替えて欲しい。

## TMCのCD機能の概要
TMCのCD機能の概要図は以下となる（公式ドキュメントより引用）

![1665110576096.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/dad4b4c8-0c98-0f65-0dc3-d5bf26a60ef9.png)

クラスタの構成をYAMLで宣言的に定義し、Gitリポジトリに格納する。それをFlux Controllerが取得してKustomizeで同期する仕組みのようだ。

なお、現時点で以下のクラスタは未サポートになっている。
-  OpenShiftクラスタ
-  UnmanagedのTanzu Community Edition (TCE)クラスタ
-  v0.12以前のTCEクラスタ

また、ドキュメントには記載されていないが、YAMLを格納するリポジトリのbranch名が固定化されているので(mainが使えない！)、試す場合はとりあえずmasterブランチを作成しておくこと。

※'22/12/7追記
確認できていないが、ブランチ固定の制限がなくなっているらしいとのことなので、これから使う人はこの制限を気にしなくても良さそう。が、どうも話を聞いていると上手く行った人と上手く行っていない人がいるので、実際に試してから使った方がいい。

## TMCのCD機能を試す

ざっくりとした手順は以下となる。
1. CD機能の有効化
2. Gitリポジトリの認証情報の登録
3. Gitリポジトリの登録
4. kustomizationリソースの登録

CD機能の有効化だが、TMCのコンソールでクラスタを選択し、`Continuous Delivery`のタブを選択すると、以下のような画面が出るので、`ENABLE CONTINUOUS DELIVERY`をクリックするとCD機能が有効化される。
![1665110809401.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/cf3b9299-32de-c376-1e17-367e5cd7d7ba.png)

有効化されると、以下のカスタムリソースがクラスタにインストールされる。
```
buckets.source.toolkit.fluxcd.io                                               2022-10-07T02:00:51Z
fluxcdcontinuousdeliveries.intents.tmc.cloud.vmware.com                        2022-10-07T01:59:32Z
gitrepositories.source.toolkit.fluxcd.io                                       2022-10-07T02:00:51Z
helmcharts.source.toolkit.fluxcd.io                                            2022-10-07T02:00:51Z
helmrepositories.source.toolkit.fluxcd.io                                      2022-10-07T02:00:51Z
kustomizations.kustomize.toolkit.fluxcd.io                                     2022-10-07T02:00:51Z
managedgitrepositories.intents.tmc.cloud.vmware.com                            2022-10-07T01:59:32Z
managedkustomizations.intents.tmc.cloud.vmware.com                             2022-10-07T01:59:32Z
```

次にGitリポジトリの認証情報を登録する。なお、この手順はPublicなリポジトリを使う場合はスキップ出来る。\
`Repository credentials`を選択し、`CREATE REPOSITORY CREDENTIAL`をクリックする。\
認証情報を入力する画面が出てくるので認証方法を選んで入力していく。
製品の作りがまだ荒く、認証周りは非常に詰まりやすいので、詰まった場合はPublicで試すことも検討したほうが良い。

今回はGitHubを利用するため、GitHubで使っているSSHの秘密鍵とknown_hostsを入力する。
![1665112123759.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/76bff1df-c205-1756-8c53-d1cd60bcb14c.png)

なお、known_hostsの値は`ssh-keyscan github.com`の結果から、暗号化方式が`ecdsa-sha2-nistp256`のものを選んだ。(.ssh/known_hostsのものや、他の暗号化方式では上手く行かなかった)


次にGitリポジトリを登録する。`Git repositories`を選択し、`ADD GIT REPOSITORY`をクリックする。

ここでは以下のように入力する。
- `Repository name`：好きな名前
- `Repository URL`：ssh://git@github.com/<アカウント名>/<リポジトリ>.git
- `Repository credential`：Publicの場合は変更しない。Privateの場合は先程作ったCredentialを選択
  
`Repository URL`に癖があり、HTTPSを入力しても自分の場合は上手く行かなかったので、ここではsshを推奨する。また、GitHubからgitのURLをコピーしたものは直接使えないので、上記のようにURLを修正すること。

また、冒頭でも記載したが、リポジトリのbranchがmainのみのリポジトリを指定すると、
```
failed to checkout and determine revision: unable to clone ‘リポジトリ名’: couldn’t find remote ref “refs/heads/master
```
とエラーとなってしまう。現状mainブランチをサポートしていない！、かつ特定のbranch名のみサポートしている状況のようなので、masterのbranchを作成しておくこと。
作成に成功すると、以下のようにSync statusが緑になる。
![1665121583812.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/65e3b605-2b21-74fd-84d2-5719d41fe2ed.png)

次にkustomizationの作成だが、その前に元となるYAMLをGitリポジトリに登録する。今回利用したサンプルはこのページの末尾に掲載した。mainではなくmasterリポジトリ登録することを忘れないこと。

Kustomizationの作成は`Kustomizations`から`ADD KUSTOMIZATION`を選択して作成する。
ここでは以下のように入力する。
- `Kustomization name`：好きな名前
- `Repository`：先程登録したGitリポジトリを選択する
- `Path`：GitリポジトリからKustomizeを含むファイルのディレクトリまでのパス（今回は`base/`｀）
- `Prune`：Gitリポジトリ内のリソースを削除した場合、クラスタ側にも反映するかどうか。今回はOnにした。

作成が終わると、Gitリポジトリ内に作成したYAMLを元にKubernetesリソースが作成される。
![1665122767315.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/d7b1730a-7594-8ee4-4ddf-db2612e42c1f.png)
上記のようにSync statusが緑になると、kustomizeで定義したリソースが展開され、正常に起動した状態となっている。
``` 
$ kubectl get all -n tmc-cd-demo
NAME                               READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-b9b96dd87-xxwm6   1/1     Running   0          117s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/nginx-deploy   ClusterIP   100.64.204.242   <none>        80/TCP    7m

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

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deploy-b9b96dd87    1         1         1       117s
```

なお、デプロイが上手く行かない場合はkustomizationsリソースをチェックすると手がかりが見つかるかもしれない。
以下はnamespaceを書き忘れた際のエラーログとなる。
```
$ kubectl get kustomizations -A
NAMESPACE                            NAME   AGE     READY   STATUS
tanzu-continuousdelivery-resources   fuga   6m41s   False   Service/nginx-deploy namespace not specified, error: the server could not find the requested resource...

```
なお、この時KusutomizationのSync statusは`Progressing`のままなので、`Progressing`から変化がない場合はエラーが起きていることを疑った方がよい。
また、kustomizations側が`True`になっているにも関わらずTMC側のSync statusが`Progressing`のままな場合はk8sリソースは展開済みだがk8sリソースが正常に起動していない（例：imageのpullに失敗)ことが考えられるので、k8sリソース側をチェックするとよい。

先程Pruneを設定したので、正常に削除されるかを確認する。
service.yamlを`git rm`で削除し、kustomization.yamlからも記述を削除してpushする。

pushして5分程度待つと、kustomizationが参照するコードが変わることが分かる。（なお、この待ち時間はKustomizationリソース内に`interval`というパラメータで持っているので、待つのが嫌な人は修正するとよい。GUIからは修正できないのでkubectl editで修正することになる。）
```
$ kubectl get kustomizations -w -A
NAMESPACE                            NAME   AGE   READY   STATUS
tanzu-continuousdelivery-resources   fuga   29m   True    Applied revision: master/b57742ddf85e1ebe8a39a92beb8389eb6ca3ec03
tanzu-continuousdelivery-resources   fuga   30m   Unknown   reconciliation in progress
tanzu-continuousdelivery-resources   fuga   31m   True      Applied revision: master/21e2d50878c3d07712e3ea19085bf9976ec6f668
```

`kubectl get svc`で実際に消えていることも分かる。
```
$ kubectl get svc -n tmc-cd-demo
No resources found in tmc-cd-demo namespace.
```

## 付録：サンプルコード

リポジトリの構成は以下となる。
```
.
├── LICENSE
├── README.md
└── base
    ├── deployment.yaml
    ├── kustomization.yaml
    ├── namespace.yaml
    └── service.yaml
````
base以下のファイルの中身は以下となる。

```yaml:deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy
  name: nginx-deploy
  namespace: tmc-cd-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-deploy
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      containers:
      - image: nginx
        name: nginx
```
```yaml:namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: tmc-cd-demo
```
```yaml:service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-deploy
  name: nginx-deploy
  namespace: tmc-cd-demo
spec:
  ports:
  - port: 80
  selector:
    app: nginx-deploy
```
```yaml:kustomization.yaml
resources:
- namespace.yaml
- deployment.yaml
- service.yaml
```