31 全自动定向网络置备 #
31.1 简介 #
定向网络置备是用于自动置备下游群集的功能。如果您有许多下游群集需要置备并希望自动完成该过程,此功能将非常有用。
管理群集(第 29 章 “设置管理群集”)会自动部署以下组件:
SUSE Linux Enterprise Micro RT
(操作系统)。可以根据用例自定义网络、存储、用户和内核参数等配置。RKE2
(Kubernetes 群集)。默认的CNI
插件为Cilium
。根据具体的用例,可以使用Cilium+Multus
等某些CNI
插件。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 联网方案的先决条件 #
需要安装 Podman 或 Rancher Desktop 等容器运行时,以便能够运行 Edge Image Builder。
必须从 SUSE Customer Center 或 SUSE 下载页面下载
SLE-Micro.x86_64-5.5.0-Default-RT-GM.raw
基础映像。
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 目录包含首次引导时运行的脚本;目前需要使用
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}
是 root 用户的已加密口令,可用于测试/调试。可以使用
openssl passwd-6 PASSWORD
命令生成此口令
对于生产环境,建议使用可添加到 users 块的 SSH 密钥(将该块中的 ${USERKEY1}
替换为实际
SSH 密钥)。
net.ifnames=1
会启用可预测网络接口命名
这与 metal3 chart 的默认配置相匹配,但设置必须与配置的 chart
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 配置独立群集”。
与此解决方法相关的 bug 为 https://bugzilla.suse.com/show_bug.cgi?id=1217430
31.2.2.3 电信工作负载的附加配置 #
要启用 dpdk
、sr-iov
或
FEC
等电信功能,可能需要提供附加软件包,如以下示例中所示。
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 高级网络配置的附加脚本 #
如果您需要配置静态 IP 或第 31.6 节 “高级网络配置”中所述的更高级网络方案,则需要提供以下附加配置。
在 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 隔离方案的先决条件 #
需要安装 Podman 或 Rancher Desktop 等容器运行时,以便能够运行 Edge Image Builder。
必须从 SUSE Customer Center 或 SUSE 下载页面下载
SLE-Micro.x86_64-5.5.0-Default-RT-GM.raw
基础映像。如果您要使用 SR-IOV 或任何其他需要容器映像的工作负载,则必须部署并事先配置一个本地专用注册表(设置/未设置 TLS 和/或身份验证)。此注册表用于存储 Helm chart 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
目录包含首次引导时运行的脚本;目前需要使用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-chart OCI 映像并将其推送到专用注册表
下载、提取所需的其余映像并将其推送到专用注册表
可使用以下脚本下载、提取映像并将其推送到专用注册表。本节将通过一个示例来说明如何预加载 SR-IOV 映像,但您也可以使用相同的方法来预加载任何其他自定义映像:
预加载 SR-IOV 的 helm-chart OCI 映像:
必须创建一个包含所需 helm-chart 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
使用以下脚本和上面创建的列表生成本地 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
使用以下脚本将 tarball 文件上载到专用注册表(例如
myregistry:5000
),以预加载包含上一步骤中下载的 helm chart OCI 映像的注册表:$ tar zxvf edge-release-oci-tgz-20240705.tgz $ ./edge-load-oci-artefacts.sh -ad edge-release-oci-tgz-20240705 -r myregistry:5000
预加载 SR-IOV 所需的其余映像:
在这种情况下,必须包含电信工作负载的 sr-iov 容器映像(例如,作为参考,您可以从 helm-chart 值获取这些映像)
$ 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
必须使用以下脚本和上面创建的列表,在本地生成包含所需映像的 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
使用以下脚本将 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 使用定向网络置备来置备下游群集(单节点) #
本节介绍用于通过定向网络置备自动置备单节点下游群集的工作流程。这是自动置备下游群集的最简单方法。
要求
如上一节(第 31.2 节 “为联网方案准备下游群集映像”)所述使用
EIB
生成的、附带用于设置下游群集的最低限度配置的映像,必须位于管理群集上您按照注意一节所述配置的确切路径中。管理服务器已创建并可在后续章节中使用。有关详细信息,请参见管理群集相关的一章第 29 章 “设置管理群集”。
工作流程
下图显示了用于通过定向网络置备自动置备单节点下游群集的工作流程:
可以执行两个不同的步骤来使用定向网络置备自动置备单节点下游群集:
登记裸机主机,使其在置备过程中可用。
置备裸机主机,以安装并配置操作系统和 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}
— 裸机主机BMC
的URL
(例如redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/
)。要了解有关硬件提供商支持的不同选项的详细信息,请访问此链接。
创建该文件后,必须在管理群集中执行以下命令,才能在管理群集中开始登记新的裸机主机:
$ kubectl apply -f bmh-example.yaml
随后会登记新裸机主机对象,其状态将从正在注册依次更改为正在检查和可用。可使用以下命令检查状态更改:
$ kubectl get bmh
在验证 BMC
身份凭证之前,BaremetalHost
对象将一直处于正在注册
状态。验证身份凭证后,BaremetalHost
对象的状态将更改为正在检查
,此步骤可能需要一段时间(最长 20
分钟),具体取决于所用的硬件。在检查阶段,将检索硬件信息并更新 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
格式以及用于配置 RKE2
节点的
additionalUserData
,其中包含名为
rke2-preinstall.service
的 systemd 等信息,用于在置备过程中使用 Ironic
信息自动替换 BAREMETALHOST_UUID
和
node-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
对象指定以下信息:
dataTemplate
,用作对模板的引用。hostSelector
,在与登记过程中创建的标签匹配时使用。image
,用作对上一节(第 31.2 节 “为联网方案准备下游群集映像”)中使用EIB
生成的映像的引用;checksum
和checksumType
,用于验证映像。
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
自动置备多节点下游群集的工作流程。
要求
如上一节(第 31.2 节 “为联网方案准备下游群集映像”)所述使用
EIB
生成的、附带用于设置下游群集的最低限度配置的映像,必须位于管理群集上您按照注意一节所述配置的确切路径中。管理服务器已创建并可在后续章节中使用。有关详细信息,请参见管理群集相关的一章:第 29 章 “设置管理群集”。
工作流程
下图显示了用于通过定向网络置备自动置备多节点下游群集的工作流程:
登记三个裸机主机,使其在置备过程中可用。
置备三个裸机主机,以使用
MetalLB
安装并配置操作系统和 Kubernetes 群集。
登记裸机主机
第一步是在管理群集中登记三个裸机主机,使其可供置备。为此,必须在管理群集中创建以下文件(bmh-example-node1.yaml
、bmh-example-node2.yaml
和 bmh-example-node3.yaml
),以指定要使用的 BMC
身份凭证,以及要在管理群集中登记的 BaremetalHost
对象。
只需将
${...}
中的值替换为实际值。本节只会指导您完成一个主机的置备过程。这些步骤同样适用于另外两个节点。
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
随后会登记新裸机主机对象,其状态将从正在注册依次更改为正在检查和可用。可使用以下命令检查状态更改:
$ kubectl get bmh -o wide
在验证 BMC
身份凭证之前,BaremetalHost
对象将一直处于正在注册
状态。验证身份凭证后,BaremetalHost
对象的状态将更改为正在检查
,此步骤可能需要一段时间(最长 20
分钟),具体取决于所用的硬件。在检查阶段,将检索硬件信息并更新 Kubernetes 对象。使用以下命令检查信息:kubectl
get bmh -o yaml
。
置备步骤
三个裸机主机已登记并可供使用后,下一步是置备裸机主机,以安装和配置操作系统与 Kubernetes
群集,并创建用于管理该操作系统和群集的负载平衡器。为此,必须在管理群集中创建以下文件
(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
,因为使用了三个裸机节点。
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
地址)。serverConfig
,其中包含要使用的CNI
插件(在本例中为Cilium
);用于配置VIP
地址的tlsSan
。agentConfig 块包含要使用的
Ignition
格式以及用于配置RKE2
节点的additionalUserData
,其中的信息如下:名为
rke2-preinstall.service
的 systemd 服务,用于在置备过程中使用 Ironic 信息自动替换BAREMETALHOST_UUID
和node-name
。storage
块,其中包含用于安装MetalLB
和endpoint-copier-operator
的 Helm chart。metalLB
自定义资源文件,其中包含要使用的IPaddressPool
和L2Advertisement
(请将${EDGE_VIP_ADDRESS}
替换为VIP
地址)。用于配置
kubernetes-vip
服务的end-svc.yaml
文件,MetalLB
使用该服务来管理VIP
地址。
最后一个信息块包含要使用的 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
对象指定以下信息:
dataTemplate
,用作对模板的引用。hostSelector
,在与登记过程中创建的标签匹配时使用。image
,用作对上一节(第 31.2 节 “为联网方案准备下游群集映像”)中使用EIB
生成的映像的引用;checksum
和checksumType
,用于验证映像。
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
通过联接上述块创建该文件后,必须在管理群集中执行以下命令才能开始置备三个新的裸机主机:
$ kubectl apply -f capi-provisioning-example.yaml
31.6 高级网络配置 #
定向网络置备工作流程允许使用静态 IP、绑定、VLAN 等下游群集网络配置。
以下章节将介绍使用高级网络配置置备下游群集所要执行的附加步骤。
要求
使用
EIB
生成的映像必须包含第 31.2.2.4 节 “高级网络配置的附加脚本”一节中所述的 network 文件夹和脚本。
配置
基于以下两个章节的内容登记和置备主机:
使用定向网络置备来置备下游群集(单节点)(第 31.4 节 “使用定向网络置备来置备下游群集(单节点)”)
使用定向网络置备来置备下游群集(多节点)(第 31.5 节 “使用定向网络置备来置备下游群集(多节点)”)
需要做出以下更改才能启用高级网络配置:
登记步骤:以下新示例文件中的某个密钥包含有关
networkData
(用于配置下游群集的静态IP
和VLAN
等设置)的信息
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}
此文件包含用于配置下游群集的高级网络配置(例如静态 IP
和
VLAN
)的、采用 nmstate
格式的
networkData
。可以看到,该示例显示了启用采用静态 IP 的接口的配置,以及启用采用基础接口的 VLAN
的配置。可以定义任何其他 nmstate
示例来配置下游群集的网络以适应特定要求。必须将示例中的以下变量替换为实际值:
${CONTROLPLANE1_INTERFACE}
— 用于边缘群集的控制平面接口(例如eth0
)。${CONTROLPLANE1_IP}
— 用作边缘群集端点的 IP 地址(必须与 kubeapi-server 端点匹配)。${CONTROLPLANE1_PREFIX}
— 用于边缘群集的 CIDR(例如,如果您要使用/24
子网掩码,请指定24
;也可以指定255.255.255.0
)。${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
目前不支持 Metal3DataTemplate
、networkData
和
Metal3 IPAM
;只有通过静态密钥进行的配置才完全受支持。
31.7 电信功能(DPDK、SR-IOV、CPU 隔离、大页、NUMA 等) #
定向网络置备工作流程允许将下游群集中使用的电信功能自动化,以便在这些服务器上运行电信工作负载。
要求
使用
EIB
生成的映像必须包含第 31.2.2.3 节 “电信工作负载的附加配置”一节中所述的特定电信软件包。如上一节(第 31.2 节 “为联网方案准备下游群集映像”)所述使用
EIB
生成的映像必须位于管理群集上您按照注意一节所述配置的确切路径中。管理服务器已创建并可在后续章节中使用。有关详细信息,请参见管理群集相关的一章:第 29 章 “设置管理群集”。
配置
基于以下两个章节的内容登记和置备主机:
使用定向网络置备来置备下游群集(单节点)(第 31.4 节 “使用定向网络置备来置备下游群集(单节点)”)
使用定向网络置备来置备下游群集(多节点)(第 31.5 节 “使用定向网络置备来置备下游群集(多节点)”)
本节将介绍以下电信功能:
DPDK 和 VF 创建
工作负载使用的 SR-IOV 和 VF 分配
CPU 隔离和性能微调
大页配置
内核参数微调
有关电信功能的详细信息,请参见第 30 章 “电信功能配置”。
启用上述电信功能所要做出的更改都可以在 capi-provisioning-example.yaml
置备文件的
RKE2ControlPlane
块中完成。capi-provisioning-example.yaml
文件中的其余信息与置备相关章节(第 31.4 节 “使用定向网络置备来置备下游群集(单节点)”)中提供的信息相同。
明确地说,为启用电信功能而需要在该块 (RKE2ControlPlane
) 中所做的更改如下:
指定
preRKE2Commands
,用于在RKE2
安装过程开始之前执行命令。本例使用modprobe
命令启用vfio-pci
和SR-IOV
内核模块。指定 ignition 文件
/var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
,用于定义要创建的并向工作负载公开的接口、驱动程序及VF
数量。只有
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 | 允许内核在系统空闲时在单个 CPU 上运行计时器滴答周期。 |
nohz_full | 1-30,33-62 | 内核引导参数是当前用于配置完整 dynticks 及 CPU 隔离的主接口。 |
rcu_nocbs | 1-30,33-62 | 允许内核在系统空闲时在单个 CPU 上运行 RCU 回调。 |
kthread_cpus | 0,31,32,63 | 允许内核在系统空闲时在单个 CPU 上运行 kthreads。 |
irqaffinity | 0,31,32,63 | 允许内核在系统空闲时在单个 CPU 上运行中断。 |
processor.max_cstate | 1 | 防止 CPU 在空闲时进入休眠状态。 |
intel_idle.max_cstate | 0 | 禁用 intel_idle 驱动程序并允许使用 acpi_idle。 |
iommu | pt | 允许为 dpdk 接口使用 vfio。 |
intel_iommu | on | 允许为 VF 使用 vfio。 |
hugepagesz | 1G | 允许将大页的大小设置为 1 G。 |
hugepages | 40 | 先前定义的大页数量。 |
default_hugepagesz | 1G | 用于启用大页的默认值。 |
以下 systemd 服务用于启用下述功能:
rke2-preinstall.service
,用于在置备过程中使用 Ironic 信息自动替换BAREMETALHOST_UUID
和node-name
。cpu-performance.service
,用于启用 CPU 性能微调。必须将${CPU_FREQUENCY}
替换为实际值(例如,替换为2500000
会将 CPU 频率设置为2.5GHz
)。cpu-partitioning.service
,用于启用CPU
核心隔离(例如1-30,33-62
)。sriov-custom-auto-vfs.service
,用于安装sriov
Helm chart,等待创建自定义资源并运行/var/sriov-auto-filler.sh
,以替换配置映射sriov-custom-auto-config
中的值并创建工作负载要使用的sriovnetworknodepolicy
。
${RKE2_VERSION}
是要使用的RKE2
版本,请替换此值(例如替换为v1.28.9+rke2r1
)。
做出上述所有更改后,capi-provisioning-example.yaml
中的
RKE2ControlPlane
块如下所示:
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.crt
、tls.key
和
ca.crt
是用于对专用注册表进行身份验证的证书。username
和
password
是用于对专用注册表进行身份验证的身份凭证。
必须以 base64 格式对
tls.crt
、tls.key
、ca.crt
、username
和 password
进行编码才能在密钥中使用它们。
做出上述所有更改后,capi-provisioning-example.yaml
中的
RKE2ControlPlane
块如下所示:
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 隔离方案的要求 #
使用
EIB
生成的原始
映像必须包含用于在隔离方案中运行下游群集的特定容器映像(helm-chart OCI 和容器映像)。有关详细信息,请参见第 31.3 节 “为隔离方案准备下游群集映像”一节。如果使用 SR-IOV 或任何其他自定义工作负载,则必须按照有关预加载专用注册表的章节(第 31.3.2.5 节 “预加载包含隔离方案和 SR-IOV 所需映像的专用注册表(可选)”)中所述,在专用注册表中预加载用于运行工作负载的映像。
31.9.2 在隔离方案中登记裸机主机 #
在管理群集中登记裸机主机的过程与上一节(第 31.4 节 “使用定向网络置备来置备下游群集(单节点)”)中所述的过程相同。
31.9.3 在隔离方案中置备下游群集 #
需要做出一些重要更改才能在隔离方案中置备下游群集:
capi-provisioning-example.yaml
文件中的RKE2ControlPlane
块必须包含spec.agentConfig.airGapped: true
指令。必须按照有关专用注册表的章节(第 31.8 节 “专用注册表”)中所述,将专用注册表配置包含在
capi-provisioning-airgap-example.yaml
文件中的RKE2ControlPlane
块中。如果您正在使用 SR-IOV 或任何其他需要安装 helm-chart 的
AdditionalUserData
配置(combustion 脚本),则必须修改配置内容以引用专用注册表,而不是使用公共注册表。
以下示例显示了 capi-provisioning-airgap-example.yaml
文件的
AdditionalUserData
块中的 SR-IOV 配置,以及为了引用专用注册表而需要做出的修改
专用注册表密钥引用
在 Helm-Chart 定义中使用专用注册表而不是公共 OCI 映像。
# 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"