documentation.suse.com / SUSE Edgeドキュメント / ハウツーガイド / ClusterClassを使用したダウンストリームクラスタのデプロイ

29 ClusterClassを使用したダウンストリームクラスタのデプロイ

29.1 はじめに

Kubernetesクラスタのプロビジョニングは、クラスタコンポーネントの設定に深い専門知識が求められる複雑な作業です。設定が複雑化したり、さまざまなプロバイダからの要求により多数のプロバイダ固有のリソース定義が導入されたりすると、クラスタの作成が困難に感じられるかもしれません。幸いなことに、Kubernetes Cluster API (CAPI)は、ClusterClassによってさらに強化された、より洗練された宣言型アプローチを提供します。この機能はテンプレート駆動型モデルを導入し、複雑さをカプセル化して一貫性を促進する再利用可能なクラスタクラスを定義できます。

29.2 ClusterClassとは

CAPIプロジェクトは、クラスタのインスタンス化にテンプレートベースの手法を採用することで、Kubernetesクラスタのライフサイクル管理におけるパラダイムシフトとしてClusterClass機能を導入しました。ユーザがクラスタごとにリソースを個別に定義する代わりに、ClusterClassを定義することで、ClusterClassは包括的で再利用可能なブループリントとして機能します。この抽象データ型表現は、Kubernetesクラスタの望ましい状態と設定をカプセル化し、定義された仕様に準拠した複数のクラスタを迅速かつ一貫して作成できるようにします。 この抽象データ型により、設定の負担が軽減され、より管理しやすいデプロイメントマニフェストが実現されます。つまり、ワークロードクラスタのコアコンポーネントはクラスレベルで定義されるため、ユーザはこれらのテンプレートをKubernetesクラスタのフレーバーとして使用し、クラスタのプロビジョニングに1回または複数回再利用できるようになります。ClusterClassの実装は、従来の大規模なCAPI管理に固有の課題に対処するいくつかの重要な利点をもたらします。

  • 複雑さとYAMLの冗長性を大幅に削減

  • 最適化された保守と更新プロセス

  • デプロイメント全体における一貫性と標準化の強化

  • スケーラビリティと自動化機能の向上

  • 宣言型管理と堅牢なバージョン管理

ClusterClass

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つのみのリソースでクラスタをデプロイする、より効率的なプロセスが可能になります。

Documentation survey