Tanzu Kubernetes Grid 2.1を新規にインストールする

Tanzu Kubernetes Grid2.1が先日リリースされたが、Workload Clusterのデプロイ方法が若干変更されている。
今回はそれを試すためにゼロから新規にインストールする。


## 前提条件
インストールするにあたり、以下のものが用意済みであるとする。
- vSphere（6.7, 7, 8のいずれか。k8sのバージョンによっては動かないものもあるので、8が望ましい）
- Nodeに利用するOSイメージをテンプレート化済み
- vSphere上でリソースプールが作成済み

また、今回作業端末はubuntu20.04を利用し、4CPU16GBのリソースを割り当てている。\
メモリの割り当てが小さい場合、インストールに使うコンテナ(kind)の起動でつまずくことがあるので、メモリはある程度大きめに割り当てておきたい。


## 前準備

TKGをインストールする際の前提として作業端末でDocker Daemonが起動している必要がある。
作業端末にまずDockerをインストールする。

```
sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo systemctl restart docker
```
ログインアカウントをdocker groupに追加し、ログインしなおす。
```
sudo usermod -aG docker $USER
exit
```

クラスタのインストール時、kubectlが必要となるのでkubectlもインストールする。こちらはTKGのDownloadサイトからダウンロードしたものを利用する。
```
gunzip kubectl-linux-v1.24.9+vmware.1.gz
sudo install kubectl-linux-v1.24.9+vmware.1 /usr/local/bin/kubectl
```

次にtanzu cliをインストールする。
```
tar xvzfp tanzu-cli-bundle-linux-amd64.tar.gz
sudo install ./cli/core/v0.28.0/tanzu-core-linux_amd64 /usr/local/bin/tanzu
```
初期化する。
```
tanzu init
```

## Management Clusterの作成
公式ドキュメントは[こちら](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/2.1/tkg-deploy-mc-21/mgmt-index.html)になる。

Management Clusterインストール用のUIを起動する。
```
 tanzu mc create -u --bind 10.220.148.181:8080
```
WebUIにアクセスすると、以下のようなデプロイ先選択画面が表示される。
![1675832405856.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/154e1cca-d8af-3acb-33c2-33871842b06c.png)

ここではオンプレミスのvSphere8にインストールするので、VMware vSphereの`DEPLOY`を選択する。

最初にvCenterのIP、ユーザ名、パスワードを入力して`CONNECT`をクリックする。証明書が適当な場合は`Disable Verification`をチェックしておく。

![1675833060910.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/f4cd268c-92e6-b79d-1e6d-20dfd9be4cf3.png)

クリックすると、以下のようにvSphere with Tanzuの設定をするかどうかを聞かれる。
![1675833107739.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/b3281c80-a8ee-203d-173b-906ad16713a2.png)


vSphere with TanzuはvSphereと強力に統合されたKubernetesディストリビューションであるが、今回はこちらは利用せず、いわゆるスタンドアロン管理クラスタと呼ばれるタイプでインストールするため、`DEPLOY TKG MANAGEMENT CLUSTER`を選択する。\
なお、vSphere with Tanzuのスーパーバイザークラスタとスタンドアロン管理クラスタの違いは[こちら](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/index.html)に詳細があるので、必要に応じて読むとよい。

選択すると、自動的に`DATACENTER `のところに既存のDatacenterが埋まるが、もし複数ある場合はここでデプロイしたいDatacenterを選択する。
また、デプロイ後のクラスタのノードにアクセスするためのssh公開鍵を入力する。
作業端末では作っていなかったので、以下で作成して取得する。
```
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub
```
取得したものを入力して`NEXT`をクリックする。
![1675833620217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/6b4da0f7-0a0e-3af7-3d73-b41687a1ec9e.png)


次にManagement Clusterの設定を行う。
以下それぞれ入力する。
- クラスタタイプ：1ノードでデプロイするなら`Development`、3ノードでデプロイするなら`Production`を選択
- `INSTANCE TYPE`：ControlPlaneのノードのサイズを選択
- `CLUSTER NAME`：クラスタ名
- `MACHINE HEALTH CHECKS`：MachineHealthCheck(Nodeダウン時の自動復旧機能)を有効化するかどうか
- `CONTROL PLANE ENDPOINT PROVIDER`：クラスタのエンドポイントを提供する機能（kube-vip or NSX/ALBを選択）
- `CONTROL PLANE ENDPOINT`：クラスタのエンドポイントのIP（固定IP）
- `WORKER NODE INSTANCE TYPE`：Workerノードのサイズを選択
- `ACTIVATE AUDIT LOGGING`：監査ログを取得するかどうか

今回は以下のようにした。
![1675833757232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/453e182d-6e20-1c84-d86c-a9aab7d420e0.png)


次に「Optional VMware NSX Advanced Load Balancer Settings」とNSX/ALBの設定を促す画面が出るが、Optionalとあるように使わない場合は省略できる。
ここではスキップする。

次の「Optional Metadata」はラベル等設定が出来るが、ここもスキップ可能なのでスキップする。

「Specify the Resources」ではノードのVMを格納するVM FOLDER、DATASTORE、リソースプールを選択する。
今回は以下のようにした。

![1675834365092.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c0abd0d9-2b2a-e064-709a-07e28ada741e.png)


次にネットワークの設定をする。
利用するネットワーク、クラスタ内のService、Podが利用するIPレンジ、Proxy設定をここで実施する。
今回はProxyを使わないので、特にいじらずにそのままの入力値を利用した。

![1675835293334.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/664c0d2b-589d-2275-e690-4d7e8bc8660e.png)


「Optionally Specify Identity Management with OIDC or LDAPS」ではOIDCやLDAPと連携させる場合に設定するが、ここでは連携させないためスキップする。

次にノードで使うOSイメージを選択する。
事前にテンプレート化が終わっていれば、テンプレート化したものが自動で選択されている状態になるので、複数テンプレート化していなければそのまま`NEXT`をクリックする。

最後に、カスタマーエクスペリエンス向上プログラムに参加するかどうか聞かれる。参加すると情報を収集するPodがクラスタ内に展開される。こちらはお好みで。

全て終わると、`REVIEW CONFIGURATION`が活性化されるのでクリックする。
設定が表示されるので、問題なければ`DEPLOY MANAGEMENT CLUSTER`をクリックする。

デプロイが始まると、以下の画面が表示される。

![1675835700686.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/e9af125b-d95c-0865-6497-c6f6b71d5d40.png)


`CLI Command Equivalent`は今WebUIで実施したデプロイをコマンドで実行するとどうなるか、が書かれている。
`--file`で指定されたファイルはWebUIで設定した値を元に自動生成されたものであり、デプロイに失敗した時はこのファイルを使ってリトライすることも出来る。
また、Workload Cluster作成にも利用するので削除しないようにする。
今回の設定ではデプロイが完了するまでに50分程度掛かったので、終わるまで気長に待つ。

なお、Management Clusterのデプロイはkindを利用してbootstrap用のk8sクラスタが作成され、そこからManagement Clusterが作成される。デプロイに失敗した時はこのbootstrap用のk8sにアクセスしてデバッグすることもある。bootstrap用のk8sは`.kube-tkg/tmp/`以下にkubeconfigを作るので、以下の方法でアクセスできる。
```
$ kubectl get pod -A --kubeconfig=.kube-tkg/tmp/config_QmQorBGx
NAMESPACE            NAME                                                                  READY   STATUS     RESTARTS   AGE
kube-system          coredns-77d74f6759-6x7xx                                              1/1     Running    0          53s
kube-system          coredns-77d74f6759-v5g8z                                              1/1     Running    0          52s
kube-system          etcd-tkg-kind-cfhjsebq8bo7st8m4afg-control-plane                      1/1     Running    0          109s
kube-system          kindnet-fqj62                                                         1/1     Running    0          51s
kube-system          kube-apiserver-tkg-kind-cfhjsebq8bo7st8m4afg-control-plane            1/1     Running    0          67s
kube-system          kube-controller-manager-tkg-kind-cfhjsebq8bo7st8m4afg-control-plane   1/1     Running    0          108s
kube-system          kube-proxy-w8r5t                                                      1/1     Running    0          53s
kube-system          kube-scheduler-tkg-kind-cfhjsebq8bo7st8m4afg-control-plane            1/1     Running    0          112s
local-path-storage   local-path-provisioner-6b84c5c67f-6vft8                               1/1     Running    0          48s
tkg-system           kapp-controller-67c8f4d99f-84lf5                                      0/2     Init:0/1   0          15s
```

インストールが完了すると、tanzuコマンドを実行した端末に以下のメッセージが出力されてreturn 0で戻ってくる。
```
:（省略）
Creating tkg-bom versioned ConfigMaps...
You can now access the management cluster tkg21-mc by running 'kubectl config use-context tkg21-mc-admin@tkg21-mc'

Management cluster created!


You can now create your first workload cluster by running the following:

  tanzu cluster create [name] -f [file]

ℹ  Checking for required plugins...
ℹ  Installing plugin 'kubernetes-release:v0.28.0' with target 'kubernetes'
ℹ  Installing plugin 'cluster:v0.28.0' with target 'kubernetes'
ℹ  Installing plugin 'feature:v0.28.0' with target 'kubernetes'
ℹ  Successfully installed all required plugins
```

Managment Clusterにアクセスするには、上で表示されていたようにコンテキストを切り替えれば使えるようになっている。（.kube/configに設定追記済み）
```
$ kubectl config use-context tkg21-mc-admin@tkg21-mc
Switched to context "tkg21-mc-admin@tkg21-mc".
$ kubectl get node
NAME                                   STATUS   ROLES           AGE   VERSION
tkg21-mc-l9mhj-j25p5                   Ready    control-plane   46m   v1.24.9+vmware.1
tkg21-mc-md-0-xvwf5-6c48ddc5f5-vj768   Ready    <none>          38m   v1.24.9+vmware.1
```


## Workload Clusterの作成
公式ドキュメントは[こちら](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/2.1/using-tkg-21/workload-index.html)や[こちら](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/2.1/using-tkg-21/workload-clusters-configure.html#creating-your-first-cluster-configuration-file-4)あたりが参考になる。

従来はManagement Cluster作成時、`~/.config/tanzu/tkg/clusterconfigs`にランダムな名前でクラスタ作成用の設定ファイルが配置されるので、これをベースにWorkload Clusterを作成していた。
TKG2.1ではこれがレガシーなPlan-Basedでのデプロイ方法となり、デフォルトではKubernetesスタイルのyamlを使うClass-Basedという方法でデプロイする。
（なおPlan-Basedで実施する際は環境変数`ALLOW_LEGACY_CLUSTER`を設定した状態でtanzuコマンドを叩く必要がある）
※'23/4/4追記：
ドキュメントでは環境変数ではなく
`tanzu config set features.cluster.allow-legacy-cluster true`
で設定するように指示があるため、こちらを利用した方が良さそう。

Management Cluster作成時、`~/.config/tanzu/tkg/clusterconfigs`にManagement Cluster名のyamlが保存されており、これがClass Baseのyamlとなる。これをコピーして編集する。
```
cd ~/.config/tanzu/tkg/clusterconfigs
cp tkg21-mc.yaml tkg21-wc.yaml
```
viで開いてエンドポイントとクラスタ名をまとめて置換してデプロイする。変更箇所は以下となった。Plan Baseの方が変更点は少ない。
```diff
@@ -6,8 +6,8 @@
   labels:
     clusterctl.cluster.x-k8s.io/move: ""
     tkg.tanzu.vmware.com/addon-name: pinniped
-    tkg.tanzu.vmware.com/cluster-name: tkg21-mc
-  name: tkg21-mc-pinniped-package
+    tkg.tanzu.vmware.com/cluster-name: tkg21-wc
+  name: tkg21-wc-pinniped-package
   namespace: tkg-system
 stringData:
   values.yaml: |
@@ -19,22 +19,22 @@
 apiVersion: cpi.tanzu.vmware.com/v1alpha1
 kind: VSphereCPIConfig
 metadata:
-  name: tkg21-mc
+  name: tkg21-wc
   namespace: tkg-system
 spec:
   vsphereCPI:
     mode: vsphereCPI
     tlsCipherSuites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
     vmNetwork:
-      excludeExternalSubnetCidr: 10.220.148.236/32
-      excludeInternalSubnetCidr: 10.220.148.236/32
+      excludeExternalSubnetCidr: 10.220.148.249/32
+      excludeInternalSubnetCidr: 10.220.148.249/32
 ---
 apiVersion: run.tanzu.vmware.com/v1alpha3
 kind: ClusterBootstrap
 metadata:
   annotations:
     tkg.tanzu.vmware.com/add-missing-fields-from-tkr: v1.24.9---vmware.1-tkg.1
-  name: tkg21-mc
+  name: tkg21-wc
   namespace: tkg-system
 spec:
   additionalPackages:
@@ -47,14 +47,14 @@
       providerRef:
         apiGroup: cpi.tanzu.vmware.com
         kind: VSphereCPIConfig
-        name: tkg21-mc
+        name: tkg21-wc
   kapp:
     refName: kapp-controller*
 ---
 apiVersion: v1
 kind: Secret
 metadata:
-  name: tkg21-mc
+  name: tkg21-wc
   namespace: tkg-system
 stringData:
   password: xxxxxxx
@@ -65,12 +65,12 @@
 metadata:
   annotations:
     osInfo: photon,3,amd64
-    tkg.tanzu.vmware.com/cluster-controlplane-endpoint: 10.220.148.236
+    tkg.tanzu.vmware.com/cluster-controlplane-endpoint: 10.220.148.249
     tkg/plan: dev
   labels:
     cluster-role.tkg.tanzu.vmware.com/management: ""
-    tkg.tanzu.vmware.com/cluster-name: tkg21-mc
-  name: tkg21-mc
+    tkg.tanzu.vmware.com/cluster-name: tkg21-wc
+  name: tkg21-wc
   namespace: tkg-system
 spec:
   clusterNetwork:
@@ -101,7 +101,7 @@
         deactivated: false
         warn: baseline
     - name: apiServerEndpoint
-      value: 10.220.148.236
+      value: 10.220.148.249
     - name: aviAPIServerHAProvider
       value: false
     - name: vcenter
```
なお、その他の設定を変更したい場合は基本ドキュメントを見てもらいたいのだが、今まで使っていた設定ファイルをClass-Basedに書き換えたい場合は[こちら](https://github.com/vmware-tanzu/tanzu-framework/blob/main/docs/cli/clusterclass/legacy-to-cc-variable-mapping.md)を参照。苦行。。。

`tanzu cluster create`でデプロイする。`-v9`は詳細なメッセージが出るオプションで、デプロイに失敗した時にたまに役に立つので普段からつけるようにする。
```
tanzu  cluster create -f ./tkg21-wc.yaml -v9
```
10分くらいでクラスタが作成できた。
```
Workload cluster 'tkg21-wc' created
```
kubeconfigに作成したクラスタを追記し、コンテキストを切り替える。
```
tanzu cluster kubeconfig get tkg21-wc --admin
kubectl config use-context tkg21-wc-admin@tkg21-wc
```
無事使えるようになっているようだ。
```
$ kubectl get node
NAME                                   STATUS   ROLES           AGE     VERSION
tkg21-wc-md-0-gr8cs-5954bdfdb8-h9wvs   Ready    <none>          8m46s   v1.24.9+vmware.1
tkg21-wc-rkgc2-js9v4                   Ready    control-plane   11m     v1.24.9+vmware.1
```