これまでのTanzu Kubernetes Grid(TKG)でノードの中身を設定する場合(例えば証明書を入れるとか)、設定ファイルにパラメータがない場合はytt overlayでカスタマイズしてきた。
しかし、Class BasedのTKGでは従来のytt overlayが利用できなくなり、ClusterClassをカスタマイズして修正する必要がある。
この修正が非常に癖があるので、今回は試しにスタティックルートの設定をWorkload ClusterのWorkerノードに追加して、どういう手順が必要になるを検証する。
なお、公式ドキュメントのこちらを参考にした。
スタティックルートの設定をWorkerノードに追加するには、kind: VSphereMachineTemplate
のdevices
にroutesを足して実現できる。
network:
devices:
- dhcp4: true
networkName: /vSAN-DC/network/VM Network
+ routes:
+ - metric: 1
+ to: 192.168.111.200
+ via: 192.168.111.1
これをClusterClassをカスタマイズして実現する。
事前準備
Management Clusterの作成
今回はManagement Clusterを作成した状態から始める。作成手順は省略する。
Carvelのインストール
${HOME}/bin/
以下にインストールする。(パスは通っているものとしている)
cd ~
mkdir ~/bin/
curl -L https://carvel.dev/install.sh | K14SIO_INSTALL_BIN_DIR=bin bash
vendir version
ベースとなるManifestの入手
BaseとなるManifestをDownloadして解凍し、ディレクトリをコピーする。
wget https://github.com/vmware-tanzu/tanzu-framework/archive/refs/tags/v0.28.1.zip
unzip v0.28.1.zip
cp -r tanzu-framework-0.28.1/packages/tkg-clusterclass-vsphere/bundle/ .
中身は以下のようになっている。
bundle/
└── config
├── upstream
│ ├── base.yaml
│ ├── overlay-kube-apiserver-admission.yaml
│ └── overlay.yaml
└── values.yaml
設定作業
ベースのManifestに既存設定をマージ
Management Clusterにコンテキストをあわせて、以下を実行する。
cat <<EOF > default_values.yaml
#@data/values
#@overlay/match-child-defaults missing_ok=True
---
EOF
kubectl get secret tkg-clusterclass-infra-values -o jsonpath='{.data.values\.yaml}' -n tkg-system | base64 -d >> default_values.yaml
tkg-clusterclass-infra-values
の中にはManagement Cluster構築時に使ったvalues.yaml(plan based)が入っているので、それが追記されることになる。
抜き出した、ベースとなるManifestと結合する。
ytt -f bundle/ -f default_values.yaml > default_cc.yaml
中身はClusterClassを含むクラスタ関連のリソースが定義されている。
$ grep "^kind" default_cc.yaml
kind: VSphereClusterTemplate
kind: VSphereMachineTemplate
kind: VSphereMachineTemplate
kind: KubeadmControlPlaneTemplate
kind: KubeadmConfigTemplate
kind: ClusterClass
なお、ここでは細かく紹介しないが、default_cc.yaml内のClusterClass
でカスタマイズするための変数等が設定されている。
今回ytt overlayを作成するにあたり非常に参考になったので、実際にカスタマイズする際はこれをよく読んでおくとよい。
カスタムするoverlayの作成
最初にoverlayをまとめるディレクトリを作成する。
mkdir custom
kind: ClusterClass
内のkind: VSphereMachineTemplate
を修正するoverlayを作成する。
cat << EOF > ./custom/overlay_staticRoute.yaml
#@ load("@ytt:overlay", "overlay")
#@ load("@ytt:data", "data")
#@overlay/match by=overlay.subset({"kind":"ClusterClass"})
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: ClusterClass
spec:
variables:
- name: staticRoute
required: false
schema:
openAPIV3Schema:
type: object
properties:
metric:
type: integer
to:
type: string
via:
type: string
patches:
- name: staticRoute
enabledIf: '{{ not (empty .staticRoute) }}'
definitions:
- selector:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: VSphereMachineTemplate
matchResources:
machineDeploymentClass:
names:
- tkg-worker
jsonPatches:
- op: add
path: /spec/template/spec/network
valueFrom:
template: |
devices:
- dhcp4: true
networkName: {{ .vcenter.network }}
routes:
- metric: {{ .staticRoute.metric }}
to: {{ .staticRoute.to }}
via: {{ .staticRoute.via }}
EOF
書いている意味は以下となる。
variables:
- name: staticRoute
required: false
schema:
openAPIV3Schema:
type: object
properties:
metric:
type: integer
to:
type: string
via:
type: string
variables:
の中で変数を定義することが出来る。CRDではよく見るopenAPIV3Schemaの形式で記載する。
ここではstaticRoute
というオブジェクトを定義し、中にmetric
、to
、via
という変数的なものを定義した。
ベタ書きでいい場合は変数を作らなくても良さそう。
patches:
- name: staticRoute
enabledIf: '{{ not (empty .staticRoute) }}'
中のyamlを修正する場合、patches:
で修正箇所と修正内容を定義する。
enabledIf
でstaticRouteが指定された場合のみファイルを修正するようにしている。
definitions:
- selector:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: VSphereMachineTemplate
matchResources:
machineDeploymentClass:
names:
- tkg-worker
書き換え場所を指定する。MachineDeployment
に使うVSphereMachineTemplate
を書き換える。
matchResources
も必須で、書き換え対象を指定する。ControlPlaneに関するものだったらcontrolPlane: true
、Workerに関するものだったらmachineDeploymentClass
で対象MachineDeploymentを指定する。クラスタに関するものはinfrastructureCluster: true
を指定する。
jsonPatches:
- op: add
path: /spec/template/spec/network
valueFrom:
template: |
devices:
- dhcp4: true
networkName: {{ .vcenter.network }}
routes:
- metric: {{ .staticRoute.metric }}
to: {{ .staticRoute.to }}
via: {{ .staticRoute.via }}
上では実際のパラメータの設定を行っている。json patch形式で書くようで、pathがVSphereMachineTemplate
リソースの書き換え対象(spec.template.spec.network
)でopでjson patchでのopを指定する。
作成した変数については{{ .<変数名> }}
で参照できる。
.vcenter.network
は作成していないが別で定義されているのでそちらを引っ張ってきている。
また、defaultのClusterClassは変更できないため、別名をつけるためのytt overlayを作成する。なお公式ドキュメントではCC-VERSION
となってるが、VSPHERE_CLUSTER_CLASS_VERSION
が正しいと思われる。
cat << EOF > ./custom/values.yaml
#@data/values
#@overlay/match-child-defaults missing_ok=True
---
#! Change the suffix so we know from which default ClusterClass it is extended
VSPHERE_CLUSTER_CLASS_VERSION: extended-v1.0.0
#! Add other variables below if necessary
EOF
カスタムのClusterClass
を作成するのに必要な最終的なファイル構成は以下となった。
├── bundle
│ └── config
│ ├── upstream
│ │ ├── base.yaml
│ │ ├── overlay-kube-apiserver-admission.yaml
│ │ └── overlay.yaml
│ └── values.yaml
├── custom
│ ├── overlay_staticRoute.yaml
│ └── values.yaml
└── default_values.yaml
カスタムのClusterClassを作成する。
ytt -f bundle/ -f default_values.yaml -f custom/ > custom_cc.yaml
diffを取って、名前と追加した項目以外変わっていないことを確認する。
diff default_cc.yaml custom_cc.yaml
applyする。
kubectl apply -f ./custom_cc.yaml
追加されているのを確認する。
$ kubectl get clusterclass
NAME AGE
tkg-vsphere-default-extended-v1.0.0 23h
tkg-vsphere-default-v1.0.0 27h
Workloadクラスタの作成
Workload Clusterのテンプレートは既にあるものとする(ここでは~/.config/tanzu/tkg/clusterconfigs/workload.yamlとする)。
既存のものを以下の点について修正する。
- ClusterClassの指定をデフォルトのものから作成したものに変更
- 作成したパラメータを使ってスタティックルートを指定
スタティックルートは192.168.201.10宛を192.168.201.1経由にする設定で入れる。
修正箇所は以下になる。
topology:
- class: tkg-vsphere-default-v1.0.0
+ class: tkg-vsphere-default-extended-v1.0.0
controlPlane:
metadata:
annotations:
run.tanzu.vmware.com/resolve-os-image: image-type=ova,os-name=ubuntu
replicas: 1
variables:
+ - name: staticRoute
+ value:
+ metric: 1
+ to: 192.168.201.10
+ via: 192.168.201.1
- name: controlPlaneCertificateRotation
value:
activate: true
作成の前にdry-runが実行できる。dry-runを飛ばすことも可能だが、経験上凄く失敗するので、dry-runを試してからクラスタ作成に移った方がよい。
なお、clusterctlコマンドの古いバージョン(v1.2.0)が必要となる。(新しいバージョンだとエラーになる)
こちらにリンクを貼っておく。
https://github.com/kubernetes-sigs/cluster-api/releases/tag/v1.2.0
クラスタ作成時に使うWorkload Clusterのテンプレートをコピーする。
cp ~/.config/tanzu/tkg/clusterconfigs/workload.yaml ./dryrun.yaml
Management Clusterのkind: Cluster
で持っているTKR_DATA
というデータを表示する。
kubectl get cluster <Management Cluster名> -n tkg-system -o jsonpath='{.spec.topology.variables}' | jq -r '.[] | select(.name == "TKR_DATA")' | yq -p json '.'
表示されたTKR_DATA
をdryrun.yamlの.spec.topology.variables
に挿入する。
@@ -69,6 +69,33 @@
run.tanzu.vmware.com/resolve-os-image: image-type=ova,os-name=ubuntu
replicas: 1
variables:
+ - name: TKR_DATA
+ value:
+ v1.24.9+vmware.1:
+ kubernetesSpec:
+ coredns:
+ imageTag: v1.8.6_vmware.15
+ etcd:
+ imageTag: v3.5.6_vmware.3
+ imageRepository: projects.registry.vmware.com/tkg
+ kube-vip:
+ imageTag: v0.5.7_vmware.1
+ pause:
+ imageTag: "3.7"
+ version: v1.24.9+vmware.1
+ labels:
+ image-type: ova
+ os-arch: amd64
+ os-name: ubuntu
+ os-type: linux
+ os-version: "2004"
+ ova-version: v1.24.9---vmware.1-tkg.1-b030088fe71fea7ff1ecb87a4d425c93
+ run.tanzu.vmware.com/os-image: v1.24.9---vmware.1-tkg.1-b030088fe71fea7ff1ecb87a4d425c93
+ run.tanzu.vmware.com/tkr: v1.24.9---vmware.1-tkg.1
+ osImageRef:
+ moid: vm-51
+ template: /vSAN-DC/vm/ubuntu-2004-efi-kube-v1.24.9+vmware.1
+ version: v1.24.9+vmware.1-tkg.1-b030088fe71fea7ff1ecb87a4d425c93
dry-runの結果を保存するディレクトリを作成する。
mkdir plan
clusterctlを使ってdry-runを実行する。
./clusterctl alpha topology plan -f dryrun.yaml -o plan
実行して問題なければ今のManagement Clusterが持つリソースの差分が出力される。コンソール出力としては以下のようになり、planディレクトリ以下に作成される予定のManifestが格納される。
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
No ClusterClasses will be affected by the changes.
The following Clusters will be affected by the changes:
* default/delme-wc-edit
Changes for Cluster "default/delme-wc-edit":
NAMESPACE KIND NAME ACTION
default KubeadmConfigTemplate delme-wc-edit-md-0-bootstrap-6cqsk created
default KubeadmControlPlane delme-wc-edit-jffv2 created
default MachineDeployment delme-wc-edit-md-0-jcbmj created
default MachineHealthCheck delme-wc-edit-jffv2 created
default MachineHealthCheck delme-wc-edit-md-0-jcbmj created
default Secret delme-wc-edit-shim created
default VSphereCluster delme-wc-edit-hj967 created
default VSphereMachineTemplate delme-wc-edit-control-plane-4bw9p created
default VSphereMachineTemplate delme-wc-edit-md-0-infra-755r7 created
default Cluster delme-wc-edit modified
Created objects are written to directory "plan/created"
Modified objects are written to directory "plan/modified"
なお、現在のManagement Clusterが持つリソースとの差分なので、クラスタ作成後は何も表示されなくなるので注意。
出力された中身を見て、意図したようにVSphereMachineTemplateが書き換わっていることを確認する。
network:
devices:
- dhcp4: true
networkName: /vSAN-DC/network/VM Network
routes:
- metric: 1
to: 192.168.201.10
via: 192.168.201.1
問題なさそうであれば、デプロイする。
tanzu cluster create -f workload.yaml -v9
問題なくデプロイ出来たら、動作確認する。NodeのIPに対してsshしてip routeで確認する。
$ ssh -l capv 10.151.206.93 ip route
default via 10.151.207.254 dev eth0 proto dhcp src 10.151.206.93 metric 100
10.151.192.0/20 dev eth0 proto kernel scope link src 10.151.206.93
10.151.207.254 dev eth0 proto dhcp scope link src 10.151.206.93 metric 100
100.96.0.0/24 via 100.96.0.1 dev antrea-gw0 onlink
100.96.1.0/24 dev antrea-gw0 proto kernel scope link src 100.96.1.1
192.168.201.10 via 192.168.201.1 dev eth0 proto static metric 1 onlink
追加した192.168.201.10宛の設定が追加されていることが分かる。
おまけ:失敗例
後方に追加したいので、/-
を指定すればいい、と思って以下を書いた。
- op: add
path: /spec/template/spec/network/devices/-
結果は以下。
network:
devices:
- dhcp4: true
networkName: /vSAN-DC/network/VM Network
- routes:
- metric: 1
to: 192.168.201.10
via: 192.168.201.1
routes
をpathに含めたパターン。
- op: add
path: /spec/template/spec/network/devices/routes
こちらはclusterctlが以下のエラーを出力した。
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
Error: failed to dry run the topology controller: error computing the desired state of the Cluster topology: failed to apply patches: failed to apply patch with uid "61c28a73-17ac-4425-b8c6-5f52cad035a7": error applying json patch (RFC6902): [{"op":"add","path":"/spec/template/spec/network/devices/routes","value":{"metric":1,"to":"192.168.201.10","via":"192.168.201.1"}}]: error in add for path: '/spec/template/spec/network/devices/routes': value was not a proper array index: 'routes': strconv.Atoi: parsing "routes": invalid syntax
あと、clusterctlが最新版だと以下のエラーが出る
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
Error: failed defaulting and validation on input objects: failed to run defaulting and validation on Clusters: failed defaulting of cluster.x-k8s.io/v1beta1, Kind=Cluster default/delme-wc-edit: Cluster.cluster.x-k8s.io "delme-wc-edit" is invalid: [spec.topology.variables: Invalid value: "": failed validation: "TKR_DATA.v1.24.9+vmware.1" fields are not specified in the variable schema of variable "TKR_DATA", spec.topology.variables: Invalid value: "": failed validation: "worker.count" fields are not specified in the variable schema of variable "worker"]
結論:
- json patchは慣れが必要
- clusterctlでの事前確認は大事
- 早くclusterctlの最新版に対応して欲しい