TKGで単一ノードのWorkload Clusterを作成してみた

この記事は、「TUNA-JP Advent Calendar 2023」の9日目のエントリです。

私はVMwareの社員ではなく、VMwareの技術を学んでいるしがないエンジニアです。

Advent Calenderは初めて参加ですし、色々凝った記事にしたいなーと思っていましたが、
思っているだけで日々が過ぎていき、あ、もう時間がない！って状況になってしまいました。

ほんとは、CNCF BuildPackを使って、新しいイメージにかえるどれくらい脆弱性が減るか調査！みたいなことをしたかったっす。。。

でも、少しくらいは普段やらないことをしたいなーとも思い、
検証環境はスペックが低いので、どれだけ少ないリソースで作れるかをテーマにしようと思いました。

なので、今回は、TKGmの単一ノードクラスタ構成を組んでみる！をやってみます。

そして、サブテーマとして、出来るだけ、エアギャップの環境でTKGを作ってみたのですが、
思った以上に大変でした。。。

# エアギャップ環境を作る上で、できなかったこと。

* 必要なTKGのパッケージがダウンロード

エアギャップ環境の場合、インターネットが接続できるOSで、以下のコマンドを実行して、パッケージをダウンロードする必要があります。

~~~
tanzu isolated-cluster download-bundle --source-repo projects.registry.vmware.com/tkg --tkg-version v2.4.0
~~~

実行したら途中で処理が停止して、最後までダウンロードできなかった。。。
いくつかバージョン試したけど、約45GBくらいダウンロードすると止まるので、もしかして、家の回線の仕様かも？と思い諦めちゃいました。。。

* Squidが動いているLinuxでのマネジメントクラスタデプロイ

TKGのパッケージがダウンロードできないので、Squidでプロキシサーバをたてて、インターネットでれる構成にしました。ブートストラップに入れてしまえばいいや！と思って、やってみたらマネジメントクラスタを作るAPIっぽい処理もProxyを通ろうとして、上手くいきませんでした。
no_proxyの環境変数に設定すればよいとは思ったのですが、そこを調査するモチベーションはなかったので、、別でブートストラップに作成しました。

# 単一ノードクラスタの作成
## 1.構成

我が家の検証環境は以下の構成です。
|ソフトウェア|バージョン|ビルド番号|
|:----------|:------------|:---------|
|VMware Workstation Player|17.5.0|22583795
|VMware ESXi|8.0.0|20513097|
|VMware vCenter Server|8.0.0|20519528|
|Tanzu Kubernetes Grid |2.4.0|-|

## 2.作業
Management Clusterの作成までの作業は省略しています。
tinyのベースイメージもテンプレート化済みです。

TKGのドキュメント通りに環境変数を設定してみました。

~~~
export CLUSTER_NAME='workload-snc'
export CLUSTER_NAMESPACE='default'
export CLUSTER_CIDR='100.96.0.0/11'
export SERVICE_CIDR='100.64.0.0/13'
export VSPHERE_CONTROL_PLANE_ENDPOINT=192.168.0.202
export VSPHERE_SERVER=192.168.0.10
export VSPHERE_USERNAME='administrator@vsphere.local'
export VSPHERE_PASSWORD='VMware123!'
export VSPHERE_DATACENTER='/Datacenter'
export VSPHERE_DATASTORE='/Datacenter/datastore/vm'
export VSPHERE_FOLDER='/Datacenter/vm'
export VSPHERE_NETWORK='/Datacenter/network/vm'
export VSPHERE_RESOURCE_POOL='/Datacenter/host/Cluster/Resources'
export VSPHERE_SSH_AUTHORIZED_KEY='<省略>'
export VSPHERE_TLS_THUMBPRINT=""
export VSPHERE_CONTROL_PLANE_NUM_CPUS='2'
export VSPHERE_CONTROL_PLANE_MEM_MIB='4096'
export VSPHERE_CONTROL_PLANE_DISK_GIB='20'
export TKG_CUSTOM_IMAGE_REPOSITORY='projects.registry.vmware.com/tkg'
export OS_NAME='photon'
export TKG_CUSTOM_IMAGE_REPOSITORY_CA_CERTIFICATE="LS0tL[...]0tLQo="
~~~

以下のコンフィグでWorkload Clusterを作成してみる。

~~~
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  annotations:
    tkg.tanzu.vmware.com/cluster-controlplane-endpoint: ${VSPHERE_CONTROL_PLANE_
ENDPOINT}
    run.tanzu.vmware.com/resolve-tkr: 'tkr.tanzu.vmware.com/tiny'
  labels:
    tkg.tanzu.vmware.com/cluster-name: ${CLUSTER_NAME}
  name: ${CLUSTER_NAME}
  namespace: ${CLUSTER_NAMESPACE}
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
      - ${CLUSTER_CIDR}
    services:
      cidrBlocks:
      - ${SERVICE_CIDR}
  topology:
    class: tkg-vsphere-default-v1.1.1
    controlPlane:
      metadata:
        annotations:
          run.tanzu.vmware.com/resolve-os-image: image-type=ova,os-name=${OS_NAM
E}
      replicas: 1
    variables:
    - name: controlPlaneTaint
      value: false
    - name: auditLogging
      value:
        enabled: false
    - name: apiServerEndpoint
      value: ${VSPHERE_CONTROL_PLANE_ENDPOINT}
    - name: aviAPIServerHAProvider
      value: false
    - name: imageRepository
      value:
        host: ${TKG_CUSTOM_IMAGE_REPOSITORY}
    - name: trust
      value:
        additionalTrustedCAs:
        - data: ${TKG_CUSTOM_IMAGE_REPOSITORY_CA_CERTIFICATE}
          name: imageRepository
    - name: vcenter
      value:
        cloneMode: fullClone
        datacenter: ${VSPHERE_DATACENTER}
        datastore: ${VSPHERE_DATASTORE}
        folder: ${VSPHERE_FOLDER}
        network: ${VSPHERE_NETWORK}
        resourcePool: ${VSPHERE_RESOURCE_POOL}
        server: ${VSPHERE_SERVER}
        storagePolicyID: ""
        tlsThumbprint: ${VSPHERE_TLS_THUMBPRINT}
    - name: user
      value:
        sshAuthorizedKeys:
        - ${VSPHERE_SSH_AUTHORIZED_KEY}
    - name: controlPlane
      value:
        machine:
          diskGiB: ${VSPHERE_CONTROL_PLANE_DISK_GIB}
          memoryMiB: ${VSPHERE_CONTROL_PLANE_MEM_MIB}
          numCPUs: ${VSPHERE_CONTROL_PLANE_NUM_CPUS}
    version: v1.27.5+vmware.1-tiny.1
---
apiVersion: v1
kind: Secret
metadata:
  name: ${CLUSTER_NAME}
  namespace: ${CLUSTER_NAMESPACE}
stringData:
  password: ${VSPHERE_PASSWORD}
  username: ${VSPHERE_USERNAME}
~~~

そうすると。エラーがでました。

~~~
# tanzu cluster create -f tiny.yaml
Error: could not parse CIDR ${CLUSTER_CIDR}, error: invalid CIDR address: ${CLUSTER_CIDR}
~~~

そう簡単には上手くいかなかったです。
なので、yamlファイル変数の個所を以下のコマンドで変換しました。

~~~
cat tiny.yaml | envsubst > tiny_env.yaml
~~~

上記コンフィグでデプロイしても、一回で上手くいくことはなかったです。
トライアンドエラーを繰り返した結果以下のコンフィグでデプロイできました！

~~~
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  annotations:
    tkg.tanzu.vmware.com/cluster-controlplane-endpoint: 192.168.0.202
    run.tanzu.vmware.com/resolve-tkr: 'tkr.tanzu.vmware.com/tiny'
  labels:
    tkg.tanzu.vmware.com/cluster-name: workload-snc
  name: workload-snc
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
      - 100.96.0.0/11
    services:
      cidrBlocks:
      - 100.64.0.0/13
  topology:
    class: tkg-vsphere-default-v1.1.1
    controlPlane:
      metadata:
        annotations:
          run.tanzu.vmware.com/resolve-os-image: image-type=ova,os-name=photon
      replicas: 1
    variables:
    - name: proxy
      value:
        httpProxy: http://192.168.0.20:3128
        httpsProxy: http://192.168.0.20:3128
        noProxy:
        - localhost
        - 192.168.0.10
        - tkg.lab
        - 192.168.0.0/24
        - .svc.cluster.local
        - .svc
        - 127.0.0.1
        - 100.64.0.0/13
        - 100.96.0.0/11
        systemWide: false
    - name: controlPlaneTaint
      value: false
    - name: auditLogging
      value:
        enabled: false
    - name: apiServerEndpoint
      value: 192.168.0.202
    - name: aviAPIServerHAProvider
      value: false
    - name: vcenter
      value:
        cloneMode: fullClone
        datacenter: /Datacenter
        datastore: /Datacenter/datastore/vm
        folder: /Datacenter/vm
        network: /Datacenter/network/vm
        resourcePool: /Datacenter/host/Cluster/Resources
        server: 192.168.0.10
        storagePolicyID: ""
        tlsThumbprint: ""
    - name: user
      value:
        sshAuthorizedKeys:
        - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCtCbE21eXkwmkDplO35kOM+tNzVzoUCVzkvevoQqagHSgGJpePmk9ZKLfO+6FoT9tTNaSg+8ZWtgAmqOhbnmK0PL7Rsam24LOuJ2zMNebtvovwX1z7Erxd3Aj/WAtX6xYle1hCSHK55vEOgsjDRi8BufVmUj+0O2iwYjaWJQCPiBBx3CCCsA7e8vLkYxS2bQRNPtdbNsh7Pd8+yj3dwC2KDXrIvKfxNwoKfOM7eIJ6zpBJUEVVlca14KYgbzms9FHL6tWgbCkeM0VjXcaSoVLCiGS/InaQg5pCmyqdA3yPMBNObRv3DtahpXDc6GmP+tcYEtZc0Xw4q1RptINpsR/nSaatmyo0jdYlMyR+cOOhj5xgHHgc0VGlwYtiDZuLcYogAw8Fv7k1x7LnXqlRjVp1oJx5aVVfmYiZF5xP8XkJaysHU6ah1Naf9ZQLgbGPOKu5QMSpta4i4nkAhQVceMHfTQmJFWRs7XO4xkQ3UZCRmPgO1y76ktG9Qnb/pydPWBcgdMMW1Pyhed07nUx15ZRyU3U/vLVYGHbU0KJU/a87MFp6M3lTnWZwhF/2mTiLt6cRAuV3HG3azyU8JLGyTRHzvASd32QknmFv4AqVJUd32GQtFUZVzGV1lSn1yPuZWX4lKHP5GfO8UZ/54RLF+hidOSPcUNlfXlXYvp6alQR78w== email@example.com
    - name: controlPlane
      value:
        machine:
          diskGiB: 20
          memoryMiB: 4096
          numCPUs: 2
    version: v1.27.5+vmware.1-tiny.1
---
apiVersion: v1
kind: Secret
metadata:
  name: workload-snc
  namespace: default
stringData:
  password: VMware123!
  username: administrator@vsphere.local
~~~

listコマンドではWORKERノード数が0でした。
~~~
# tanzu cluster list
  NAME          NAMESPACE  STATUS   CONTROLPLANE  WORKERS  KUBERNETES               ROLES   PLAN  TKR
  workload-snc  default    running  1/1           0/0      v1.27.5+vmware.1-tiny.1  <none>        v1.27.5---vmware.1-tiny.1-tkg.1
~~~

kubectlでノード数確認しても、1台でした。

~~~
[root@bs2 clusterconfigs]# kubectl get node
NAME                       STATUS   ROLES           AGE     VERSION
workload-snc-5zh9m-d6ldp   Ready    control-plane   8m24s   v1.27.5+vmware.1-tiny.1
~~~


# まとめ

上手くいかなかったところはこうやったら上手く行きました！みたいなこともあればよかったのですが、失敗談ばかりになってしまいました。
何か参考になれば幸いです。