29 ClusterClassを使用したダウンストリームクラスタのデプロイ #
29.1 はじめに #
Kubernetesクラスタのプロビジョニングは、クラスタコンポーネントの設定に深い専門知識が求められる複雑な作業です。設定が複雑化したり、さまざまなプロバイダからの要求により多数のプロバイダ固有のリソース定義が導入されたりすると、クラスタの作成が困難に感じられるかもしれません。幸いなことに、Kubernetes Cluster API (CAPI)は、ClusterClassによってさらに強化された、より洗練された宣言型アプローチを提供します。この機能はテンプレート駆動型モデルを導入し、複雑さをカプセル化して一貫性を促進する再利用可能なクラスタクラスを定義できます。
29.2 ClusterClassとは #
CAPIプロジェクトは、クラスタのインスタンス化にテンプレートベースの手法を採用することで、Kubernetesクラスタのライフサイクル管理におけるパラダイムシフトとしてClusterClass機能を導入しました。ユーザがクラスタごとにリソースを個別に定義する代わりに、ClusterClassを定義することで、ClusterClassは包括的で再利用可能なブループリントとして機能します。この抽象データ型表現は、Kubernetesクラスタの望ましい状態と設定をカプセル化し、定義された仕様に準拠した複数のクラスタを迅速かつ一貫して作成できるようにします。 この抽象データ型により、設定の負担が軽減され、より管理しやすいデプロイメントマニフェストが実現されます。つまり、ワークロードクラスタのコアコンポーネントはクラスレベルで定義されるため、ユーザはこれらのテンプレートをKubernetesクラスタのフレーバーとして使用し、クラスタのプロビジョニングに1回または複数回再利用できるようになります。ClusterClassの実装は、従来の大規模なCAPI管理に固有の課題に対処するいくつかの重要な利点をもたらします。
複雑さとYAMLの冗長性を大幅に削減
最適化された保守と更新プロセス
デプロイメント全体における一貫性と標準化の強化
スケーラビリティと自動化機能の向上
宣言型管理と堅牢なバージョン管理
29.3 現在のCAPIプロビジョニングファイルの例 #
Cluster API (CAPI)とRKE2プロバイダを活用するKubernetesクラスタのデプロイメントには、いくつかのカスタムリソースの定義が必要です。これらのリソースは、クラスタとその基盤となるインフラストラクチャの望ましい状態を定義し、CAPIがプロビジョニングと管理のライフサイクルをオーケストレーションできるようにします。以下のコードスニペットは設定する必要のあるリソースタイプを示しています。
Cluster: このリソースは、ノード間の通信とサービスディスカバリを制御するネットワークトポロジを含む、高レベルな設定をカプセル化します。さらに、コントロールプレーン仕様と指定されたインフラストラクチャプロバイダリソースとの重要なリンクを確立し、これにより望ましいクラスタアーキテクチャと、そのプロビジョニング対象となる基盤インフラストラクチャについてCAPIに通知します。
Metal3Cluster: このリソースは、Metal3に固有のインフラストラクチャレベルの属性を定義します。たとえば、Kubernetes APIサーバにアクセスできる外部エンドポイントなど。
RKE2ControlPlane: RKE2ControlPlaneリソースは、クラスタのコントロールプレーンノードの特性と動作を定義します。この仕様では、コントロールプレーンレプリカの必要な数(高可用性と耐障害性を確保するために重要)、特定のKubernetesディストリビューションのバージョン(選択したRKE2リリースと一致)、コントロールプレーンコンポーネントへの更新展開戦略などのパラメータが設定されます。さらに、このリソースはクラスタ内で使用されるContainer Network Interface (CNI)を指定し、エージェント固有の設定の注入を容易にします。これには多くの場合、コントロールプレーンノード上のRKE2エージェントのシームレスで自動化されたプロビジョニングのためにIgnitionが活用されます。
Metal3MachineTemplate: このリソースは、使用されるイメージを定義するKubernetesクラスタのワーカーノードを形成する、個々のコンピューティングインスタンス作成のブループリントとして機能します。
Metal3DataTemplate: Metal3MachineTemplateを補完するMetal3DataTemplateリソースは、追加のメタデータを新たにプロビジョニングされたマシンインスタンスに指定できるようにします。
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
clusterNetwork:
pods:
cidrBlocks:
- 192.168.0.0/18
services:
cidrBlocks:
- 10.96.0.0/12
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
name: emea-spa-cluster-3
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
name: emea-spa-cluster-3
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
controlPlaneEndpoint:
host: 192.168.122.203
port: 6443
noCloudProvider: true
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
name: emea-spa-cluster-3
replicas: 1
version: v1.32.4+rke2r1
rolloutStrategy:
type: "RollingUpdate"
rollingUpdate:
maxSurge: 1
registrationMethod: "control-plane-endpoint"
registrationAddress: 192.168.122.203
serverConfig:
cni: cilium
cniMultusEnable: true
tlsSan:
- 192.168.122.203
- https://192.168.122.203.sslip.io
agentConfig:
format: ignition
additionalUserData:
config: |
variant: fcos
version: 1.4.0
storage:
files:
- path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: endpoint-copier-operator
namespace: kube-system
spec:
chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
targetNamespace: endpoint-copier-operator
version: 303.0.0+up0.2.1
createNamespace: true
- path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: metallb
namespace: kube-system
spec:
chart: oci://registry.suse.com/edge/charts/metallb
targetNamespace: metallb-system
version: 303.0.0+up0.14.9
createNamespace: true
- path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
overwrite: true
contents:
inline: |
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- 192.168.122.203/32
serviceAllocation:
priority: 100
namespaces:
- default
serviceSelectors:
- matchExpressions:
- {key: "serviceType", operator: In, values: [kubernetes-vip]}
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- kubernetes-vip-ip-pool
- path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
overwrite: true
contents:
inline: |
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
labels:
serviceType: kubernetes-vip
spec:
ports:
- name: rke2-api
port: 9345
protocol: TCP
targetPort: 9345
- name: k8s-api
port: 6443
protocol: TCP
targetPort: 6443
type: LoadBalancer
systemd:
units:
- name: rke2-preinstall.service
enabled: true
contents: |
[Unit]
Description=rke2-preinstall
Wants=network-online.target
Before=rke2-install.service
ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
[Service]
Type=oneshot
User=root
ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
ExecStartPost=/bin/sh -c "umount /mnt"
[Install]
WantedBy=multi-user.target
kubelet:
extraArgs:
- provider-id=metal3://BAREMETALHOST_UUID
nodeName: "localhost.localdomain"
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
nodeReuse: True
template:
spec:
automatedCleaningMode: metadata
dataTemplate:
name: emea-spa-cluster-3
hostSelector:
matchLabels:
cluster-role: control-plane
deploy-region: emea-spa
node: group-3
image:
checksum: http://fileserver.local:8080/eibimage-downstream-cluster.raw.sha256
checksumType: sha256
format: raw
url: http://fileserver.local:8080/eibimage-downstream-cluster.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
clusterName: emea-spa-cluster-3
metaData:
objectNames:
- key: name
object: machine
- key: local-hostname
object: machine
- key: local_hostname
object: machine
29.4 CAPIプロビジョニングファイルのClusterClassへの変換 #
29.4.1 ClusterClass定義 #
以下のコードは、特定のタイプのKubernetesクラスタを一貫してデプロイするための宣言型テンプレートである、ClusterClassリソースを定義します。この仕様には、共通のインフラストラクチャとコントロールプレーンの設定が含まれており、クラスタフリート全体にわたる効率的なプロビジョニングと統一されたライフサイクル管理が可能になります。以下のClusterClassの例にはいくつかの変数があり、実際の値を使用してクラスタインスタンス化プロセス中に置き換えられます。例では次の変数が使用されています。
controlPlaneMachineTemplate
: 使用されるControlPlane Machine Template参照を定義する名前ですcontrolPlaneEndpointHost
: コントロールプレーンエンドポイントのホスト名またはIPアドレスですtlsSan
: コントロールプレーンエンドポイントのTLSサブジェクト代替名です
ClusterClass定義ファイルは、次の3つのリソースに基づいて定義されます。
ClusterClass: このリソースは、コントロールプレーンとインフラストラクチャテンプレートを含むClusterClass定義全体をカプセル化します。また、インスタンス化プロセス中に置き換えられる変数のリストも含まれます。
RKE2ControlPlaneTemplate: このリソースは、コントロールプレーンテンプレートを定義し、コントロールプレーンノードの目的の設定を指定します。レプリカ数、Kubernetesバージョン、使用するCNIなどのパラメータが含まれます。また、一部のパラメータは、インスタンス化プロセス中に適切な値に置き換えられます。
Metal3ClusterTemplate: このリソースは、インフラストラクチャテンプレートを定義し、基盤となるインフラストラクチャの目的の設定を指定します。コントロールプレーンエンドポイントやnoCloudProviderフラグなどのパラメータが含まれます。また、一部のパラメータは、インスタンス化プロセス中に適切な値に置き換えられます。
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlaneTemplate
metadata:
name: example-controlplane-type2
namespace: emea-spa
spec:
template:
spec:
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
name: example-controlplane # This will be replaced by the patch applied in each cluster instances
namespace: emea-spa
replicas: 1
version: v1.32.4+rke2r1
rolloutStrategy:
type: "RollingUpdate"
rollingUpdate:
maxSurge: 1
registrationMethod: "control-plane-endpoint"
registrationAddress: "default" # This will be replaced by the patch applied in each cluster instances
serverConfig:
cni: cilium
cniMultusEnable: true
tlsSan:
- "default" # This will be replaced by the patch applied in each cluster instances
agentConfig:
format: ignition
additionalUserData:
config: |
default
kubelet:
extraArgs:
- provider-id=metal3://BAREMETALHOST_UUID
nodeName: "localhost.localdomain"
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3ClusterTemplate
metadata:
name: example-cluster-template-type2
namespace: emea-spa
spec:
template:
spec:
controlPlaneEndpoint:
host: "default" # This will be replaced by the patch applied in each cluster instances
port: 6443
noCloudProvider: true
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: ClusterClass
metadata:
name: example-clusterclass-type2
namespace: emea-spa
spec:
variables:
- name: controlPlaneMachineTemplate
required: true
schema:
openAPIV3Schema:
type: string
- name: controlPlaneEndpointHost
required: true
schema:
openAPIV3Schema:
type: string
- name: tlsSan
required: true
schema:
openAPIV3Schema:
type: array
items:
type: string
infrastructure:
ref:
kind: Metal3ClusterTemplate
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
name: example-cluster-template-type2
controlPlane:
ref:
kind: RKE2ControlPlaneTemplate
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
name: example-controlplane-type2
patches:
- name: setControlPlaneMachineTemplate
definitions:
- selector:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlaneTemplate
matchResources:
controlPlane: true
jsonPatches:
- op: replace
path: "/spec/template/spec/infrastructureRef/name"
valueFrom:
variable: controlPlaneMachineTemplate
- name: setControlPlaneEndpoint
definitions:
- selector:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3ClusterTemplate
matchResources:
infrastructureCluster: true # Added to select InfraCluster
jsonPatches:
- op: replace
path: "/spec/template/spec/controlPlaneEndpoint/host"
valueFrom:
variable: controlPlaneEndpointHost
- name: setRegistrationAddress
definitions:
- selector:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlaneTemplate
matchResources:
controlPlane: true # Added to select ControlPlane
jsonPatches:
- op: replace
path: "/spec/template/spec/registrationAddress"
valueFrom:
variable: controlPlaneEndpointHost
- name: setTlsSan
definitions:
- selector:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlaneTemplate
matchResources:
controlPlane: true # Added to select ControlPlane
jsonPatches:
- op: replace
path: "/spec/template/spec/serverConfig/tlsSan"
valueFrom:
variable: tlsSan
- name: updateAdditionalUserData
definitions:
- selector:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlaneTemplate
matchResources:
controlPlane: true
jsonPatches:
- op: replace
path: "/spec/template/spec/agentConfig/additionalUserData"
valueFrom:
template: |
config: |
variant: fcos
version: 1.4.0
storage:
files:
- path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: endpoint-copier-operator
namespace: kube-system
spec:
chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
targetNamespace: endpoint-copier-operator
version: 303.0.0+up0.2.1
createNamespace: true
- path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
overwrite: true
contents:
inline: |
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: metallb
namespace: kube-system
spec:
chart: oci://registry.suse.com/edge/charts/metallb
targetNamespace: metallb-system
version: 303.0.0+up0.14.9
createNamespace: true
- path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
overwrite: true
contents:
inline: |
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- {{ .controlPlaneEndpointHost }}/32
serviceAllocation:
priority: 100
namespaces:
- default
serviceSelectors:
- matchExpressions:
- {key: "serviceType", operator: In, values: [kubernetes-vip]}
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- kubernetes-vip-ip-pool
- path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
overwrite: true
contents:
inline: |
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
labels:
serviceType: kubernetes-vip
spec:
ports:
- name: rke2-api
port: 9345
protocol: TCP
targetPort: 9345
- name: k8s-api
port: 6443
protocol: TCP
targetPort: 6443
type: LoadBalancer
systemd:
units:
- name: rke2-preinstall.service
enabled: true
contents: |
[Unit]
Description=rke2-preinstall
Wants=network-online.target
Before=rke2-install.service
ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
[Service]
Type=oneshot
User=root
ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
ExecStartPost=/bin/sh -c "umount /mnt"
[Install]
WantedBy=multi-user.target
29.4.2 クラスタインスタンス定義 #
ClusterClassのコンテキストにおいて、クラスタインスタンスとは、定義されているClusterClassに基づいて作成されたクラスタの特定の実行中のインスタンスを指します。これは、ClusterClassで指定されたブループリントから直接派生した固有の設定、リソース、および運用状態を持つ具体的なデプロイメントを表します。これには、アクティブに実行されている特定のマシンのセット、ネットワーキング設定、および関連するKubernetesコンポーネントが含まれます。クラスタインスタンスを理解することは、ClusterClassフレームワークを使用してプロビジョニングされた特定のデプロイ済みクラスタのライフサイクルの管理、アップグレードの実行、スケーリング操作の実行、および監視の実行に必要不可欠です。
クラスタインスタンスを定義するには、次のリソースを定義する必要があります。
Cluster
Metal3MachineTemplate
Metal3DataTemplate
テンプレート(ClusterClass定義ファイル)で以前に定義された変数は、クラスタのインスタンス化の最終値に置き換えられます。
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
topology:
class: example-clusterclass-type2 # Correct way to reference ClusterClass
version: v1.32.4+rke2r1
controlPlane:
replicas: 1
variables: # Variables to be replaced for this cluster instance
- name: controlPlaneMachineTemplate
value: emea-spa-cluster-3-machinetemplate
- name: controlPlaneEndpointHost
value: 192.168.122.203
- name: tlsSan
value:
- 192.168.122.203
- https://192.168.122.203.sslip.io
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: emea-spa-cluster-3-machinetemplate
namespace: emea-spa
spec:
nodeReuse: True
template:
spec:
automatedCleaningMode: metadata
dataTemplate:
name: emea-spa-cluster-3
hostSelector:
matchLabels:
cluster-role: control-plane
deploy-region: emea-spa
cluster-type: type2
image:
checksum: http://fileserver.local:8080/eibimage-downstream-cluster.raw.sha256
checksumType: sha256
format: raw
url: http://fileserver.local:8080/eibimage-downstream-cluster.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
name: emea-spa-cluster-3
namespace: emea-spa
spec:
clusterName: emea-spa-cluster-3
metaData:
objectNames:
- key: name
object: machine
- key: local-hostname
object: machine
このアプローチにより、ClusterClassを定義したら、3つのみのリソースでクラスタをデプロイする、より効率的なプロセスが可能になります。