目次にジャンプページナビゲーションにジャンプ: 前のページ[アクセスキーp]/次のページ[アクセスキーn]
documentation.suse.com / SUSE Edgeドキュメント / 製品マニュアル / 完全に自動化されたダイレクトネットワークプロビジョニング

31 完全に自動化されたダイレクトネットワークプロビジョニング

31.1 はじめに

ダイレクトネットワークプロビジョニングは、ダウンストリームクラスタのプロビジョニングを自動化できる機能です。この機能は、プロビジョニングするダウンストリームクラスタが多数あり、そのプロセスを自動化したい場合に便利です。

管理クラスタ(第29章 「管理クラスタの設定)は、次のコンポーネントのデプロイメントを自動化します。

  • SUSE Linux Enterprise Micro RT (OS)。ユースケースに応じて、ネットワーキング、ストレージ、ユーザ、カーネル引数などの設定をカスタマイズできます。

  • RKE2 (Kubernetesクラスタ)。デフォルトのCNIプラグインはCiliumです。ユースケースに応じて、特定のCNIプラグイン(Cilium+Multusなど)を使用できます。

  • Longhorn (ストレージソリューション)。

  • NeuVector (セキュリティソリューション)。

  • MetalLB。高可用性マルチノードクラスタのロードバランサとして使用できます。

注記
注記

SUSE Linux Enterprise Microの詳細については第7章 「SLE Microを、RKE2の詳細については第14章 「RKE2を、Longhornの詳細については第15章 「Longhornを、NeuVectorの詳細については第16章 「NeuVectorをそれぞれ参照してください。

以降のセクションでは、さまざまなダイレクトネットワークプロビジョニングワークフローと、プロビジョニングプロセスに追加できる機能について説明します。

31.2 接続シナリオのダウンストリームクラスタイメージの準備

Edge Image Builder (第9章 「Edge Image Builder)を使用して、ダウンストリームクラスタホスト上にプロビジョニングされる、変更されたSLEMicroベースイメージを準備します。

ほとんどの設定はEdge Image Builderを使用して行うことができますが、このガイドではダウンストリームクラスタをセットアップするために必要な最小限の設定について説明します。

31.2.1 接続シナリオの前提条件

31.2.2 接続シナリオのイメージの設定

Edge Image Builderを実行すると、そのホストからディレクトリがマウントされるため、ターゲットイメージの定義に使用する設定ファイルを保存するディレクトリ構造を作成する必要があります。

  • downstream-cluster-config.yamlはイメージ定義ファイルです。詳細については、第3章 「Edge Image Builderを使用したスタンドアロンクラスタを参照してください。

  • ダウンロードされたベースイメージはxzで圧縮されているので、unxzで展開し、base-imagesフォルダの下にコピー/移動する必要があります。

  • networkフォルダはオプションです。詳細については、31.2.2.4項 「高度なネットワーク設定のための追加スクリプト」を参照してください。

  • custom/scriptsディレクトリには、初回ブート時に実行するスクリプトが含まれます。現在、デプロイメントのOSルートパーティションのサイズを変更するには、01-fix-growfs.shスクリプトが必要です。

├── downstream-cluster-config.yaml
├── base-images/
│   └ SLE-Micro.x86_64-5.5.0-Default-RT-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ scripts/
        └ 01-fix-growfs.sh

31.2.2.1 ダウンストリームクラスタイメージ定義ファイル

downstream-cluster-config.yamlファイルは、ダウンストリームクラスタイメージの主要な設定ファイルです。次に、Metal3を介したデプロイメントの最小例を示します。

apiVersion: 1.0
image:
  imageType: RAW
  arch: x86_64
  baseImage: SLE-Micro.x86_64-5.5.0-Default-RT-GM.raw
  outputImageName: eibimage-slemicro55rt-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
  users:
    - username: root
      encryptedPassword: ${ROOT_PASSWORD}
      sshKeys:
      - ${USERKEY1}

${ROOT_PASSWORD}はルートユーザの暗号化パスワードで、テスト/デバッグに役立ちます。このパスワードは、openssl passwd -6 PASSWORDコマンドで生成できます。

運用環境では、${USERKEY1}を実際のSSHキーに置き換えて、usersブロックに追加できるSSHキーを使用することをお勧めします。

注記
注記

net.ifnames=1は、Predictable Network Interface Namingを有効にします。

これはmetal3チャートのデフォルト設定と一致しますが、この設定は、設定されたチャートのpredictableNicNamesの値と一致する必要があります。

また、ignition.platform.id=openstackは必須であり、この引数がないと、Metal3の自動化フローでIgnitionによるSLEMicroの設定が失敗することにも注意してください。

31.2.2.2 Growfsスクリプト

現在、プロビジョニング後の初回ブート時にディスクサイズに合わせてファイルシステムを拡張するには、カスタムスクリプトcustom/scripts/01-fix-growfs.shが必要です。01-fix-growfs.shスクリプトには次の情報が含まれます。

#!/bin/bash
growfs() {
  mnt="$1"
  dev="$(findmnt --fstab --target ${mnt} --evaluate --real --output SOURCE --noheadings)"
  # /dev/sda3 -> /dev/sda, /dev/nvme0n1p3 -> /dev/nvme0n1
  parent_dev="/dev/$(lsblk --nodeps -rno PKNAME "${dev}")"
  # Last number in the device name: /dev/nvme0n1p42 -> 42
  partnum="$(echo "${dev}" | sed 's/^.*[^0-9]\([0-9]\+\)$/\1/')"
  ret=0
  growpart "$parent_dev" "$partnum" || ret=$?
  [ $ret -eq 0 ] || [ $ret -eq 1 ] || exit 1
  /usr/lib/systemd/systemd-growfs "$mnt"
}
growfs /
注記
注記

同じアプローチを使用して、プロビジョニングプロセス中に実行する独自のカスタムスクリプトを追加します。詳細については、第3章 「Edge Image Builderを使用したスタンドアロンクラスタを参照してください。

この回避策に関連するバグは、https://bugzilla.suse.com/show_bug.cgi?id=1217430です。

31.2.2.3 通信ワークロードの追加設定

dpdksr-iovFECなどの通信機能を有効にするには、次の例に示すように追加のパッケージが必要な場合があります。

apiVersion: 1.0
image:
  imageType: RAW
  arch: x86_64
  baseImage: SLE-Micro.x86_64-5.5.0-Default-RT-GM.raw
  outputImageName: eibimage-slemicro55rt-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
  users:
    - username: root
      encryptedPassword: ${ROOT_PASSWORD}
      sshKeys:
      - ${user1Key1}
  packages:
    packageList:
      - jq
      - dpdk22
      - dpdk22-tools
      - libdpdk-23
      - pf-bb-config
    additionalRepos:
      - url: https://download.opensuse.org/repositories/isv:/SUSE:/Edge:/Telco/SLEMicro5.5/
    sccRegistrationCode: ${SCC_REGISTRATION_CODE}

ここで、${SCC_REGISTRATION_CODE}SUSE Customer Centerからコピーした登録コードです。また、パッケージリストには通信事業者プロファイル用の最小限のパッケージが含まれています。pf-bb-configパッケージを使用するには(FEC機能とドライバへのバインドを有効にするには)、additionalReposブロックを含めてSUSE Edge Telcoリポジトリを追加する必要があります。

31.2.2.4 高度なネットワーク設定のための追加スクリプト

31.6項 「高度なネットワーク設定」で説明されている静的IPや、より高度なネットワーキングシナリオを設定する必要がある場合、次の追加設定が必要です。

networkフォルダに、次のconfigure-network.shファイルを作成します。 このファイルは、初回ブート時に設定ドライブデータを使用し、NM Configuratorツールを使用してホストネットワーキングを設定します。

#!/bin/bash

set -eux

# Attempt to statically configure a NIC in the case where we find a network_data.json
# In a configuration drive

CONFIG_DRIVE=$(blkid --label config-2 || true)
if [ -z "${CONFIG_DRIVE}" ]; then
  echo "No config-2 device found, skipping network configuration"
  exit 0
fi

mount -o ro $CONFIG_DRIVE /mnt

NETWORK_DATA_FILE="/mnt/openstack/latest/network_data.json"

if [ ! -f "${NETWORK_DATA_FILE}" ]; then
  umount /mnt
  echo "No network_data.json found, skipping network configuration"
  exit 0
fi

DESIRED_HOSTNAME=$(cat /mnt/openstack/latest/meta_data.json | tr ',{}' '\n' | grep '\"metal3-name\"' | sed 's/.*\"metal3-name\": \"\(.*\)\"/\1/')

mkdir -p /tmp/nmc/{desired,generated}
cp ${NETWORK_DATA_FILE} /tmp/nmc/desired/${DESIRED_HOSTNAME}.yaml
umount /mnt

./nmc generate --config-dir /tmp/nmc/desired --output-dir /tmp/nmc/generated
./nmc apply --config-dir /tmp/nmc/generated

31.2.3 イメージの作成

これまでのセクションに従ってディレクトリ構造を準備したら、次のコマンドを実行してイメージを構築します。

podman run --rm --privileged -it -v $PWD:/eib \
 registry.suse.com/edge/edge-image-builder:1.0.2 \
 build --definition-file downstream-cluster-config.yaml

これにより、上記の定義に基づいてeibimage-slemicro55rt-telco.rawという名前の出力ISOイメージファイルが作成されます。

その後、この出力イメージをWebサーバ経由で利用できるようにする必要があります。その際、管理クラスタのドキュメントを使用して有効にしたメディアサーバコンテナ(注記)か、ローカルにアクセス可能な他のサーバのいずれかを使用します。以下の例では、このサーバをimagecache.local:8080と呼びます。

31.3 エアギャップシナリオ用のダウンストリームクラスタイメージの準備

Edge Image Builder (第9章 「Edge Image Builder)を使用して、ダウンストリームクラスタホスト上にプロビジョニングされる、変更されたSLEMicroベースイメージを準備します。

設定の多くはEdge Image Builderを使用して行うことができますが、このガイドではエアギャップシナリオ用のダウンストリームクラスタの設定に必要な最小限の設定について説明します。

31.3.1 エアギャップシナリオの前提条件

  • Edge Image Builderを実行するには、PodmanRancher Desktopなどのコンテナランタイムが必要です。

  • ゴールデンイメージSLE-Micro.x86_64-5.5.0-Default-RT-GM.rawSUSE Customer CenterまたはSUSEダウンロードページからダウンロードする必要があります。

  • コンテナイメージが必要なSR-IOVなどのワークロードを使用する場合、ローカルのプライベートレジストリをデプロイして設定済みである必要があります(TLSまたは認証、あるいはその両方を使用/不使用)。このレジストリを使用して、イメージとHelmチャートOCIイメージを保存します。

31.3.2 エアギャップシナリオのイメージの設定

Edge Image Builderを実行すると、そのホストからディレクトリがマウントされるため、ターゲットイメージの定義に使用する設定ファイルを保存するディレクトリ構造を作成する必要があります。

  • downstream-cluster-airgap-config.yamlはイメージ定義ファイルです。詳細については、第3章 「Edge Image Builderを使用したスタンドアロンクラスタを参照してください。

  • ダウンロードされたベースイメージはxzで圧縮されているので、unxzで展開し、base-imagesフォルダの下にコピー/移動する必要があります。

  • networkフォルダはオプションです。詳細については、31.2.2.4項 「高度なネットワーク設定のための追加スクリプト」を参照してください。

  • custom/scriptsディレクトリには、初回ブート時に実行するスクリプトが含まれています。現在は、デプロイメントのOSルートパーティションのサイズを変更するために、スクリプト01-fix-growfs.shが必要です。エアギャップシナリオでは、イメージ作成プロセス中にイメージを正しい場所にコピーするために、スクリプト02-airgap.shが必要です。

  • custom/filesディレクトリには、イメージ作成プロセス中にそのイメージにコピーするrke2イメージとcniイメージが含まれています。

├── downstream-cluster-airgap-config.yaml
├── base-images/
│   └ SLE-Micro.x86_64-5.5.0-Default-RT-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ files/
    |   └ install.sh
    |   └ rke2-images-cilium.linux-amd64.tar.zst
    |   └ rke2-images-core.linux-amd64.tar.zst
    |   └ rke2-images-multus.linux-amd64.tar.zst
    |   └ rke2-images.linux-amd64.tar.zst
    |   └ rke2.linux-amd64.tar.zst
    |   └ sha256sum-amd64.txt
    └ scripts/
        └ 01-fix-growfs.sh
        └ 02-airgap.sh

31.3.2.1 ダウンストリームクラスタイメージ定義ファイル

downstream-cluster-airgap-config.yamlファイルは、ダウンストリームクラスタ用のメイン設定ファイルです。その内容については、前のセクション(31.2.2.3項 「通信ワークロードの追加設定」)で説明されています。

31.3.2.2 Growfsスクリプト

現在、プロビジョニング後の初回ブート時にディスクサイズに合わせてファイルシステムを拡張するには、カスタムスクリプトcustom/scripts/01-fix-growfs.shが必要です。01-fix-growfs.shスクリプトには次の情報が含まれます。

#!/bin/bash
growfs() {
  mnt="$1"
  dev="$(findmnt --fstab --target ${mnt} --evaluate --real --output SOURCE --noheadings)"
  # /dev/sda3 -> /dev/sda, /dev/nvme0n1p3 -> /dev/nvme0n1
  parent_dev="/dev/$(lsblk --nodeps -rno PKNAME "${dev}")"
  # Last number in the device name: /dev/nvme0n1p42 -> 42
  partnum="$(echo "${dev}" | sed 's/^.*[^0-9]\([0-9]\+\)$/\1/')"
  ret=0
  growpart "$parent_dev" "$partnum" || ret=$?
  [ $ret -eq 0 ] || [ $ret -eq 1 ] || exit 1
  /usr/lib/systemd/systemd-growfs "$mnt"
}
growfs /

31.3.2.3 エアギャップスクリプト

イメージ作成プロセス中にイメージを正しい場所にコピーするために、次のスクリプトcustom/scripts/02-airgap.shが必要です。

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/rke2-artifacts
mkdir -p /var/lib/rancher/rke2/agent/images

# copy the artifacts
cp install.sh /opt/
cp rke2-images*.tar.zst rke2.linux-amd64.tar.gz sha256sum-amd64.txt /opt/rke2-artifacts/

31.3.2.4 エアギャップシナリオのカスタムファイル

custom/filesディレクトリには、イメージ作成プロセス中にそのイメージにコピーするrke2イメージとcniイメージが含まれています。イメージを簡単に生成するには、次のスクリプトと、こちらにあるイメージのリストを使用してローカルでイメージを準備し、custom/filesに含める必要があるアーティファクトを生成します。また、最新のrke2-installスクリプトをこちらからダウンロードすることもできます。

$ ./edge-save-rke2-images.sh -o custom/files -l ~/edge-release-rke2-images.txt

イメージをダウンロードした後、ディレクトリ構造は次のようになるはずです。

└── custom/
    └ files/
        └ install.sh
        └ rke2-images-cilium.linux-amd64.tar.zst
        └ rke2-images-core.linux-amd64.tar.zst
        └ rke2-images-multus.linux-amd64.tar.zst
        └ rke2-images.linux-amd64.tar.zst
        └ rke2.linux-amd64.tar.zst
        └ sha256sum-amd64.txt

31.3.2.5 エアギャップシナリオおよびSR-IOV (オプション)に必要なイメージのプライベートレジストリへのプリロード

エアギャップシナリオまたはその他のワークロードイメージでSR-IOVを使用する場合、次の各手順に従って、ローカルのプライベートレジストリにイメージをプリロードする必要があります。

  • HelmチャートOCIイメージをダウンロードして抽出し、プライベートレジストリにプッシュする

  • 必要な残りのイメージをダウンロードして抽出し、プライベートレジストリにプッシュする

次のスクリプトを使用して、イメージをダウンロードして抽出し、プライベートレジストリにプッシュできます。これからSR-IOVイメージをプリロードする例を示しますが、その他のカスタムイメージも同じ方法でプリロードすることができます。

  1. SR-IOVのHelmチャートOCIイメージのプリロード:

    1. 必要なHelmチャートOCIイメージが含まれるリストを作成する必要があります。

      $ cat > edge-release-helm-oci-artifacts.txt <<EOF
      edge/sriov-network-operator-chart:1.2.2
      edge/sriov-crd-chart:1.2.2
      EOF
    2. 次のスクリプトと前の手順で作成したリストを使用して、ローカルのtarballファイルを生成します。

      $ ./edge-save-oci-artefacts.sh -al ./edge-release-helm-oci-artifacts.txt -s registry.suse.com
      Pulled: registry.suse.com/edge/sriov-network-operator-chart:1.2.2
      Pulled: registry.suse.com/edge/sriov-crd-chart:1.2.2
      a edge-release-oci-tgz-20240705
      a edge-release-oci-tgz-20240705/sriov-network-operator-chart-1.2.2.tgz
      a edge-release-oci-tgz-20240705/sriov-crd-chart-1.2.2.tgz
    3. 次のスクリプトを使用してtarballファイルをプライベートレジストリ(例: myregistry:5000)にアップロードし、前の手順でダウンロードしたHelmチャートOCIイメージをレジストリにプリロードします。

      $ tar zxvf edge-release-oci-tgz-20240705.tgz
      $ ./edge-load-oci-artefacts.sh -ad edge-release-oci-tgz-20240705 -r myregistry:5000
  2. SR-IOVに必要な残りのイメージをプリロードします。

    1. ここでは、通信ワークロードのために「sr-iov」コンテナイメージを含める必要があります(例: 参考として、これはhelmチャート値から取得できます)。

      $ cat > edge-release-images.txt <<EOF
      rancher/hardened-sriov-network-operator:v1.2.0-build20240327
      rancher/rancher/hardened-sriov-network-config-daemon:v1.2.0-build20240327
      rancher/hardened-sriov-cni:v1.2.0-build20240327
      rancher/hardened-ib-sriov-cni:v1.2.0-build20240327
      rancher/hardened-sriov-network-device-plugin:v1.2.0-build20240327
      rancher/hardened-sriov-network-resources-injector:v1.2.0-build20240327
      rancher/hardened-sriov-network-webhook:v1.2.0-build20240327
      EOF
    2. 次のスクリプトと前の手順で作成したリストを使用し、必要なイメージが含まれるtarballファイルをローカルで生成する必要があります。

      $ ./edge-save-images.sh -al ./edge-release-images.txt -s registry.suse.com
      Pulled: registry.suse.com/rancher/hardened-sriov-network-operator:v1.2.0-build20240327
      Pulled: registry.suse.com/rancher/rancher/hardened-sriov-network-config-daemon:v1.2.0-build20240327
      Pulled: registry.suse.com/rancher/hardened-sriov-cni:v1.2.0-build20240327
      Pulled: registry.suse.com/rancher/hardened-ib-sriov-cni:v1.2.0-build20240327
      Pulled: registry.suse.com/rancher/hardened-sriov-network-device-plugin:v1.2.0-build20240327
      Pulled: registry.suse.com/rancher/hardened-sriov-network-resources-injector:v1.2.0-build20240327
      Pulled: registry.suse.com/rancher/hardened-sriov-network-webhook:v1.2.0-build20240327
      a edge-release-images-tgz-20240705
      a edge-release-images-tgz-20240705/hardened-sriov-network-operator-v1.2.0-build20240327.tar.gz
      a edge-release-images-tgz-20240705/hardened-sriov-network-config-daemon-v1.2.0-build20240327.tar.gz
      a edge-release-images-tgz-20240705/hardened-sriov-cni-v1.2.0-build20240327.tar.gz
      a edge-release-images-tgz-20240705/hardened-ib-sriov-cni-v1.2.0-build20240327.tar.gz
      a edge-release-images-tgz-20240705/hardened-sriov-network-device-plugin-v1.2.0-build20240327.tar.gz
      a edge-release-images-tgz-20240705/hardened-sriov-network-resources-injector-v1.2.0-build20240327.tar.gz
      a edge-release-images-tgz-20240705/hardened-sriov-network-webhook-v1.2.0-build20240327.tar.gz
    3. 次のスクリプトを使用してtarballファイルをプライベートレジストリ(例: myregistry:5000)にアップロードし、前の手順でダウンロードしたイメージをプライベートレジストリにプリロードします。

      $ tar zxvf edge-release-images-tgz-20240705.tgz
      $ ./edge-load-images.sh -ad edge-release-images-tgz-20240705 -r myregistry:5000

31.3.3 エアギャップシナリオのイメージの作成

これまでのセクションに従ってディレクトリ構造を準備したら、次のコマンドを実行してイメージを構築します。

podman run --rm --privileged -it -v $PWD:/eib \
 registry.suse.com/edge/edge-image-builder:1.0.2 \
 build --definition-file downstream-cluster-airgap-config.yaml

これにより、上記の定義に基づいてeibimage-slemicro55rt-telco.rawという名前の出力ISOイメージファイルが作成されます。

その後、この出力イメージをWebサーバ経由で利用できるようにする必要があります。その際、管理クラスタドキュメントを使用して有効にしたメディアサーバコンテナ(注記)か、ローカルにアクセス可能な他のサーバのいずれかを使用します。以下の例では、このサーバをimagecache.local:8080として参照します。

31.4 ダイレクトネットワークプロビジョニングを使用したダウンストリームクラスタのプロビジョニング(シングルノード)

このセクションでは、ダイレクトネットワークプロビジョニングを使用してシングルノードのダウンストリームクラスタのプロビジョニングを自動化するために用いるワークフローについて説明します。これは、ダウンストリームクラスタのプロビジョニングを自動化する最もシンプルな方法です。

要件

ワークフロー

次の図は、ダイレクトネットワークプロビジョニングを使用してシングルノードのダウンストリームクラスタのプロビジョニングを自動化するために用いるワークフローを示しています。

atip自動化シングルノード1

ダイレクトネットワークプロビジョニングを使用してシングルノードのダウンストリームクラスタのプロビジョニングを自動化する手順は2種類です。

  1. ベアメタルホストを登録して、プロビジョニングプロセスで使用できるようにする。

  2. ベアメタルホストをプロビジョニングして、オペレーティングシステムとKubernetesクラスタをインストールして設定する。

ベアメタルホストの登録

最初の手順では、新しいベアメタルホストを管理クラスタに登録してプロビジョニングできるようにします。そのためには、次のファイル(bmh-example.yaml)を管理クラスタ内に作成して、使用するBMC資格情報と登録するBaremetalHostオブジェクトを指定する必要があります。

apiVersion: v1
kind: Secret
metadata:
  name: example-demo-credentials
type: Opaque
data:
  username: ${BMC_USERNAME}
  password: ${BMC_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: flexran-demo
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: ${BMC_MAC}
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: ${BMC_ADDRESS}
    disableCertificateVerification: true
    credentialsName: example-demo-credentials

各項目の内容は次のとおりです。

  • ${BMC_USERNAME} — 新しいベアメタルホストのBMCのユーザ名。

  • ${BMC_PASSWORD} — 新しいベアメタルホストのBMCのパスワード。

  • ${BMC_MAC} — 使用する新しいベアメタルホストのMACアドレス。

  • ${BMC_ADDRESS} — ベアメタルホストのBMCURL (例: redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/)。ハードウェアプロバイダに応じて使用できる各種のオプションの詳細については、こちらのリンクを確認してください。

ファイルを作成したら、管理クラスタで次のコマンドを実行し、管理クラスタで新しいベアメタルホストの登録を開始する必要があります。

$ kubectl apply -f bmh-example.yaml

新しいベアメタルホストオブジェクトが登録され、その状態が「Registering (登録中)」から「Inspecting (検査中)」に変わり、「Available (使用可能)」になります。この変更は次のコマンドを使用して確認できます。

$ kubectl get bmh
注記
注記

BaremetalHostオブジェクトは、BMCの資格情報が検証されるまでは「Registering (登録中)」の状態です。資格情報の検証が完了すると、BaremetalHostオブジェクトの状態が「Inspecting (検査中)」に変わります。この手順はハードウェアによっては多少時間がかかる可能性があります(最大で20分)。「Inspecting (検査中)」のフェーズ中に、ハードウェア情報が取得されてKubernetesオブジェクトが更新されます。kubectl get bmh -o yamlコマンドを使用して情報を確認してください。

プロビジョニング手順

ベアメタルホストが登録されて使用可能になったら、次に、ベアメタルホストをプロビジョニングしてオペレーティングシステムとKubernetesクラスタをインストールして設定します。そのためには、次の情報を使用して管理クラスタで以下のファイルcapi-provisioning-example.yamlを作成する必要があります(capi-provisioning-example.yamlは、以下のブロックを結合して生成できます)。

注記
注記

実際の値に置き換える必要があるのは、$\{…​\}の中の値だけです。

次のブロックはクラスタ定義です。ここで、podsブロックとservicesブロックを使用してネットワーキングを設定できます。また、ここにはコントロールプレーンオブジェクトと、使用するインフラストラクチャ(Metal3プロバイダを使用)オブジェクトへの参照も含まれています。

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: single-node-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
    kind: RKE2ControlPlane
    name: single-node-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: single-node-cluster

Metal3Clusterオブジェクトには、設定するコントロールプレーンのエンドポイント(${DOWNSTREAM_CONTROL_PLANE_IP}を置き換える)と、noCloudProvider(ベアメタルノードを使用しているため)を指定します。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: single-node-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: ${DOWNSTREAM_CONTROL_PLANE_IP}
    port: 6443
  noCloudProvider: true

RKE2ControlPlaneオブジェクトには、使用するコントロールプレーンの設定を指定し、Metal3MachineTemplateオブジェクトには、使用するコントロールプレーンのイメージを指定します。また、ここには使用するレプリカの数(ここでは1)と、使用するCNIプラグイン(ここではCilium)に関する情報が含まれています。agentConfigブロックには、使用するIgnitionの形式と、使用するadditionalUserDataが含まれます。これを使用して、RKE2ノードにrke2-preinstall.serviceという名前のsystemdサービスを設定し、プロビジョニングプロセス中にIronicの情報を使用してBAREMETALHOST_UUIDnode-nameを自動的に置き換えます。最後の情報ブロックには、使用するKubernetesバージョンが含まれています。${RKE2_VERSION}は使用するRKE2のバージョンであり、この値は置き換えます(例: v1.28.9+rke2r1)。

apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  serverConfig:
    cni: cilium
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        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
    version: ${RKE2_VERSION}
    nodeName: "localhost.localdomain"

Metal3MachineTemplateオブジェクトには次の情報を指定します。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: single-node-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: single-node-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/eibimage-slemicro55rt-telco.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/eibimage-slemicro55rt-telco.raw

Metal3DataTemplateオブジェクトには、ダウンストリームクラスタのmetaDataを指定します。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: single-node-cluster-controlplane-template
  namespace: default
spec:
  clusterName: single-node-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

前のブロックを結合してファイルを作成したら、管理クラスタで次のコマンドを実行して、新しいベアメタルホストのプロビジョニングを開始する必要があります。

$ kubectl apply -f capi-provisioning-example.yaml

31.5 ダイレクトネットワークプロビジョニングを使用したダウンストリームクラスタのプロビジョニング(マルチノード)

このセクションでは、ダイレクトネットワークプロビジョニングとMetalLBをロードバランサ戦略として使用して、マルチノードのダウンストリームクラスタのプロビジョニングを自動化するために使用するワークフローについて説明します。これはダウンストリームクラスタのプロビジョニングを自動化する最もシンプルな方法です。次の図は、ダイレクトネットワークプロビジョニングとMetalLBを使用してマルチノードのダウンストリームクラスタのプロビジョニングを自動化するためのワークフローを示しています。

要件

ワークフロー

次の図は、ダイレクトネットワークプロビジョニングを使用してマルチノードのダウンストリームクラスタのプロビジョニングを自動化するために使用するワークフローを示しています。

atip自動化マルチノード1
  1. 3つのベアメタルホストを登録し、プロビジョニングプロセスで使用できるようにする。

  2. 3つのベアメタルホストをプロビジョニングし、オペレーティングシステムと、MetalLBを使用するKubernetesクラスタをインストールして設定する。

ベアメタルホストの登録

最初の手順では、管理クラスタに3つのベアメタルホストを登録してプロビジョニングできるようにします。そのためには、管理クラスタにファイルbmh-example-node1.yamlbmh-example-node2.yaml、およびbmh-example-node3.yamlを作成して、使用するBMC資格情報と、管理クラスタに登録するBaremetalHostオブジェクトを指定する必要があります。

注記
注記
  • 実際の値に置き換える必要があるのは、$\{…​\}の中の値だけです。

  • 1つのホストのプロセスについてのみ説明します。他の2つのノードにも同じ手順が適用されます。

apiVersion: v1
kind: Secret
metadata:
  name: node1-example-credentials
type: Opaque
data:
  username: ${BMC_NODE1_USERNAME}
  password: ${BMC_NODE1_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: node1-example
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: ${BMC_NODE1_MAC}
  bmc:
    address: ${BMC_NODE1_ADDRESS}
    disableCertificateVerification: true
    credentialsName: node1-example-credentials

各項目の内容は次のとおりです。

  • ${BMC_NODE1_USERNAME} — 最初のベアメタルホストのBMCのユーザ名。

  • ${BMC_NODE1_PASSWORD} — 最初のベアメタルホストのBMCのパスワード。

  • ${BMC_NODE1_MAC} — 使用する最初のベアメタルホストのMACアドレス。

  • ${BMC_NODE1_ADDRESS} — 最初のベアメタルホストのBMCのURL (例: redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/)。ハードウェアプロバイダに応じて使用できる各種のオプションの詳細については、こちらのリンクを確認してください。

ファイルを作成したら、管理クラスタで次のコマンドを実行して、管理クラスタへのベアメタルホストの登録を開始する必要があります。

$ kubectl apply -f bmh-example-node1.yaml
$ kubectl apply -f bmh-example-node2.yaml
$ kubectl apply -f bmh-example-node3.yaml

新しいベアメタルホストオブジェクトが登録され、その状態が「Registering (登録中)」から「Inspecting (検査中)」に変わり、「Available (使用可能)」になります。この変更は次のコマンドを使用して確認できます。

$ kubectl get bmh -o wide
注記
注記

BaremetalHostオブジェクトは、BMCの資格情報が検証されるまでは「Registering (登録中)」の状態です。資格情報の検証が完了すると、BaremetalHostオブジェクトの状態が「Inspecting (検査中)」に変わります。この手順はハードウェアによっては多少時間がかかる可能性があります(最大で20分)。「Inspecting (検査中)」のフェーズ中に、ハードウェア情報が取得されてKubernetesオブジェクトが更新されます。kubectl get bmh -o yamlコマンドを使用して情報を確認してください。

プロビジョニング手順

3つのベアメタルホストが登録されて使用可能になったら、次の手順は、ベアメタルホストをプロビジョニングしてオペレーティングシステムとKubernetesクラスタをインストールして設定し、ロードバランサを作成して3つのベアメタルホストを管理することです。そのためには、次の情報を使用して管理クラスタにファイルcapi-provisioning-example.yamlを作成する必要があります(capi-provisioning-example.yamlは、次のブロックを結合して生成できます)。

注記
注記
  • 実際の値に置き換える必要があるのは、$\{…​\}の中の値だけです。

  • VIPアドレスは、どのノードにも割り当てられていない予約済みのIPアドレスであり、ロードバランサを設定するために使用されます。

以下はクラスタ定義です。ここで、podsブロックとservicesブロックを使用してクラスタのネットワークを設定できます。また、ここにはコントロールプレーンと、使用するインフラストラクチャ(Metal3プロバイダを使用)のオブジェクトへの参照も含まれています。

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: multinode-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
    kind: RKE2ControlPlane
    name: multinode-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: multinode-cluster

Metal3Clusterオブジェクトには、予約済みのVIPアドレス(${DOWNSTREAM_VIP_ADDRESS}を置き換え)を使用して設定するコントロールプレーンのエンドポイントと、noCloudProvider (3つのベアメタルノードを使用しているため)を指定しています。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: multinode-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: ${EDGE_VIP_ADDRESS}
    port: 6443
  noCloudProvider: true

RKE2ControlPlaneオブジェクトには、使用するコントロールプレーンの設定を指定し、Metal3MachineTemplateオブジェクトには、使用するコントロールプレーンのイメージを指定します。

  • 使用するレプリカの数(ここでは3)。

  • ロードバランサで使用するアドバタイズモード(addressではL2実装を使用)、および使用するアドレス(${EDGE_VIP_ADDRESS}VIPアドレスに置き換え)。

  • 使用するCNIプラグイン(ここではCilium)と、VIPアドレスの設定に使用するtlsSanが含まれるserverConfig

  • agentConfigブロックには、使用するIgnitionの形式と、RKE2ノードに次のような情報を設定するために使用するadditionalUserDataが含まれています。

    • プロビジョニングプロセス中にIronicの情報を使用してBAREMETALHOST_UUIDnode-nameを自動的に置き換える、rke2-preinstall.serviceという名前のsystemdサービス。

    • MetalLBendpoint-copier-operatorのインストールに使用するHelmチャートが含まれているstorageブロック。

    • 使用するIPaddressPoolL2Advertisementが含まれているmetalLBカスタムリソースファイル(${EDGE_VIP_ADDRESS}VIPアドレスに置き換え)。

    • MetalLBVIPアドレスを管理するために使用するkubernetes-vipサービスの設定に使用するendpoint-svc.yamlファイル。

  • 最後の情報ブロックには、使用するKubernetesバージョンが含まれています。${RKE2_VERSION}は、使用するRKE2のバージョンであり、この値は置き換えます(例: v1.28.9+rke2r1)。

apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
  name: multinode-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: multinode-cluster-controlplane
  replicas: 3
  registrationMethod: "address"
  registrationAddress: ${EDGE_VIP_ADDRESS}
  serverConfig:
    cni: cilium
    tlsSan:
      - ${EDGE_VIP_ADDRESS}
      - https://${EDGE_VIP_ADDRESS}.sslip.io
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        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
        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/endpoint-copier-operator-chart
                    targetNamespace: endpoint-copier-operator
                    version: 0.2.0
                    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/metallb-chart
                    targetNamespace: metallb-system
                    version: 0.14.3
                    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:
                      - ${EDGE_VIP_ADDRESS}/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
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    version: ${RKE2_VERSION}
    nodeName: "Node-multinode-cluster"

Metal3MachineTemplateオブジェクトには次の情報を指定します。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: multinode-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: multinode-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/eibimage-slemicro55rt-telco.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/eibimage-slemicro55rt-telco.raw

Metal3DataTemplateオブジェクトには、ダウンストリームクラスタのmetaDataを指定します。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: single-node-cluster-controlplane-template
  namespace: default
spec:
  clusterName: single-node-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

前のブロックを結合してファイルを作成したら、管理クラスタで次のコマンドを実行して、新しい3つのベアメタルホストのプロビジョニングを開始する必要があります。

$ kubectl apply -f capi-provisioning-example.yaml

31.6 高度なネットワーク設定

ダイレクトネットワークプロビジョニングのワークフローでは、静的IP、ボンディング、VLANなどのダウンストリームクラスタのネットワーク設定を行うことができます。

次の各セクションでは、高度なネットワーク設定を使用してダウンストリームクラスタをプロビジョニングできるようにするために必要な追加手順について説明します。

要件

設定

次の2つのセクションをベースとして使用し、ホストを登録してプロビジョニングします。

高度なネットワーク設定を有効にするために必要な変更は次のとおりです。

  • 登録手順: 設定に使用するnetworkDataに関する情報(例: ダウンストリームクラスタの静的IPVLAN)を格納したシークレットが含まれる新しいサンプルファイル

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: ${CONTROLPLANE_INTERFACE}
      type: ethernet
      state: up
      mtu: 1500
      mac-address: "${CONTROLPLANE_MAC}"
      ipv4:
        address:
        - ip:  "${CONTROLPLANE_IP}"
          prefix-length: "${CONTROLPLANE_PREFIX}"
        enabled: true
        dhcp: false
    - name: floating
      type: vlan
      state: up
      vlan:
        base-iface: ${CONTROLPLANE_INTERFACE}
        id: ${VLAN_ID}
    dns-resolver:
      config:
        server:
        - "${DNS_SERVER}"
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: "${CONTROLPLANE_GATEWAY}"
        next-hop-interface: ${CONTROLPLANE_INTERFACE}

このファイルには、ダウンストリームクラスタに高度なネットワーク設定(例: 静的IPVLAN)を行う場合に使用するnmstate形式のnetworkDataが含まれています。ご覧のとおり、この例は、静的IPを使用してインタフェースを有効にするための設定と、ベースインタフェースを使用してVLANを有効にするための設定を示しています。その他のnmstateの例を定義して、ダウンストリームクラスタのネットワークを特定の要件に適合するように設定できます。ここでは、次の変数を実際の値に置き換える必要があります。

  • ${CONTROLPLANE1_INTERFACE} — エッジクラスタに使用するコントロールプレーンインタフェース(例: eth0)。

  • ${CONTROLPLANE1_IP} — エッジクラスタのエンドポイントとして使用するIPアドレス(kubeapiサーバのエンドポイントと一致する必要があります)。

  • ${CONTROLPLANE1_PREFIX} — エッジクラスタに使用するCIDR (例: /24または255.255.255.0を使用する場合には24)。

  • ${CONTROLPLANE1_GATEWAY} — エッジクラスタに使用するゲートウェイ(例: 192.168.100.1)。

  • ${CONTROLPLANE1_MAC} — コントロールプレーンインタフェースに使用するMACアドレス(例: 00:0c:29:3e:3e:3e)。

  • ${DNS_SERVER} — エッジクラスタに使用するDNS (例: 192.168.100.2)。

  • ${VLAN_ID} — エッジクラスタに使用するVLAN ID (例: 100)。

また、管理クラスタに登録するには、ファイルの末尾にあるBaremetalHostオブジェクトに、preprovisioningNetworkDataNameを使用するシークレットへの参照が必要です。

apiVersion: v1
kind: Secret
metadata:
  name: example-demo-credentials
type: Opaque
data:
  username: ${BMC_USERNAME}
  password: ${BMC_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: flexran-demo
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: ${BMC_MAC}
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: ${BMC_ADDRESS}
    disableCertificateVerification: true
    credentialsName: example-demo-credentials
  preprovisioningNetworkDataName: controlplane-0-networkdata
注記
注記

マルチノードクラスタをデプロイする必要がある場合は、同じプロセスをその他のノードに対して実行する必要があります。

  • プロビジョニング手順: ネットワークデータに関連する情報のブロックを削除する必要があります。その理由は、ネットワークデータの設定は、プラットフォームによってシークレットcontrolplane-0-networkdataに組み込まれるためです。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: multinode-cluster-controlplane-template
  namespace: default
spec:
  clusterName: multinode-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine
注記
注記

Metal3DataTemplatenetworkData、およびMetal3 IPAMは現在サポートされていません。静的シークレットを介した設定のみが完全にサポートされています。

31.7 通信機能(DPDK、SR-IOV、CPUの分離、Huge Page、NUMAなど)

ダイレクトネットワークプロビジョニングのワークフローでは、ダウンストリームクラスタで使用する通信機能を自動化して、そのサーバ上で通信ワークロードを実行できます。

要件

設定

次の2つのセクションをベースとして使用し、ホストを登録してプロビジョニングします。

このセクションで説明する通信機能を次に示します。

  • DPDKとVFの作成

  • ワークロードで使用されるSR-IOVとVFの割り当て

  • CPUの分離とパフォーマンスの調整

  • Huge Pageの設定

  • カーネルパラメータの調整

注記
注記

通信機能の詳細については、第30章 「通信機能の設定を参照してください。

上記の通信機能を有効にするために必要な変更はすべて、プロビジョニングファイルcapi-provisioning-example.yamlRKE2ControlPlaneブロック内にあります。ファイルcapi-provisioning-example.yaml内の残りの情報は、プロビジョニングに関するセクション(31.4項 「ダイレクトネットワークプロビジョニングを使用したダウンストリームクラスタのプロビジョニング(シングルノード)」)で指定した情報と同じです。

このプロセスを明確にするために、通信機能を有効にするためにそのブロック(RKE2ControlPlane)で必要な変更を次に示します。

  • RKE2インストールプロセスの前にコマンドを実行するために使用するpreRKE2Commands。ここでは、modprobeコマンドを使用して、vfio-pciSR-IOVのカーネルモジュールを有効にします。

  • 作成してワークロードに公開するインタフェース、ドライバ、およびVFsの数を定義するために使用するIgnitionファイル/var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml

    • 実際の値に置き換える値は、設定マップsriov-custom-auto-config内の値のみです。

      • ${RESOURCE_NAME1} — 最初のPFインタフェースに使用するリソース名(例: sriov-resource-du1)。このリソース名はプレフィックスrancher.ioに追加されてラベルとして使用され、ワークロードで使用されます(例: rancher.io/sriov-resource-du1)。

      • ${SRIOV-NIC-NAME1} — 使用する最初のPFインタフェースの名前(例: eth0)。

      • ${PF_NAME1} — 使用する最初の物理機能PFの名前。これを使用して、より複雑なフィルタを生成します(例: eth0#2-5)。

      • ${DRIVER_NAME1} — 最初のVFインタフェースに使用するドライバ名(例: vfio-pci)。

      • ${NUM_VFS1} — 最初のPFインタフェース用に作成するVFの数(例: 8)。

  • /var/sriov-auto-filler.shは、高レベルの設定マップsriov-custom-auto-configと、低レベルのハードウェア情報を含むsriovnetworknodepolicyとの間で情報を変換するために使用されます。このスクリプトは、ユーザがハードウェア情報を事前に把握する手間をなくすために作成されています。このファイルを変更する必要はありませんが、sr-iovを有効にしてVFを作成する必要がある場合は、このファイルが存在する必要があります。

  • 次の機能を有効にするために使用するカーネル引数:

パラメータ

説明

isolcpus

1-30、33-62

コア1-30および33-62を分離します。

skew_tick

1

分離されたCPU間でカーネルがタイマー割り込みをずらすことができるようにします。

nohz

on

システムがアイドル状態のときにカーネルが1つのCPUでタイマーティックを実行できるようにします。

nohz_full

1-30、33-62

カーネルブートパラメータは、完全なdynticksとCPU分離の設定を行うための現在の主要インタフェースです。

rcu_nocbs

1-30、33-62

システムがアイドル状態のときにカーネルが1つのCPUでRCUコールバックを実行できるようにします。

kthread_cpus

0、31、32、63

システムがアイドル状態のときにカーネルが1つのCPUでkthreadsを実行できるようにします。

irqaffinity

0、31、32、63

システムがアイドル状態のときにカーネルが1つのCPUで割り込みを実行できるようにします。

processor.max_cstate

1

アイドル状態のときにCPUがスリープ状態にならないようにします。

intel_idle.max_cstate

0

intel_idleドライバを無効にし、acpi_idleを使用できるようにします。

iommu

pt

vfioをdpdkインタフェースに使用できるようにします。

intel_iommu

on

vfioをVFに使用できるようにします。

hugepagesz

1G

Huge Pageのサイズを1Gに設定できるようにします。

hugepages

40

前に定義したHuge Pageの数。

default_hugepagesz

1G

Huge Pageを有効にする場合のデフォルト値。

  • 次のsystemdサービスは、以下のサービスを有効にするために使用します。

    • rke2-preinstall.service - プロビジョニングプロセス中にIronicの情報を利用してBAREMETALHOST_UUIDnode-nameを自動的に置き換えます。

    • cpu-performance.service - CPUパフォーマンスの調整を有効にします。${CPU_FREQUENCY}は実際の値に置き換える必要があります(例: CPUの周波数を2.5GHzに設定する場合、2500000)。

    • cpu-partitioning.service - CPUの分離コアを有効にします(例: 1-30,33-62)。

    • sriov-custom-auto-vfs.service - sriov Helmチャートをインストールし、カスタムリソースが作成されるまで待機し、/var/sriov-auto-filler.shを実行して設定マップsriov-custom-auto-configの値を置き換えてワークロードが使用するsriovnetworknodepolicyを作成します。

  • ${RKE2_VERSION}は、この値の置き換えに使用するRKE2のバージョンです(例: v1.28.9+rke2r1)。

これらの変更をすべて行うと、capi-provisioning-example.yamlRKE2ControlPlaneブロックは次のようになります。

apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  serverConfig:
    cni: cilium
    cniMultusEnable: true
  preRKE2Commands:
    - modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        storage:
          files:
            - path: /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    name: sriov-custom-auto-config
                    namespace: kube-system
                  data:
                    config.json: |
                      [
                         {
                           "resourceName": "${RESOURCE_NAME1}",
                           "interface": "${SRIOV-NIC-NAME1}",
                           "pfname": "${PF_NAME1}",
                           "driver": "${DRIVER_NAME1}",
                           "numVFsToCreate": ${NUM_VFS1}
                         },
                         {
                           "resourceName": "${RESOURCE_NAME2}",
                           "interface": "${SRIOV-NIC-NAME2}",
                           "pfname": "${PF_NAME2}",
                           "driver": "${DRIVER_NAME2}",
                           "numVFsToCreate": ${NUM_VFS2}
                         }
                      ]
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/lib/rancher/rke2/server/manifests/sriov-crd.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-crd
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/sriov-crd-chart
                    targetNamespace: sriov-network-operator
                    version: 1.2.2
                    createNamespace: true
            - path: /var/lib/rancher/rke2/server/manifests/sriov-network-operator.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-network-operator
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/sriov-network-operator-chart
                    targetNamespace: sriov-network-operator
                    version: 1.2.2
                    createNamespace: true
            - path: /var/sriov-auto-filler.sh
              overwrite: true
              contents:
                inline: |
                  #!/bin/bash
                  cat <<- EOF > /var/sriov-networkpolicy-template.yaml
                  apiVersion: sriovnetwork.openshift.io/v1
                  kind: SriovNetworkNodePolicy
                  metadata:
                    name: atip-RESOURCENAME
                    namespace: sriov-network-operator
                  spec:
                    nodeSelector:
                      feature.node.kubernetes.io/network-sriov.capable: "true"
                    resourceName: RESOURCENAME
                    deviceType: DRIVER
                    numVfs: NUMVF
                    mtu: 1500
                    nicSelector:
                      pfNames: ["PFNAMES"]
                      deviceID: "DEVICEID"
                      vendor: "VENDOR"
                      rootDevices:
                        - PCIADDRESS
                  EOF

                  export KUBECONFIG=/etc/rancher/rke2/rke2.yaml; export KUBECTL=/var/lib/rancher/rke2/bin/kubectl
                  while [ $(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r '.items[].status.syncStatus') != "Succeeded" ]; do sleep 1; done
                  input=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get cm sriov-custom-auto-config -n kube-system -ojson | jq -r '.data."config.json"')
                  jq -c '.[]' <<< $input | while read i; do
                    interface=$(echo $i | jq -r '.interface')
                    pfname=$(echo $i | jq -r '.pfname')
                    pciaddress=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r ".items[].status.interfaces[]|select(.name==\"$interface\")|.pciAddress")
                    vendor=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r ".items[].status.interfaces[]|select(.name==\"$interface\")|.vendor")
                    deviceid=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r ".items[].status.interfaces[]|select(.name==\"$interface\")|.deviceID")
                    resourceName=$(echo $i | jq -r '.resourceName')
                    driver=$(echo $i | jq -r '.driver')
                    sed -e "s/RESOURCENAME/$resourceName/g" \
                        -e "s/DRIVER/$driver/g" \
                        -e "s/PFNAMES/$pfname/g" \
                        -e "s/VENDOR/$vendor/g" \
                        -e "s/DEVICEID/$deviceid/g" \
                        -e "s/PCIADDRESS/$pciaddress/g" \
                        -e "s/NUMVF/$(echo $i | jq -r '.numVFsToCreate')/g" /var/sriov-networkpolicy-template.yaml > /var/lib/rancher/rke2/server/manifests/$resourceName.yaml
                  done
              mode: 0755
              user:
                name: root
              group:
                name: root
        kernel_arguments:
          should_exist:
            - intel_iommu=on
            - intel_pstate=passive
            - processor.max_cstate=1
            - intel_idle.max_cstate=0
            - iommu=pt
            - mce=off
            - hugepagesz=1G hugepages=40
            - hugepagesz=2M hugepages=0
            - default_hugepagesz=1G
            - kthread_cpus=${NON-ISOLATED_CPU_CORES}
            - irqaffinity=${NON-ISOLATED_CPU_CORES}
            - isolcpus=${ISOLATED_CPU_CORES}
            - nohz_full=${ISOLATED_CPU_CORES}
            - rcu_nocbs=${ISOLATED_CPU_CORES}
            - rcu_nocb_poll
            - nosoftlockup
            - nohz=on
        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
            - name: cpu-performance.service
              enabled: true
              contents: |
                [Unit]
                Description=CPU perfomance
                Wants=network-online.target
                After=network.target network-online.target
                [Service]
                User=root
                Type=forking
                TimeoutStartSec=900
                ExecStart=/bin/sh -c "cpupower frequency-set -g performance; cpupower frequency-set -u ${CPU_FREQUENCY}; cpupower frequency-set -d ${CPU_FREQUENCY}"
                RemainAfterExit=yes
                KillMode=process
                [Install]
                WantedBy=multi-user.target
            - name: cpu-partitioning.service
              enabled: true
              contents: |
                [Unit]
                Description=cpu-partitioning
                Wants=network-online.target
                After=network.target network-online.target
                [Service]
                Type=oneshot
                User=root
                ExecStart=/bin/sh -c "echo isolated_cores=${ISOLATED_CPU_CORES} > /etc/tuned/cpu-partitioning-variables.conf"
                ExecStartPost=/bin/sh -c "tuned-adm profile cpu-partitioning"
                ExecStartPost=/bin/sh -c "systemctl enable tuned.service"
                [Install]
                WantedBy=multi-user.target
            - name: sriov-custom-auto-vfs.service
              enabled: true
              contents: |
                [Unit]
                Description=SRIOV Custom Auto VF Creation
                Wants=network-online.target  rke2-server.target
                After=network.target network-online.target rke2-server.target
                [Service]
                User=root
                Type=forking
                TimeoutStartSec=900
                ExecStart=/bin/sh -c "while ! /var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml wait --for condition=ready nodes --all ; do sleep 2 ; done"
                ExecStartPost=/bin/sh -c "while [ $(/var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml get sriovnetworknodestates.sriovnetwork.openshift.io --ignore-not-found --no-headers -A | wc -l) -eq 0 ]; do sleep 1; done"
                ExecStartPost=/bin/sh -c "/var/sriov-auto-filler.sh"
                RemainAfterExit=yes
                KillMode=process
                [Install]
                WantedBy=multi-user.target
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    version: ${RKE2_VERSION}
    nodeName: "localhost.localdomain"

前の各ブロックを結合してファイルを作成したら、管理クラスタで次のコマンドを実行し、通信機能を使用する新しいダウンストリームクラスタのプロビジョニングを開始する必要があります。

$ kubectl apply -f capi-provisioning-example.yaml

31.8 プライベートレジストリ

ワークロードで使用するイメージのミラーとしてプライベートレジストリを設定できます。

そのために、ダウンストリームクラスタで使用するプライベートレジストリに関する情報を含むシークレットを作成します。

apiVersion: v1
kind: Secret
metadata:
  name: private-registry-cert
  namespace: default
data:
  tls.crt: ${TLS_CERTIFICATE}
  tls.key: ${TLS_KEY}
  ca.crt: ${CA_CERTIFICATE}
type: kubernetes.io/tls
---
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-auth
  namespace: default
data:
  username: ${REGISTRY_USERNAME}
  password: ${REGISTRY_PASSWORD}

tls.crttls.key、およびca.crtは、プライベートレジストリを認証するために使用する証明書です。usernameおよびpasswordは、プライベートレジストリを認証するために使用する資格情報です。

注記
注記

tls.crttls.keyca.crtusername、およびpasswordは、シークレットで使用する前にbase64形式でエンコードする必要があります。

これらの変更をすべて行うと、capi-provisioning-example.yamlRKE2ControlPlaneブロックは次のようになります。

apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  privateRegistriesConfig:
    mirrors:
      "registry.example.com":
        endpoint:
          - "https://registry.example.com:5000"
    configs:
      "registry.example.com":
        authSecret:
          apiVersion: v1
          kind: Secret
          namespace: default
          name: private-registry-auth
        tls:
          tlsConfigSecret:
            apiVersion: v1
            kind: Secret
            namespace: default
            name: private-registry-cert
  serverConfig:
    cni: cilium
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        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
    version: ${RKE2_VERSION}
    nodeName: "localhost.localdomain"

ここで、registry.example.comは、ダウンストリームクラスタで使用するプライベートレジストリの名前の例です。これは実際の値に置き換える必要があります。

31.9 エアギャップシナリオでのダウンストリームクラスタのプロビジョニング

ダイレクトネットワークプロビジョニングワークフローでは、エアギャップシナリオでのダウンストリームクラスタのプロビジョニングを自動化できます。

31.9.1 エアギャップシナリオの要件

  1. EIBを使用して生成されたのイメージには、エアギャップシナリオでダウンストリームクラスタを実行するために必要な特定のコンテナイメージ(HelmチャートOCIイメージとコンテナイメージ)を含める必要があります。詳細については、こちらのセクション(31.3項 「エアギャップシナリオ用のダウンストリームクラスタイメージの準備」)を参照してください。

  2. SR-IOVまたはその他のカスタムワークロードを使用する場合、プライベートレジストリへのプリロードに関するセクション(31.3.2.5項 「エアギャップシナリオおよびSR-IOV (オプション)に必要なイメージのプライベートレジストリへのプリロード」)に従って、ワークロードを実行するために必要なイメージをプライベートレジストリにプリロードする必要があります。

31.9.2 エアギャップシナリオでのベアメタルホストの登録

管理クラスタにベアメタルホストを登録するプロセスは、前のセクション(31.4項 「ダイレクトネットワークプロビジョニングを使用したダウンストリームクラスタのプロビジョニング(シングルノード)」)で説明したプロセスと同じです。

31.9.3 エアギャップシナリオでのダウンストリームクラスタのプロビジョニング

エアギャップシナリオでダウンストリームクラスタをプロビジョニングするために必要となる重要な変更がいくつかあります。

  1. capi-provisioning-example.yamlファイルのRKE2ControlPlaneブロックにspec.agentConfig.airGapped: trueディレクティブを含める必要があります。

  2. プライベートレジストリに関するセクション(31.8項 「プライベートレジストリ」)に従って、プライベートレジストリの設定をcapi-provisioning-airgap-example.yamlファイルのRKE2ControlPlaneブロックに含める必要があります。

  3. SR-IOV、またはHelmチャートをインストールする必要があるその他のAdditionalUserData設定(combustionスクリプト)を使用している場合、内容を変更して、パブリックレジストリを使用するのではなくプライベートレジストリを参照する必要があります。

次の例は、プライベートレジストリを参照するために必要な変更を行った、capi-provisioning-airgap-example.yamlファイルのAdditionalUserDataブロックのSR-IOVの設定を示しています。

  • プライベートレジストリのシークレットの参照

  • パブリックOCIイメージではなくプライベートレジストリを使用するHelmチャートの定義

# secret to include the private registry certificates
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-cert
  namespace: default
data:
  tls.crt: ${TLS_BASE64_CERT}
  tls.key: ${TLS_BASE64_KEY}
  ca.crt: ${CA_BASE64_CERT}
type: kubernetes.io/tls
---
# secret to include the private registry auth credentials
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-auth
  namespace: default
data:
  username: ${REGISTRY_USERNAME}
  password: ${REGISTRY_PASSWORD}
---
apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  privateRegistriesConfig:       # Private registry configuration to add your own mirror and credentials
    mirrors:
      docker.io:
        endpoint:
          - "https://$(PRIVATE_REGISTRY_URL)"
    configs:
      "192.168.100.22:5000":
        authSecret:
          apiVersion: v1
          kind: Secret
          namespace: default
          name: private-registry-auth
        tls:
          tlsConfigSecret:
            apiVersion: v1
            kind: Secret
            namespace: default
            name: private-registry-cert
          insecureSkipVerify: false
  serverConfig:
    cni: cilium
    cniMultusEnable: true
  preRKE2Commands:
    - modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  agentConfig:
    airGapped: true       # Airgap true to enable airgap mode
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        storage:
          files:
            - path: /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    name: sriov-custom-auto-config
                    namespace: sriov-network-operator
                  data:
                    config.json: |
                      [
                         {
                           "resourceName": "${RESOURCE_NAME1}",
                           "interface": "${SRIOV-NIC-NAME1}",
                           "pfname": "${PF_NAME1}",
                           "driver": "${DRIVER_NAME1}",
                           "numVFsToCreate": ${NUM_VFS1}
                         },
                         {
                           "resourceName": "${RESOURCE_NAME2}",
                           "interface": "${SRIOV-NIC-NAME2}",
                           "pfname": "${PF_NAME2}",
                           "driver": "${DRIVER_NAME2}",
                           "numVFsToCreate": ${NUM_VFS2}
                         }
                      ]
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/lib/rancher/rke2/server/manifests/sriov.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  data:
                    .dockerconfigjson: ${REGISTRY_AUTH_DOCKERCONFIGJSON}
                  kind: Secret
                  metadata:
                    name: privregauth
                    namespace: kube-system
                  type: kubernetes.io/dockerconfigjson
                  ---
                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    namespace: kube-system
                    name: example-repo-ca
                  data:
                    ca.crt: |-
                      -----BEGIN CERTIFICATE-----
                      ${CA_BASE64_CERT}
                      -----END CERTIFICATE-----
                  ---
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-crd
                    namespace: kube-system
                  spec:
                    chart: oci://${PRIVATE_REGISTRY_URL}/sriov-crd
                    dockerRegistrySecret:
                      name: privregauth
                    repoCAConfigMap:
                      name: example-repo-ca
                    createNamespace: true
                    set:
                      global.clusterCIDR: 192.168.0.0/18
                      global.clusterCIDRv4: 192.168.0.0/18
                      global.clusterDNS: 10.96.0.10
                      global.clusterDomain: cluster.local
                      global.rke2DataDir: /var/lib/rancher/rke2
                      global.serviceCIDR: 10.96.0.0/12
                    targetNamespace: sriov-network-operator
                    version: ${SRIOV_CRD_VERSION}
                  ---
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-network-operator
                    namespace: kube-system
                  spec:
                    chart: oci://${PRIVATE_REGISTRY_URL}/sriov-network-operator
                    dockerRegistrySecret:
                      name: privregauth
                    repoCAConfigMap:
                      name: example-repo-ca
                    createNamespace: true
                    set:
                      global.clusterCIDR: 192.168.0.0/18
                      global.clusterCIDRv4: 192.168.0.0/18
                      global.clusterDNS: 10.96.0.10
                      global.clusterDomain: cluster.local
                      global.rke2DataDir: /var/lib/rancher/rke2
                      global.serviceCIDR: 10.96.0.0/12
                    targetNamespace: sriov-network-operator
                    version: ${SRIOV_OPERATOR_VERSION}
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/sriov-auto-filler.sh
              overwrite: true
              contents:
                inline: |
                  #!/bin/bash
                  cat <<- EOF > /var/sriov-networkpolicy-template.yaml
                  apiVersion: sriovnetwork.openshift.io/v1
                  kind: SriovNetworkNodePolicy
                  metadata:
                    name: atip-RESOURCENAME
                    namespace: sriov-network-operator
                  spec:
                    nodeSelector:
                      feature.node.kubernetes.io/network-sriov.capable: "true"
                    resourceName: RESOURCENAME
                    deviceType: DRIVER
                    numVfs: NUMVF
                    mtu: 1500
                    nicSelector:
                      pfNames: ["PFNAMES"]
                      deviceID: "DEVICEID"
                      vendor: "VENDOR"
                      rootDevices:
                        - PCIADDRESS
                  EOF

                  export KUBECONFIG=/etc/rancher/rke2/rke2.yaml; export KUBECTL=/var/lib/rancher/rke2/bin/kubectl
                  while [ $(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r '.items[].status.syncStatus') != "Succeeded" ]; do sleep 1; done
                  input=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get cm sriov-custom-auto-config -n sriov-network-operator -ojson | jq -r '.data."config.json"')
                  jq -c '.[]' <<< $input | while read i; do
                    interface=$(echo $i | jq -r '.interface')
                    pfname=$(echo $i | jq -r '.pfname')
                    pciaddress=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r ".items[].status.interfaces[]|select(.name==\"$interface\")|.pciAddress")
                    vendor=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r ".items[].status.interfaces[]|select(.name==\"$interface\")|.vendor")
                    deviceid=$(${KUBECTL} --kubeconfig=${KUBECONFIG} get sriovnetworknodestates.sriovnetwork.openshift.io -n sriov-network-operator -ojson | jq -r ".items[].status.interfaces[]|select(.name==\"$interface\")|.deviceID")
                    resourceName=$(echo $i | jq -r '.resourceName')
                    driver=$(echo $i | jq -r '.driver')
                    sed -e "s/RESOURCENAME/$resourceName/g" \
                        -e "s/DRIVER/$driver/g" \
                        -e "s/PFNAMES/$pfname/g" \
                        -e "s/VENDOR/$vendor/g" \
                        -e "s/DEVICEID/$deviceid/g" \
                        -e "s/PCIADDRESS/$pciaddress/g" \
                        -e "s/NUMVF/$(echo $i | jq -r '.numVFsToCreate')/g" /var/sriov-networkpolicy-template.yaml > /var/lib/rancher/rke2/server/manifests/$resourceName.yaml
                  done
              mode: 0755
              user:
                name: root
              group:
                name: root
        kernel_arguments:
          should_exist:
            - intel_iommu=on
            - intel_pstate=passive
            - processor.max_cstate=1
            - intel_idle.max_cstate=0
            - iommu=pt
            - mce=off
            - hugepagesz=1G hugepages=40
            - hugepagesz=2M hugepages=0
            - default_hugepagesz=1G
            - kthread_cpus=${NON-ISOLATED_CPU_CORES}
            - irqaffinity=${NON-ISOLATED_CPU_CORES}
            - isolcpus=${ISOLATED_CPU_CORES}
            - nohz_full=${ISOLATED_CPU_CORES}
            - rcu_nocbs=${ISOLATED_CPU_CORES}
            - rcu_nocb_poll
            - nosoftlockup
            - nohz=on
        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
            - name: cpu-partitioning.service
              enabled: true
              contents: |
                [Unit]
                Description=cpu-partitioning
                Wants=network-online.target
                After=network.target network-online.target
                [Service]
                Type=oneshot
                User=root
                ExecStart=/bin/sh -c "echo isolated_cores=${ISOLATED_CPU_CORES} > /etc/tuned/cpu-partitioning-variables.conf"
                ExecStartPost=/bin/sh -c "tuned-adm profile cpu-partitioning"
                ExecStartPost=/bin/sh -c "systemctl enable tuned.service"
                [Install]
                WantedBy=multi-user.target
            - name: sriov-custom-auto-vfs.service
              enabled: true
              contents: |
                [Unit]
                Description=SRIOV Custom Auto VF Creation
                Wants=network-online.target  rke2-server.target
                After=network.target network-online.target rke2-server.target
                [Service]
                User=root
                Type=forking
                TimeoutStartSec=900
                ExecStart=/bin/sh -c "while ! /var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml wait --for condition=ready nodes --all ; do sleep 2 ; done"
                ExecStartPost=/bin/sh -c "while [ $(/var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml get sriovnetworknodestates.sriovnetwork.openshift.io --ignore-not-found --no-headers -A | wc -l) -eq 0 ]; do sleep 1; done"
                ExecStartPost=/bin/sh -c "/var/sriov-auto-filler.sh"
                RemainAfterExit=yes
                KillMode=process
                [Install]
                WantedBy=multi-user.target
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    version: ${RKE2_VERSION}
    nodeName: "localhost.localdomain"