Tanzu Kubernetes Gridの1Nodeあたりの最大Pod数を変更する

TKGで1Nodeあたりの最大Pod数はデフォルトでは110となっている。
```
$ kubectl describe node
：（省略）
Allocatable:
  cpu:                2
  ephemeral-storage:  37867920936
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             8065612Ki
  pods:               110
```
これを200に変更する。
稼働中のものに対する変更方法と、事前に設定ファイルをおいてデプロイ時に変更する方法を検証する。

なお、本検証はTKG1.6.1で確認した。バージョンが変わると方法が変わる可能性がある点に注意。

# 稼働中のものに対する変更
ここの値はkubeletで管理されているため、kubeletにパラメタを渡す。
kubeletの設定はControlPlaneは`kubeadmcontrolplanes`リソース(kcp)、Worker Nodeは`KubeadmConfigTemplate`リソース(kct)で管理されている。
これを書き換えて変更する。
## ControlPlaneの変更

Management Clusterにコンテキストを切り替えて、`kcp`の名前を確認する。
```
$ kubectl get kcp -A
NAMESPACE    NAME                            CLUSTER           INITIALIZED   API SERVER AVAILABLE   REPLICAS   READY   UPDATED   UNAVAILABLE   AGE    VERSION
default      tkg15wc-hogeeee-control-plane   tkg15wc-hogeeee   true          true                   1          1       1         0             6d6h   v1.23.10+vmware.1
tkg-system   tkg15mc-control-plane           tkg15mc           true          true                   1          1       1         0             6d7h   v1.23.10+vmware.1
```
今回はWorkload Clusterの最大Pod数を変更する。
このkcpをeditする。
```
kubectl edit kcp tkg15wc-hogeeee-control-plane -n default
```
`spec.kubeadmConfigSpec.joinConfiguration.nodeRegistration.kubeletExtraArgs`に`max-pods: "200"`を以下のような感じで追記する。
```yaml
    joinConfiguration:
      localAPIEndpoint:
        advertiseAddress: 0.0.0.0
        bindPort: 6443
      nodeRegistration:
        criSocket: /var/run/containerd/containerd.sock
        kubeletExtraArgs:
          max-pods: "200"
```
少し補足すると、`kubeletExtraArgs`に書いた値はkubeletの引数として`--key "value"`のように渡すことが出来る。
更新を保存すると、勝手にNodeの再作成が始まる。
再作成が終わったら、コンテキストをWorkload Clusterに切り替えてNodeの状態を確認する
```
$ kubectl describe node tkg15wc-hogeeee-control-plane-c4hlc | grep pod
  pods:               200
  pods:               200
```
変更が確認できた。

## Worker Nodeの変更
Management Clusterにコンテキストを切り替えて、`kubeadmconfigtemplate`の名前を確認する。
```
$ kubectl get kubeadmconfigtemplate -A
NAMESPACE    NAME                            AGE
default      tkg15wc-hogeeee-md-0            6d9h
tkg-system   tkg15mc-md-0                    6d10h
```
複数NodePoolを作成していてどれを変えるべきか分からない場合は`MachineDeployment`リソースもあわせて確認すると良い。
ここでは確認方法は省略する。
狙いを定めたものをeditする。
```
kubectl edit kubeadmconfigtemplate tkg15wc-hogeeee-md-0 -n default
```
こちらも先程と同じような感じで`max-pods: "200"`を`spec.template.spec.joinConfiguration.nodeRegistration.kubeletExtraArgs`に追記する。
```yaml
      joinConfiguration:
        nodeRegistration:
          criSocket: /var/run/containerd/containerd.sock
          kubeletExtraArgs:
            max-pods: "200"
            cloud-provider: external
            tls-cipher-suites: 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
```
こちらに関しては自動でNodeの再作成は走らないので、参照している`MachineDeployment`を適当に更新する。
```
kubectl patch machinedeployment tkg15wc-hogeeee-md-0 --type merge -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"
```
上記のコマンドを実行すると、`MachineDeployment`のレプリカ数分、Nodeが再作成される。
こちらもコンテキストをWorkload Clusterに切り替えて確認する。
```
$ kubectl describe node tkg15wc-hogeeee-md-0-c7464df65-868zp | grep pods
  pods:               200
  pods:               200
  Normal   NodeAllocatableEnforced  103s  kubelet     Updated Node Allocatable limit across pods
```
問題ないようだ。

# クラスタ作成時に変更する
ここではWorkload Clusterの作成用yamlが既にある前提で話を進める。
クラスタ作成のタイミングで変更する場合、`~/.config/tanzu/tkg/providers/ytt/03_customizations`にyttのoverlay用yamlを設置してkubeletにパラメタを渡す。
オフィシャルなドキュメントはないが[ドキュメントのこの辺の手順](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.6/vmware-tanzu-kubernetes-grid-16/GUID-cluster-lifecycle-secrets.html#trust-custom-ca-certificates-in-new-clusters-2)が近い。
以下のような感じでoverlay用のファイルを作成する。
```yaml
cat << EOF > ~/.config/tanzu/tkg/providers/ytt/03_customizations/edit_maxpods.yaml
#@ load("@ytt:overlay", "overlay")
#@ load("@ytt:data", "data")
#@ if data.values.PROVIDER_TYPE in ["vsphere"]:
#@overlay/match by=overlay.subset({"kind":"KubeadmControlPlane"})
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
spec:
  kubeadmConfigSpec:
    initConfiguration:
      nodeRegistration:
        kubeletExtraArgs:
          #@overlay/match missing_ok=True
          max-pods: "200"
    joinConfiguration:
      nodeRegistration:
        kubeletExtraArgs:
          #@overlay/match missing_ok=True
          max-pods: "200"
---
#@overlay/match by=overlay.subset({"kind":"KubeadmConfigTemplate"})
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfigTemplate
spec:
  template:
    spec:
      joinConfiguration:
        nodeRegistration:
          kubeletExtraArgs:
            #@overlay/match missing_ok=True
            max-pods: "200"
#@ end
EOF
```
`kcp`をeditした時と異なり、一番最初に作られるControlPlaneにも適用するためにinitConfigurationにも追加している。
作成したファイルが上手くハマるか確認する。
```
tanzu cluster create -f ~/.config/tanzu/tkg/clusterconfigs/delme.yaml --dry-run
```
overlayにミスがあったりすると、ここで以下のように検出できる。
```
Error: unable to get template:
- mismatched set of block openings (if/else/elif/for/def) and closing (end)
    03_customizations/edit_maxpods.yaml:3 | #@ if data.values.PROVIDER_TYPE in ["vsphere"]:
Error: exit status 1
```
問題なければyamlが表示される。yamlを見ると以下のように`KubeadmControlPlane` リソースと`KubeadmConfigTemplate`リソースそれぞれに値が適用されていることが分かる。
```yaml
    initConfiguration:
      nodeRegistration:
        criSocket: /var/run/containerd/containerd.sock
        kubeletExtraArgs:
          cloud-provider: external
          max-pods: "200"
          ：（省略）
    joinConfiguration:
      nodeRegistration:
        criSocket: /var/run/containerd/containerd.sock
        kubeletExtraArgs:
          cloud-provider: external
          max-pods: "200"
--
spec:
  template:
    spec:
      files: []
      joinConfiguration:
        nodeRegistration:
          criSocket: /var/run/containerd/containerd.sock
          kubeletExtraArgs: 
            cloud-provider: external
            max-pods: "200"
```
問題なければそのままdeployする。
```
tanzu cluster create -f ~/.config/tanzu/tkg/clusterconfigs/delme.yaml
```
クラスタを切り替えて確認する。
```
tanzu cluster kubeconfig get delme --admin
kubectl config use-context delme-admin@delme
```
```
$ kubectl describe node |grep "^ *pod"
  pods:               200
  pods:               200
  pods:               200
  pods:               200
```
問題なさそうだ。