TUNA-JP Advent Calendar 2021 その1の14日目のエントリです。
本記事執筆時点で自宅のhome labはESXiをインストールした3台のNUC (NUC6i7KYK x 1, NUC10i7FNH x 2) で構成されています。 また Synology DiskStation DS718+ という少し古い安物のNASも使用しています。
ここにTanzu Kubernetes Gridをインストールしています。このブログもWorkloadクラスタの一つの上で動いています。
Tanzu Community Editionを使う場合でも同じなので、以下の内容はTKG -> TCEに置き換えても読めます。
共有データストアがないと冗長化できない問題
ESXi Host (NUC)が3台あるので、TKGのWorkload Clusterをスケールアウトして異なるホスト上に分散させたいです。1台のホストがダウンしてもk8sクラスタは稼働し続けるための当然の欲求です。
しかし、TKG及びTCEでクラスタを作成する場合、VSPHERE_DATASTORE
に指定するデータストアは一つしか選べません。
- TKGのクラスタ作成時のパラメータ https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.4/vmware-tanzu-kubernetes-grid-14/GUID-tanzu-k8s-clusters-vsphere.html
- TCEのクラスタ作成時のパラメータ https://tanzucommunityedition.io/docs/latest/vsphere-wl-template/
VSPHERE_DATASTORE
で指定したデータストアはNodeのVMのdiskのプロビジョニング先として使用されます。
したがって、この値にホストのローカルデータストアを選択すると次の図のように、対象のクラスタの全VMがそのローカルデータストアを持つホスト上に作成されてしまいます。
worker x 3なk8sクラスタを3つ作っても、3つのホストそれぞれに1クラスタ作ることしかできません。とても残念な構成です。
共有データストアを使用した場合は、次の図のような期待通りのホストを跨ったクラスタを作成することができます。
共有データストアの選択肢としては
- vSANを構築する
- NASをiSCSIまたはNFSでデータストアとして使う
が考えられます。
vSANはハードウェア的 (NICの数, 通信速度) にもリソース消費量(CPU, Memory)的にも現有戦力では難しいです。
なお、vSANを構築したいって方は本記事の内容は不要です。 https://qiita.com/hirosat/items/537f3b75160e2a9f4a21 を参考にしてください。
NASとして使用しているSynology DiskstationはiSCSIに対応しているので、これをデータストアに使うことができます。 しかし、NASもNUCもNICが1GbEにしか対応していません。まともに使うには最低でも2.5GbEは欲しいところです。
実際にiSCSIのデータストアをVSPHERE_DATASTORE
に設定して、クラスタを作成した時はControlplaneのDisk IOの負荷が大きく、ロードアベレージが高くなり、
API Serverへのアクセスのレスポンスタイムが遅くなり、kube-vipがクラッシュし、ControlplaneのVIPが消えては復活し、というのを繰り返す不安定な状態になっていました。
SSDのローカルデータストアを使う場合はこのようなことは起きません。
(もしかしたらこれはIOが多いkapp controllerがControlplaneに配置されていたからかもしれません。kapp controllerをWorkerに再配置したら改善していたかもしれないので、興味のある方は試してみてください。)
したがって、自宅環境では、VSPHERE_DATASTORE
にローカルデータストアを指定し、NodeのDiskにはローカルSSDを使うのが前提条件となりました。
このままではホストを跨った冗長なk8sクラスタを作ることができません...
救世主Node Pool
仕方なくk8sクラスタが同一ホスト上に全て乗ってしまう状態で運用していたのですが、TKG 1.4で朗報がありました。 Node Poolのサポートです。TCEでは最初から使えます。
Node Poolは異なるタイプのWorkerをサポートするための機能です。例えば特定のWorker NodeのみをCI専用にしてCPUのコア数を増やしたい場合に利用できます。 Cluster APIの用語で言うと、Clusterに対してMachineDeploymentリソースを増やす形になります。MachineDeploymentにはvSphere上のVMのSpecを決めるVSphereMachineTemplateリソースが紐づきます。 TKG/TCEのNode PoolではこのVSphereMachineTemplateの情報を追加設定できます。
具体的には次のような設定が可能です。
name: tkg-wc-oidc-md-1
replicas: 4
labels:
key1: value1
key2: value2
vsphere:
memoryMiB: 8192
diskGiB: 64
numCPUs: 4
datacenter: dc0
datastore: iscsi-ds-0
storagePolicyName: name
folder: vmFolder
resourcePool: rp-1
vcIP: 10.0.0.1
template: templateName
cloneMode: clone-mode
network: network-name
見ての通り、vsphere.datastore
にデータストアを定義できます。
つまり、新しく作るNode Pool (WorkerのMachineDeployment)を別のデータストアに紐づくホスト上に作成できます。
これにより、1つのクラスタに複数のデータストアを持つMachineDeploymentを結びつけられ、結果的にホストを跨ったWorker VMを持つk8sクラスタを作成できます。
次の図のような構成になります。
Node Poolが対応しているのはWorkerのみで、Controlplaneは最初のクラスタ作成時に指定したデータストアを使用しますが、 アプリケーションが乗るWorkerが複数ホストに分散できるのであれば、自宅環境の用途としては問題ありません。
ホストが3台あるので、最初に使用したデータストア以外の2つのデータストアを使用するNode Poolを作成するために、
次のようなyamlを作成します。クラスタ名はapple
です。
# nodepool1.yaml
name: apple-md-1
replicas: 1
vsphere:
datastore: /Datacenter/datastore/datastore01
# nodepool2.yaml
name: apple-md-2
replicas: 2
vsphere:
datastore: /Datacenter/datastore/datastore02
指定しなかった設定項目は元のクラスタの設定が引き継がれます。
ちなみにtanzu cluster create
コマンドで作成されるMachineDeployment名は<cluster name>-md-0
なので、
Node Pool名は<cluster name>-md-1
と<cluster name>-md-2
にしました。
次のコマンドでapple
クラスタに対して、Node Poolを追加できます。
tanzu cluster node-pool set apple -f nodepool1.yaml
tanzu cluster node-pool set apple -f nodepool2.yaml
Node Pool及び、クラスタの状態を確認します。
$ tanzu cluster node-pool list apple
NAME NAMESPACE PHASE REPLICAS READY UPDATED UNAVAILABLE
apple-md-0 default Running 2 2 2 0
apple-md-1 default Running 1 1 1 0
apple-md-2 default Running 2 2 2 0
$ tanzu cluster get apple --show-group-members
NAME NAMESPACE STATUS CONTROLPLANE WORKERS KUBERNETES ROLES
apple default running 1/1 5/5 v1.21.2+vmware.1 <none>
ℹ
Details:
NAME READY SEVERITY REASON SINCE MESSAGE
/apple True 69d
├─ClusterInfrastructure - VSphereCluster/apple True 93d
├─ControlPlane - KubeadmControlPlane/apple-control-plane True 69d
│ └─Machine/apple-control-plane-6g89p True 70d
└─Workers
├─MachineDeployment/apple-md-0
│ ├─Machine/apple-md-0-5c747f779f-twdgg True 84d
│ └─Machine/apple-md-0-5c747f779f-x9bjv True 63d
├─MachineDeployment/apple-md-1
│ └─Machine/apple-md-1-89bf4f8c4-l28tm True 81d
└─MachineDeployment/apple-md-2
├─Machine/apple-md-2-97546f689-clgjh True 82d
└─Machine/apple-md-2-97546f689-ndcvh True 63d
MachineDeploymentが合計3つ作られているのがわかります。
kubectl
のcontextをManagement Clusterに切り替えて、Cluster APIのリソースを確認します。
Node Poolに相当するMachineDeploymentが作成されていることがわかります。
$ kubectl get machinedeployment -l cluster.x-k8s.io/cluster-name=apple
NAME PHASE REPLICAS READY UPDATED UNAVAILABLE
apple-md-0 Running 2 2 2
apple-md-1 Running 1 1 1
apple-md-2 Running 2 2 2
また、MachineDeploymentに対応してVSphereMachineTemplateが作成されています。
$ kubectl get vspheremachinetemplate
NAME AGE
apple-control-plane 93d
apple-md-1-mt 93d
apple-md-2-mt 93d
apple-worker 93d
Node Poolに対して指定したデータストアが使用されていることも確認できます。
$ kubectl get vspheremachinetemplate apple-md-2-mt -oyaml | kubectl neat
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
kind: VSphereMachineTemplate
metadata:
name: apple-md-2-mt
namespace: default
spec:
template:
spec:
cloneMode: fullClone
datacenter: /Datacenter
datastore: /Datacenter/datastore/datastore02
diskGiB: 20
folder: /Datacenter/vm/tkg
memoryMiB: 8192
network:
devices:
- dhcp4: true
nameservers:
- 8.8.8.8
networkName: VM Network
numCPUs: 2
resourcePool: /Datacenter/host/Cluster/Resources/tkg
server: vcenter.example.com
template: /Datacenter/vm/tkg/photon-3-kube-v1.21.2
vCenterを見ても、3つのホストにWorkerが分散していることがわかります。
これで、期待した構成でクラスタを作ることができました。
この構成には一つ制約があります。k8sのPersistent Volumeをローカルデータストア(SSD)上に作成することができません。 考えてみれば当たり前で、ローカルにPVができるとそのPVを使っているコンテナが移動できないからです。
Node Poolを使用して異なるデータストア上にWorkerを作った場合は、vCenterに共有データストアが存在しないとPersistent Volumeが作成できず、Pending状態になります。 storagePolicyを指定している場合は、指定したstoragePolicyに共有データストアが存在しないといけません。
自宅の環境ではiSCSI接続のNASをk8sのPersistent Volume用途に使用しています。こちらは自宅用途では許容範囲です。 PVはvSphere CSI Driver経由で作成されるため、k8s側でNASを使うための設定は特に要りません。
まとめると、vSANがない自宅環境でTKG/TCEを使ったホスト跨ぎな冗長k8sクラスタを作りたい場合、
- Node VMはローカルデータストアを使う
- Node Poolを追加することで異なるデータストアを使うWorker Nodeを増やす
- Persistent VolumeにはiSCSI接続のNASを使う
でうまく行きました。次の図のような構成です。
複数のNUC + 安いNASで手軽に構成できます。
この構成にしてからまだTKGのアップデートが行われていないので、アップデートがどのような手順になるのか現時点で不明です。