- SUSE Edge 文档
- I 快速入门
- II 使用的组件
- III 操作指南
- IV 第三方集成
- V Day 2 操作
- VI 产品文档
- VII 附录
- 25.1 Kubernetes 升级计划 Pod 示例
- 25.2 操作系统软件包更新计划 Pod 示例
- 25.3 HA 群集上 EIB 部署的 Helm chart 的升级计划 Pod 示例
- 25.4 操作系统软件包更新工作流程
- 25.5 Kubernetes 版本升级工作流程
- 25.6 Helm chart 升级工作流程
- 25.7 longhorn-single-k3s 安装的 Longhorn 版本
- 25.8 longhorn-ha-rke2 安装的 Longhorn 版本
- 25.9 成功部署 SUC 和 Longhorn GitRepo
- 25.10 升级初始化器节点上运行的 Pod
- 25.11 升级非初始化器节点上运行的 Pod
- 25.12 已成功完成的 helm-install Pod
- 25.13 已成功完成的 helm-install Pod 的日志
- 25.14 longhorn-single-k3s 上已升级的 Longhorn 版本
- 25.15 longhorn-ha-rke2 上已升级的 Longhorn 版本
SUSE Edge 文档 #
欢迎阅读 SUSE Edge 文档,在其中可以找到快速入门指南、经过验证的设计、组件用法指南、第三方集成,以及有关管理边缘计算基础架构和工作负载的最佳实践。
1 什么是 SUSE Edge? #
SUSE Edge 是有针对性的、紧密集成且经过全面验证的端到端解决方案,用于解决在边缘处部署基础架构和云原生应用程序时存在的独特挑战。其核心作用是提供一个有主见但高度灵活、高度可缩放且安全的平台,涵盖初始部署映像的构建、节点置备和初始配置、应用程序部署、可观测性和完整生命周期操作。该平台从一开始就构建于同类最佳的开源软件基础之上,与我们 30 年来提供安全、稳定且经认证的 SUSE Linux 平台的历史,以及通过 Rancher 产品组合提供高度可缩放且功能丰富的 Kubernetes 管理经验相一致。SUSE Edge 是基于这些功能构建的,可以提供满足众多细分市场需求的功能,包括零售、医疗、交通、物流、电信、智能制造和工业物联网 (IoT)。
2 设计理念 #
该解决方案的设计考虑到了客户的需求和期望千差万别,因此不存在“以一应百”的边缘平台。边缘部署促使我们解决并不断设想出一些极具挑战性的问题,包括大规模可伸缩性、网络受限情况下的可用性、物理空间限制、新的安全威胁和攻击途径、硬件体系结构和系统资源的差异、部署旧式基础架构和应用程序并与之连接的要求,以及使用寿命较长的客户解决方案。由于其中的许多挑战与传统思维方式不同(例如在数据中心或公有云中部署基础架构和应用程序),我们必须更仔细地审视设计,并反复思考许多常见假设条件。
例如,我们发现极简主义、模块化和易操作性具有重要价值。极简主义对于边缘环境非常重要,因为系统越复杂,就越容易出现故障。在分析数百个甚至数十万个位置后,我们发现复杂的系统会出现纷繁复杂的故障。解决方案中的模块化允许用户做出更多选择,同时消除部署的平台中不必要的复杂性。我们还需要在这些方面与易操作性之间取得平衡。人类用户在重复某个流程数千次后可能会出现失误,因此平台应确保任何潜在失误都可恢复,从而消除技术人员亲临现场解决问题的需要,同时尽力实现一致性和标准化。
3 应使用哪一篇快速入门? #
由于操作环境和生命周期要求各不相同,我们已针对一些不同的部署模式履行了支持,这些模式与 SUSE Edge 所属的细分市场和用例大体一致。我们为其中的每种部署模式编写了一份快速入门指南,以帮助您根据自己的需求熟悉 SUSE Edge 平台。下面介绍了我们目前支持的三种部署模式,并附有相关快速入门页面的链接。
3.1 定向网络置备 #
定向网络置备适用于您知道所要部署到的硬件的细节,并可以直接访问带外管理界面来协调和自动化整个置备过程的情况。在这种情况下,客户预期解决方案能够从一个中心位置全自动地置备边缘站点,并可以最大限度地减少边缘位置的手动操作,也就是说,解决方案的作用远不止是创建引导映像;您只需将物理硬件装入机架、通电并为其连接所需的网络,自动化过程就会通过带外管理(例如通过 Redfish API)打开计算机电源并处理基础架构的置备、初始配置和部署,全程无需用户的干预。做到这一点的关键在于管理员了解系统;他们知道哪个硬件在哪个位置,并且部署预期可以得到集中处理。
此解决方案最为稳健,因为您可以直接与硬件的管理界面交互和处理已知硬件,并且很少会遇到网络可用性方面的限制。在功能上,此解决方案广泛使用群集 API 和 Metal3 来自动完成从裸机到操作系统、Kubernetes 和分层应用程序的置备,还可让您链接到 SUSE Edge 部署后的其他常用生命周期管理功能。此解决方案的快速入门可在第 1 章 “使用 Metal3 实现 BMC 自动化部署”中找到。
3.2 “电告总部”网络置备 #
有时,在您的操作环境中,中心管理群集无法直接管理硬件(例如,您的远程网络位于防火墙后面,或者没有带外管理界面;这种情况在边缘处经常使用的“PC”型硬件中很常见)。对于这种情况,我们提供了相应的工具来远程置备群集及其工作负载,而无需知道硬件在引导时位于何处。这就是大多数人对边缘计算的看法;有成千上万种不太常见的系统在边缘位置引导、安全地电告总部、验证它们的身份,并接收有关要执行哪种操作的指令。为此,我们希望除了出厂前预先构建计算机映像,或者简单挂接引导映像(例如通过 USB)来打开系统外,置备和生命周期管理工作几乎不需要用户干预即可完成。在此方面存在的主要挑战是如何解决这些设备在各种环境下的缩放性、一致性、安全性和生命周期。
此解决方案针对系统置备和初始配置方式提供了极大的灵活性和一致性,不受系统位置、类型或规格以及首次开机时间的影响。在 SUSE Edge 中,可以通过 Edge Image Builder 十分灵活地对系统进行自定义,同时可以利用 Rancher Elemental 提供的注册功能来初始配置节点和置备 Kubernetes,并利用 SUSE Manager 来修补操作系统。此解决方案的快速入门可在第 2 章 “使用 Elemental 进行远程主机初始配置”中找到。
3.3 基于映像的置备 #
对于需要在独立、隔离或网络受限的环境中操作的客户,SUSE Edge 提供了一种解决方案供客户生成完全自定义的安装媒体,其中包含所有必要的部署项目,用于在边缘启用单节点和多节点高可用性 Kubernetes 群集,包括任何所需的工作负载或其他分层组件。所有这些项目无需与外界建立任何网络连接,且无需集中式管理平台的干预。用户体验与“电告总部”解决方案非常相似,安装媒体同样会提供给目标系统,但该解决方案会“就地引导”。在这种情况下,可将创建的群集挂接到 Rancher 进行持续管理(即从“断开连接”转换为“已连接”操作模式,无需经过大范围的重新配置或重新部署),或者群集可以继续独立运行。请注意,在这两种情况下,都可以应用相同的一致性机制来自动执行生命周期操作。
此外,使用此解决方案可以快速创建管理集群,这些管理群集可以托管同时支持“定向网络置备”和“电告总部网络置备”模型的集中式基础架构,因为它可能是置备各种 Edge 基础架构最快速、最简单的方式。此解决方案重度使用 SUSE Edge Image Builder 的功能来创建完全自定义的无人照管安装媒体;快速入门可在第 3 章 “使用 Edge Image Builder 配置独立群集”中找到。
4 SUSE Edge 中使用的组件 #
SUSE Edge 由现有的 SUSE 组件(包括 Linux 和 Rancher 团队提供的组件),以及 Edge 团队构建的、使 SUSE 能够解决基础架构要求和各种复杂问题的其他功能和组件构成。在以下章节中可以找到组件列表,以及每个组件的简要介绍及其在 SUSE Edge 中的用法的链接:
Rancher(第 4 章 “Rancher”)
Rancher 仪表板扩展(第 5 章 “Rancher 仪表板扩展”)
Fleet(第 6 章 “Fleet”)
SLE Micro(第 7 章 “SLE Micro”)
Metal³(第 8 章 “Metal3”)
Edge Image Builder(第 9 章 “Edge Image Builder”)
NetworkManager Configurator(第 10 章 “边缘网络”)
Elemental(第 11 章 “Elemental”)
Akri(第 12 章 “Akri”)
K3s(第 13 章 “K3s”)
RKE2(第 14 章 “RKE2”)
Longhorn(第 15 章 “Longhorn”)
NeuVector(第 16 章 “NeuVector”)
MetalLB(第 17 章 “MetalLB”)
KubeVirt(第 18 章 “边缘虚拟化”)
第 I 部分 快速入门 #
从这里快速入门
- 1 使用 Metal3 实现 BMC 自动化部署
Metal3 是一个 CNCF 项目,它为 Kubernetes 提供裸机基础架构管理功能。
- 2 使用 Elemental 进行远程主机初始配置
本章介绍 SUSE Edge 中的“电告总部网络置备”解决方案。我们将使用 Elemental 来协助完成节点初始配置。Elemental 是一个软件堆栈,可用于注册远程主机和通过 Kubernetes 实现集中式云原生操作系统全面管理。在 SUSE Edge 堆栈中,我们将使用 Elemental 的注册功能将远程主机初始配置到 Rancher,以便将主机集成到集中式管理平台,然后从该平台部署和管理 Kubernetes 群集以及分层组件、应用程序及其生命周期,所有这些操作都在一个中心位置完成。
- 3 使用 Edge Image Builder 配置独立群集
Edge Image Builder (EIB) 工具可以简化为引导计算机生成自定义的、随时可引导 (CRB) 磁盘映像的过程,即使在完全隔离式方案中也能做到这一点。EIB 用于创建所有三个 SUSE Edge 部署空间中使用的部署映像,因为它足够灵活,可以提供最简单的自定义,例如通过提供全面配置的映像来添加用户或设置时区。例如,该映像可以设置复杂的网络配置、部署多节点 Kubernetes 群集、部署客户工作负载,并通过 Rancher/Elemental 和 SUSE Manager 注册到集中式管理平台。EIB 以容器映像的形式运行,因此具有极高的跨平台可移植性,可确保所有必需的依赖项都…
1 使用 Metal3 实现 BMC 自动化部署 #
Metal3 是一个 CNCF 项目,它为 Kubernetes 提供裸机基础架构管理功能。
Metal3 提供 Kubernetes 原生资源来管理裸机服务器的生命周期,支持通过 Redfish 等带外协议进行管理。
它还为群集 API (CAPI) 提供成熟的支持,允许通过广泛采用的不区分供应商的 API 来管理跨多个基础架构提供商的基础架构资源。
1.1 为何使用此方法 #
此方法非常适合用于目标硬件支持带外管理,并且需要全自动化基础架构管理流程的方案。
管理群集配置为提供声明性 API 来对下游群集裸机服务器进行清单和状态管理,包括自动检查、清理和置备/取消置备。
1.2 概要体系结构 #
1.3 先决条件 #
下游群集服务器硬件和网络相关的限制具体如下所述:
管理群集
必须与目标服务器管理/BMC API 建立网络连接
必须与目标服务器控制平面网络建立网络连接
对于多节点管理群集,需要配置额外的预留 IP 地址
要控制的主机
必须支持通过 Redfish、iDRAC 或 iLO 接口进行带外管理
必须支持通过虚拟媒体进行部署(目前不支持 PXE)
必须与管理群集建立网络连接,以便能够访问 Metal3 置备 API
需要一些工具,可以安装在管理群集上,也可以安装在能够访问管理群集的主机上。
Podman 或 Rancher Desktop 等容器运行时
必须从 SUSE Customer Center 或
SUSE 下载页面下载
SLE-Micro.x86_64-5.5.0-Default-GM.raw.xz
操作系统映像文件。
1.3.1 设置管理群集 #
安装管理群集和使用 Metal3 的基本步骤如下:
安装 RKE2 管理群集
安装 Rancher
安装存储提供程序
安装 Metal3 依赖项
安装 CAPI 依赖项
为下游群集主机构建 SLEMicro 操作系统映像
注册 BareMetalHost CR 以定义裸机清单
通过定义 CAPI 资源创建下游群集
本指南假设已安装现有的 RKE2 群集和 Rancher(包括 cert-manager),例如已使用 Edge Image Builder 安装(第 9 章 “Edge Image Builder”)。
也可以按照 ATIP 管理群集文档(第 29 章 “设置管理群集”)中所述,将此处所述的步骤完全自动化。
1.3.2 安装 Metal3 依赖项 #
必须安装并运行 cert-manager(如果在安装 Rancher 的过程中未安装)。
必须安装永久存储提供程序。建议使用 Longhorn,但对于开发/PoC 环境,也可以使用 local-path。以下说明假设已将 StorageClass 标记为默认,否则需要对 Metal3 chart 进行额外的配置。
需要提供一个额外的 IP,该 IP 由 MetalLB 管理,用于为 Metal3 管理服务提供一致的端点。此 IP 必须是控制平面子网的一部分,并且是为静态配置预留的(不是任何 DHCP 池的一部分)。
如果管理群集是单个节点,则可以避免通过 MetalLB 管理额外的浮动 IP,具体参见“单节点配置”(第 1.6.1 节 “单节点配置”)
首先,我们需要安装 MetalLB:
helm install \ metallb oci://registry.suse.com/edge/metallb-chart \ --namespace metallb-system \ --create-namespace
然后使用定义为
STATIC_IRONIC_IP
(如下所示)的预留 IP 来定义IPAddressPool
和L2Advertisment
:export STATIC_IRONIC_IP=<STATIC_IRONIC_IP> cat <<-EOF | kubectl apply -f - apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ironic-ip-pool namespace: metallb-system spec: addresses: - ${STATIC_IRONIC_IP}/32 serviceAllocation: priority: 100 serviceSelectors: - matchExpressions: - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]} EOF
cat <<-EOF | kubectl apply -f - apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: ironic-ip-pool-l2-adv namespace: metallb-system spec: ipAddressPools: - ironic-ip-pool EOF
现在可以安装 Metal3:
helm install \ metal3 oci://registry.suse.com/edge/metal3-chart \ --namespace metal3-system \ --create-namespace \ --set global.ironicIP="${STATIC_IRONIC_IP}"
大约要经过两分钟,initContainer 才会在此部署中运行,因此在继续之前,请确保所有 Pod 都已运行:
kubectl get pods -n metal3-system NAME READY STATUS RESTARTS AGE baremetal-operator-controller-manager-85756794b-fz98d 2/2 Running 0 15m metal3-metal3-ironic-677bc5c8cc-55shd 4/4 Running 0 15m metal3-metal3-mariadb-7c7d6fdbd8-64c7l 1/1 Running 0 15m
请在 metal3-system
名称空间中的所有 Pod 都已运行之后才继续执行以下步骤
1.3.3 安装群集 API 依赖项 #
首先,我们需要禁用 Rancher 嵌入的 CAPI 控制器:
cat <<-EOF | kubectl apply -f -
apiVersion: management.cattle.io/v3
kind: Feature
metadata:
name: embedded-cluster-api
spec:
value: false
EOF
kubectl delete mutatingwebhookconfiguration.admissionregistration.k8s.io mutating-webhook-configuration
kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration
kubectl wait --for=delete namespace/cattle-provisioning-capi-system --timeout=300s
然后,要使用 SUSE 映像,需要创建一个配置文件:
mkdir ~/.cluster-api
cat > ~/.cluster-api/clusterctl.yaml <<EOF
images:
all:
repository: registry.suse.com/edge
EOF
安装 clusterctl 1.6.x,之后我们将安装核心、基础架构、引导程序和控制平面提供程序,如下所示:
clusterctl init --core "cluster-api:v1.6.2" --infrastructure "metal3:v1.6.0" --bootstrap "rke2:v0.2.6" --control-plane "rke2:v0.2.6"
一段时间后,控制器 Pod 应会在
capi-system
、capm3-system
、rke2-bootstrap-system
和 rke2-control-plane-system
名称空间中运行。
1.3.4 准备下游群集映像 #
Edge Image Builder(第 9 章 “Edge Image Builder”)用于准备下游群集主机上置备的经过修改的 SLEMicro 基础映像。
可以通过 Edge Image Builder 完成大部分配置,但本指南仅介绍设置下游群集所需的最低限度配置。
1.3.4.1 映像配置 #
运行 Edge Image Builder 时,将从主机挂载一个目录,因此需要创建一个目录结构来存储用于定义目标映像的配置文件。
downstream-cluster-config.yaml
是映像定义文件,有关更多细节,请参见第 3 章 “使用 Edge Image Builder 配置独立群集”。下载的基础映像已经过
xz
压缩,必须使用unxz
将其解压缩,并将其复制/移动到base-images
文件夹中。network
文件夹是可选的,有关更多细节,请参见第 1.3.5.1.1 节 “用于静态网络配置的附加脚本”。custom/scripts 目录包含首次引导时运行的脚本;目前需要使用
growfs.sh
脚本来调整部署中的操作系统根分区的大小
├── downstream-cluster-config.yaml ├── base-images/ │ └ SLE-Micro.x86_64-5.5.0-Default-GM.raw ├── network/ | └ configure-network.sh └── custom/ └ scripts/ └ growfs.sh
1.3.4.1.1 下游群集映像定义文件 #
downstream-cluster-config.yaml
文件是下游群集映像的主配置文件。下面是通过
Metal3 进行部署的极简示例:
apiVersion: 1.0
image:
imageType: RAW
arch: x86_64
baseImage: SLE-Micro.x86_64-5.5.0-Default-GM.raw
outputImageName: SLE-Micro-eib-output.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 配置将会失败。
1.3.4.1.2 Growfs 脚本 #
目前是一个自定义脚本
(custom/scripts/growfs.sh
),在置备后首次引导时,必须使用此脚本来增大文件系统,使之与磁盘大小匹配。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
1.3.4.2 映像创建 #
按照前面的章节准备好目录结构后,运行以下命令来构建映像:
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
这会根据上述定义创建名为 SLE-Micro-eib-output.raw
的输出映像文件。
然后必须通过 Web 服务器提供输出映像,该服务器可以是通过 Metal3 chart 启用的媒体服务器容器(注意),也可以是其他某个本地可访问的服务器。在下面的示例中,此服务器是
imagecache.local:8080
1.3.5 添加 BareMetalHost 清单 #
注册自动部署的裸机服务器需要创建两个资源:一个用于存储 BMC 访问身份凭证的密钥,以及一个用于定义 BMC 连接和其他细节的 Metal3 BareMetalHost 资源:
apiVersion: v1
kind: Secret
metadata:
name: controlplane-0-credentials
type: Opaque
data:
username: YWRtaW4=
password: cGFzc3dvcmQ=
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
name: controlplane-0
labels:
cluster-role: control-plane
spec:
online: true
bootMACAddress: "00:f3:65:8a:a3:b0"
bmc:
address: redfish-virtualmedia://192.168.125.1:8000/redfish/v1/Systems/68bd0fb6-d124-4d17-a904-cdf33efe83ab
disableCertificateVerification: true
credentialsName: controlplane-0-credentials
请注意以下几点:
密钥用户名/口令必须采用 base64 编码。请注意,此值不能包含任何尾部换行符(例如,应使用
echo-n
,而不是简单地使用echo
!)可以现在设置
cluster-role
标签,也可以稍后在创建群集时设置。在以下示例中,应该设置control-plane
或worker
bootMACAddress
必须是与主机的控制平面 NIC 匹配的有效 MACbmc
地址是与 BMC 管理 API 的连接,支持以下设置:redfish-virtualmedia://<IP 地址>/redfish/v1/Systems/<系统 ID>
:Redfish 虚拟媒体,例如 SuperMicroidrac-virtualmedia://<IP 地址>/redfish/v1/Systems/System.Embedded.1
:Dell iDRAC
有关 BareMetalHost API 的更多细节,请参见上游 API 文档
1.3.5.1 配置静态 IP #
上面的 BareMetalHost 示例假设 DHCP 提供控制平面网络配置,但对于需要手动配置(例如静态 IP)的情况,可以提供附加配置,如下所述。
1.3.5.1.1 用于静态网络配置的附加脚本 #
使用 Edge Image Builder 创建基础映像时,请在 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
1.3.5.1.2 包含主机网络配置的附加密钥 #
可为每个主机定义一个附加密钥,其中包含采用 NM Configurator(第 10 章 “边缘网络”)所支持的 nmstate 格式的数据。
然后通过 preprovisioningNetworkDataName
规范字段在
BareMetalHost
资源中引用该密钥。
apiVersion: v1
kind: Secret
metadata:
name: controlplane-0-networkdata
type: Opaque
stringData:
networkData: |
interfaces:
- name: enp1s0
type: ethernet
state: up
mac-address: "00:f3:65:8a:a3:b0"
ipv4:
address:
- ip: 192.168.125.200
prefix-length: 24
enabled: true
dhcp: false
dns-resolver:
config:
server:
- 192.168.125.1
routes:
config:
- destination: 0.0.0.0/0
next-hop-address: 192.168.125.1
next-hop-interface: enp1s0
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
name: controlplane-0
labels:
cluster-role: control-plane
spec:
preprovisioningNetworkDataName: controlplane-0-networkdata
# Remaining content as in previous example
尽管 mac-address 在 nmstate API 中是可选的,但要通过 NM Configurator 进行配置,必须提供 mac-address。
1.3.5.2 BareMetalHost 准备 #
按照上述步骤创建 BareMetalHost 资源和关联的密钥后,将触发主机准备工作流程:
虚拟媒体附件将 ramdisk 映像引导至目标主机 BMC
ramdisk 检查硬件细节,并为主机做好置备准备(例如,清理磁盘中的旧数据)
完成此过程后,BareMetalHost
status.hardware
字段中的硬件细节将会更新并可供校验
此过程可能需要几分钟时间,但完成后,您应会看到 BareMetalHost 状态变为 available
:
% kubectl get baremetalhost
NAME STATE CONSUMER ONLINE ERROR AGE
controlplane-0 available true 9m44s
worker-0 available true 9m44s
1.3.6 创建下游群集 #
现在创建用于定义下游群集的群集 API 资源,并创建计算机资源,后者会导致置备 BareMetalHost 资源,然后引导这些资源以形成 RKE2 群集。
1.3.7 控制平面部署 #
为了部署控制平面,我们需要定义一个如下所示的 yaml 清单,其中包含以下资源:
群集资源定义群集名称、网络和控制平面/基础架构提供程序的类型(在本例中为 RKE2/Metal3)
Metal3Cluster 定义控制平面端点(单节点群集的主机 IP,多节点群集的负载平衡器端点,本示例假设使用单节点群集)
RKE2ControlPlane 定义 RKE2 版本,以及群集引导期间所需的任何其他配置
Metal3MachineTemplate 定义要应用于 BareMetalHost 资源的操作系统映像,hostSelector 定义要使用的 BareMetalHost
Metal3DataTemplate 定义要传递给 BareMetalHost 的附加 metaData(请注意,Edge 解决方案目前不支持 networkData)
请注意,为简单起见,本示例假设使用单节点控制平面,其中 BareMetalHost 配置了 IP
192.168.125.200
- 有关更高级的多节点示例,请参见 ATIP 文档(第 31 章 “全自动定向网络置备”)
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: sample-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: sample-cluster
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
name: sample-cluster
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
name: sample-cluster
namespace: default
spec:
controlPlaneEndpoint:
host: 192.168.125.200
port: 6443
noCloudProvider: true
---
apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
name: sample-cluster
namespace: default
spec:
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
name: sample-cluster-controlplane
replicas: 1
agentConfig:
format: ignition
kubelet:
extraArgs:
- provider-id=metal3://BAREMETALHOST_UUID
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
version: v1.28.9+rke2r1
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: sample-cluster-controlplane
namespace: default
spec:
template:
spec:
dataTemplate:
name: sample-cluster-controlplane-template
hostSelector:
matchLabels:
cluster-role: control-plane
image:
checksum: http://imagecache.local:8080/SLE-Micro-eib-output.raw.sha256
checksumType: sha256
format: raw
url: http://imagecache.local:8080/SLE-Micro-eib-output.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
name: sample-cluster-controlplane-template
namespace: default
spec:
clusterName: sample-cluster
metaData:
objectNames:
- key: name
object: machine
- key: local-hostname
object: machine
- key: local_hostname
object: machine
复制以上示例并根据您的环境进行修改后,可以通过 kubectl
应用该示例,然后使用
clusterctl
监控群集状态
% kubectl apply -f rke2-control-plane.yaml
# Wait for the cluster to be provisioned - status can be checked via clusterctl
% clusterctl describe cluster sample-cluster
NAME READY SEVERITY REASON SINCE MESSAGE
Cluster/sample-cluster True 22m
├─ClusterInfrastructure - Metal3Cluster/sample-cluster True 27m
├─ControlPlane - RKE2ControlPlane/sample-cluster True 22m
│ └─Machine/sample-cluster-chflc True 23m
1.3.8 工作/计算节点部署 #
与部署控制平面时一样,我们需要定义一个 yaml 清单,其中包含以下资源:
MachineDeployment 定义副本(主机)的数量和引导/基础架构提供程序(在本例中为 RKE2/Metal3)
RKE2ConfigTemplate 描述代理主机引导的 RKE2 版本和首次引导配置
Metal3MachineTemplate 定义要应用于 BareMetalHost 资源的操作系统映像,hostSelector 定义要使用的 BareMetalHost
Metal3DataTemplate 定义要传递给 BareMetalHost 的附加 metaData(请注意,Edge 解决方案目前不支持 networkData)
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
labels:
cluster.x-k8s.io/cluster-name: sample-cluster
name: sample-cluster
namespace: default
spec:
clusterName: sample-cluster
replicas: 1
selector:
matchLabels:
cluster.x-k8s.io/cluster-name: sample-cluster
template:
metadata:
labels:
cluster.x-k8s.io/cluster-name: sample-cluster
spec:
bootstrap:
configRef:
apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
kind: RKE2ConfigTemplate
name: sample-cluster-workers
clusterName: sample-cluster
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
name: sample-cluster-workers
nodeDrainTimeout: 0s
version: v1.28.9+rke2r1
---
apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
kind: RKE2ConfigTemplate
metadata:
name: sample-cluster-workers
namespace: default
spec:
template:
spec:
agentConfig:
format: ignition
version: v1.28.9+rke2r1
kubelet:
extraArgs:
- provider-id=metal3://BAREMETALHOST_UUID
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
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: sample-cluster-workers
namespace: default
spec:
template:
spec:
dataTemplate:
name: sample-cluster-workers-template
hostSelector:
matchLabels:
cluster-role: worker
image:
checksum: http://imagecache.local:8080/SLE-Micro-eib-output.raw.sha256
checksumType: sha256
format: raw
url: http://imagecache.local:8080/SLE-Micro-eib-output.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
name: sample-cluster-workers-template
namespace: default
spec:
clusterName: sample-cluster
metaData:
objectNames:
- key: name
object: machine
- key: local-hostname
object: machine
- key: local_hostname
object: machine
复制以上示例并根据您的环境进行修改后,可以通过 kubectl
应用该示例,然后使用
clusterctl
监控群集状态
% kubectl apply -f rke2-agent.yaml
# Wait some time for the compute/agent hosts to be provisioned
% clusterctl describe cluster sample-cluster
NAME READY SEVERITY REASON SINCE MESSAGE
Cluster/sample-cluster True 25m
├─ClusterInfrastructure - Metal3Cluster/sample-cluster True 30m
├─ControlPlane - RKE2ControlPlane/sample-cluster True 25m
│ └─Machine/sample-cluster-chflc True 27m
└─Workers
└─MachineDeployment/sample-cluster True 22m
└─Machine/sample-cluster-56df5b4499-zfljj True 23m
1.3.9 群集取消置备 #
可以通过删除上述创建步骤中应用的资源来取消置备下游群集:
% kubectl delete -f rke2-agent.yaml
% kubectl delete -f rke2-control-plane.yaml
这会触发 BareMetalHost 资源的取消置备,此过程可能需要几分钟,之后,这些资源将再次处于可用状态:
% kubectl get bmh
NAME STATE CONSUMER ONLINE ERROR AGE
controlplane-0 deprovisioning sample-cluster-controlplane-vlrt6 false 10m
worker-0 deprovisioning sample-cluster-workers-785x5 false 10m
...
% kubectl get bmh
NAME STATE CONSUMER ONLINE ERROR AGE
controlplane-0 available false 15m
worker-0 available false 15m
1.4 已知问题 #
上游 IP 地址管理控制器目前不受支持,因为它与我们在 SLEMicro 中选择的网络配置工具和首次引导工具链尚不兼容。
相关的 IPAM 资源和 Metal3DataTemplate networkData 字段目前也不受支持。
目前仅支持通过 redfish-virtualmedia 进行部署。
部署的群集目前不会导入 Rancher
由于禁用了 Rancher 嵌入式 CAPI 控制器,如上所述为 Metal3 配置的管理群集也无法用于其他群集置备方法,例如 Elemental(第 11 章 “Elemental”)
1.5 计划的更改 #
我们已计划好将来通过 Rancher Turtles 将部署的群集导入 Rancher
采用与 Rancher Turtles 一致的做法还有望消除禁用 Rancher 嵌入式 CAPI 的要求,因此其他群集方法应该可以通过管理群集来实现。
通过 networkData 字段启用 IPAM 资源和配置支持
1.6 其他资源 #
ATIP 文档(第 26 章 “SUSE 自适应电信基础架构平台 (ATIP)”)提供了 Metal3 在电信用例中的更高级用法示例。
1.6.1 单节点配置 #
对于管理群集是单个节点的测试/PoC 环境,可能不需要通过 MetalLB 管理额外的浮动 IP。
在此模式下,管理群集 API 的端点是管理群集的 IP,因此在使用 DHCP 时应预留该 IP,或者配置静态 IP,以确保管理群集 IP 不会变化 -
在下面显示为 MANAGEMENT_CLUSTER_IP
。
为了实现此方案,必须如下所示指定 metal3 chart 值:
global:
ironicIP: <MANAGEMENT_CLUSTER_IP>
metal3-ironic:
service:
type: NodePort
1.6.2 对虚拟媒体 ISO 附件禁用 TLS #
某些服务器供应商在将虚拟媒体 ISO 映像挂接到 BMC 时会校验 SSL 连接,这可能会导致问题,因为为 Metal3 部署生成的证书是自我签名证书。要解决此问题,可以使用如下所示的 metal3 chart 值仅对虚拟媒体磁盘附件禁用 TLS:
global:
enable_vmedia_tls: false
另一种解决方法是使用 CA 证书配置 BMC - 在这种情况下,可以使用 kubectl
从群集读取证书:
kubectl get secret -n metal3-system ironic-vmedia-cert -o yaml
然后可以在服务器 BMC 控制台上配置证书,不过,配置过程根据特定的供应商而异(并且不一定适用于所有供应商,如果不适用,可能需要指定
enable_vmedia_tls
标志)。
2 使用 Elemental 进行远程主机初始配置 #
本章介绍 SUSE Edge 中的“电告总部网络置备”解决方案。我们将使用 Elemental 来协助完成节点初始配置。Elemental 是一个软件堆栈,可用于注册远程主机和通过 Kubernetes 实现集中式云原生操作系统全面管理。在 SUSE Edge 堆栈中,我们将使用 Elemental 的注册功能将远程主机初始配置到 Rancher,以便将主机集成到集中式管理平台,然后从该平台部署和管理 Kubernetes 群集以及分层组件、应用程序及其生命周期,所有这些操作都在一个中心位置完成。
此方法在以下情况下可能很有用:您要控制的设备与上游群集不在同一网络中,或没有带外管理控制器初始配置功能可以进行更直接的控制;您要在边缘处引导许多不同的“未知”系统,并且需要安全地大规模初始配置和管理这些系统。这种情况在以下领域的用例中很常见:零售、工业物联网,或几乎无法通过设备要安装到的网络进行控制的其他领域。
2.1 概要体系结构 #
2.2 所需资源 #
下面说明了学习本快速入门所要满足的最低系统和环境要求:
集中式管理群集的主机(托管 Rancher 和 Elemental 的主机):
至少 8 GB RAM 和 20 GB 磁盘空间,用于开发或测试(对于生产用途,请参见此处)
要置备的目标节点,即边缘设备(可以使用虚拟机进行演示或测试)
至少 4GB RAM、2 个 CPU 核心和 20 GB 磁盘空间
管理群集的可解析主机名,或用于 sslip.io 等服务的静态 IP 地址
用于通过 Edge Image Builder 构建安装媒体的主机
用于引导的 USB 闪存盘(如果使用物理硬件)
在初始配置过程中会重写目标计算机上的现有数据,因此请务必备份挂接到目标部署节点的所有 USB 存储设备和磁盘上的所有数据。
本指南是使用托管上游群集的 Digital Ocean droplet 以及用作下游设备的 Intel NUC 制作的。为了构建安装媒体,我们使用了 SUSE Linux Enterprise Server。
2.3 如何使用 Elemental #
安装和使用 Elemental 的基本步骤如下:
2.3.1 构建引导群集 #
首先创建一个能够托管 Rancher 和 Elemental 的群集。必须可以从下游节点所连接到的网络路由此群集。
2.3.1.1 创建 Kubernetes 群集 #
如果您使用的是超大规模云(例如 Azure、AWS 或 Google Cloud),那么,设置群集的最简单方法是使用这些云的内置工具。为简洁起见,本指南不会详细介绍每种选项的用法过程。
如果您要安装到裸机或其他宿主服务,同时需要提供 Kubernetes 发行版本身,我们建议您使用 RKE2。
2.3.1.2 设置 DNS #
在继续之前,需要设置群集访问权限。与群集本身的设置一样,DNS 的配置方式根据群集的托管位置而异。
如果您不想处理 DNS 记录的设置(例如,这只是一个临时使用的测试服务器),可以改用 sslip.io 之类的服务。通过此服务,可以使用
<address>.sslip.io
解析任何 IP 地址。
2.3.2 安装 Rancher #
要安装 Rancher,需要访问刚刚创建的群集的 Kubernetes API。具体方法取决于使用的 Kubernetes 发行版。
对于 RKE2,kubeconfig 文件会写入
/etc/rancher/rke2/rke2.yaml
。将此文件作为
~/.kube/config
保存在本地系统上。可能需要编辑该文件,以包含正确的外部可路由 IP 地址或主机名。
使用 Rancher 文档中所述的命令轻松安装 Rancher:
安装 cert-manager:
- Linux
- Windows
helm repo add rancher-prime https://charts.rancher.com/server-charts/prime kubectl create namespace cattle-system kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.crds.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace
然后安装 Rancher 本身:
- Linux
- Windows
helm install rancher rancher-prime/rancher \ --namespace cattle-system \ --set hostname=<DNS or sslip from above> \ --set replicas=1 \ --set bootstrapPassword=<PASSWORD_FOR_RANCHER_ADMIN>
如果目标系统是生产系统,请使用 cert-manager 配置实际证书(例如 Let's Encrypt 提供的证书)。
浏览到您设置的主机名,然后使用您的 bootstrapPassword
登录到
Rancher。系统将指导您完成一个简短的设置过程。
2.3.3 安装 Elemental #
安装 Rancher 后,接下来可以安装 Elemental Operator 和所需的 CRD。Elemental 的 Helm chart 作为 OCI 项目发布,因此其安装过程比其他 chart 略简单一些。可以通过您用来安装 Rancher 的同一外壳安装 Helm chart,也可以在浏览器中通过 Rancher 的外壳安装。
helm install --create-namespace -n cattle-elemental-system \
elemental-operator-crds \
oci://registry.suse.com/rancher/elemental-operator-crds-chart \
--version 1.4.4
helm install --create-namespace -n cattle-elemental-system \
elemental-operator \
oci://registry.suse.com/rancher/elemental-operator-chart \
--version 1.4.4
2.3.3.1 (可选)安装 Elemental UI 扩展 #
2.3.3.2 配置 Elemental #
为方便起见,我们建议将变量 $ELEM
设置为配置目录所在的完整路径:
export ELEM=$HOME/elemental mkdir -p $ELEM
为了能够将计算机注册到 Elemental,我们需要在 fleet-default
名称空间中创建
MachineRegistration
对象。
我们来创建该对象的基本版本:
cat << EOF > $ELEM/registration.yaml apiVersion: elemental.cattle.io/v1beta1 kind: MachineRegistration metadata: name: ele-quickstart-nodes namespace: fleet-default spec: machineName: "\${System Information/Manufacturer}-\${System Information/UUID}" machineInventoryLabels: manufacturer: "\${System Information/Manufacturer}" productName: "\${System Information/Product Name}" EOF kubectl apply -f $ELEM/registration.yaml
cat
命令使用反斜杠 (\
) 将每个
$
符号转义,以免 Bash 将其模板化。如果手动复制命令,请去除反斜杠。
创建该对象后,找到并记下分配的端点:
REGISURL=$(kubectl get machineregistration ele-quickstart-nodes -n fleet-default -o jsonpath='{.status.registrationURL}')
或者,可以在 UI 中执行此操作。
- UI 扩展
- UI 扩展
如果您刚刚创建了配置,则应会看到列出的注册 URL,可以单击“Copy”(复制)来复制该网址:
提示如果您退出了该屏幕,可以单击左侧菜单中的“Registration Endpoints”(注册端点),然后单击刚刚创建的端点的名称。
此 URL 将在下一步骤中使用。
2.3.4 构建安装媒体 #
虽然当前版本的 Elemental 提供了构建其自身安装媒体的方法,但在 SUSE Edge 3.0 中,我们会改用 Edge Image Builder 来构建安装媒体,因此最终构建的系统使用 SLE Micro 作为基础操作系统。
有关 Edge Image Builder 的更多细节,请查看相关入门指南(第 3 章 “使用 Edge Image Builder 配置独立群集”)和组件文档(第 9 章 “Edge Image Builder”)。
在装有 Podman 的 Linux 系统上,运行:
mkdir -p $ELEM/eib_quickstart/base-images
mkdir -p $ELEM/eib_quickstart/elemental
curl $REGISURL -o $ELEM/eib_quickstart/elemental/elemental_config.yaml
cat << EOF > $ELEM/eib_quickstart/eib-config.yaml
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM.install.iso
outputImageName: elemental-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: \$6\$jHugJNNd3HElGsUZ\$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
EOF
未编码的口令是
eib
。cat
命令使用反斜杠 (\
) 将每个$
符号转义,以免 Bash 将其模板化。如果手动复制命令,请去除反斜杠。
podman run --privileged --rm -it -v $ELEM/eib_quickstart/:/eib \
registry.suse.com/edge/edge-image-builder:1.0.2 \
build --definition-file eib-config.yaml
如果要引导物理设备,我们需要将映像刻录到 USB 闪存盘中。为此请使用以下命令:
sudo dd if=/eib_quickstart/elemental-image.iso of=/dev/<PATH_TO_DISK_DEVICE> status=progress
2.3.5 引导下游节点 #
现在我们已创建安装媒体,接下来可以用它来引导下游节点。
对于您要使用 Elemental 控制的每个系统,请添加安装媒体并引导设备。安装后,系统会重引导并自行注册。
如果您正在使用 UI 扩展,则应会看到您的节点出现在“Inventory of Machines”(计算机清单)中。
在出现登录提示之前,请勿移除安装媒体;在首次引导期间,仍需访问 USB 记忆棒上的文件。
2.3.6 创建下游群集 #
使用 Elemental 置备新群集时,需要创建两个对象。
- Linux
- UI 扩展
第一个对象是
MachineInventorySelectorTemplate
。此对象用于指定群集与清单中计算机之间的映射。
创建一个选择器,用于根据标签匹配清单中的任何计算机:
cat << EOF > $ELEM/selector.yaml apiVersion: elemental.cattle.io/v1beta1 kind: MachineInventorySelectorTemplate metadata: name: location-123-selector namespace: fleet-default spec: template: spec: selector: matchLabels: locationID: '123' EOF
将资源应用于群集:
kubectl apply -f $ELEM/selector.yaml
获取计算机名称并添加匹配标签:
MACHINENAME=$(kubectl get MachineInventory -n fleet-default | awk 'NR>1 {print $1}') kubectl label MachineInventory -n fleet-default \ $MACHINENAME locationID=123
创建简单的单节点 K3s 群集资源,并将其应用于群集:
cat << EOF > $ELEM/cluster.yaml apiVersion: provisioning.cattle.io/v1 kind: Cluster metadata: name: location-123 namespace: fleet-default spec: kubernetesVersion: v1.28.9+k3s1 rkeConfig: machinePools: - name: pool1 quantity: 1 etcdRole: true controlPlaneRole: true workerRole: true machineConfigRef: kind: MachineInventorySelectorTemplate name: location-123-selector apiVersion: elemental.cattle.io/v1beta1 EOF kubectl apply -f $ELEM/cluster.yaml
创建这些对象后,您应会看到一个新的 Kubernetes 群集使用刚刚安装的新节点运行。
为了能够更轻松地将系统分组,可以添加一个启动脚本,用于在环境中查找已知在该位置独有的内容。
例如,如果您知道每个位置都有一个唯一的子网,则可以编写一个脚本来查找网络前缀,并为相应的 MachineInventory 添加标签。
通常需要根据您的系统设计自定义此脚本,如下所示:
INET=`ip addr show dev eth0 | grep "inet\ "`
elemental-register --label "network=$INET" \
--label "network=$INET" /oem/registration
2.4 节点重置 #
SUSE Rancher Elemental 支持执行“节点重置”,从 Rancher 中删除整个群集、从群集中删除单个节点或者从计算机清单中手动删除某个节点时,可以选择性地触发该操作。当您想要重置和清理任何孤立资源,并希望自动将清理的节点放回计算机清单以便重复使用时,此功能非常有用。默认未启用此功能,因此不会清理任何已去除的系统(即,不会去除数据,任何 Kubernetes 群集资源将继续在下游群集上运行),并且需要手动干预才能擦除数据,并通过 Elemental 将计算机重新注册到 Rancher。
如果您希望默认启用此功能,则需要通过添加 config.elemental.reset.enabled:
true
,来确保 MachineRegistration
明确启用此功能,例如:
config:
elemental:
registration:
auth: tpm
reset:
enabled: true
然后,所有使用此 MachineRegistration
注册的系统将自动在其配置中收到
elemental.cattle.io/resettable: 'true'
批注。如果您希望在各个节点上手动执行此操作(例如,您的现有 MachineInventory
没有此批注,或者您已部署节点),您可以修改 MachineInventory
并添加
resettable
配置,例如:
apiVersion: elemental.cattle.io/v1beta1
kind: MachineInventory
metadata:
annotations:
elemental.cattle.io/os.unmanaged: 'true'
elemental.cattle.io/resettable: 'true'
在 SUSE Edge 3.0 中,Elemental Operator 会在操作系统上放置一个标记,该标记将自动触发清理过程;它会停止所有
Kubernetes 服务、去除所有永久数据、卸装所有 Kubernetes 服务、清理所有剩余 Kubernetes/Rancher 目录,并通过原始
Elemental MachineRegistration
配置强制重新注册到
Rancher。此过程会自动发生,无需任何手动干预。调用的脚本可以在
/opt/edge/elemental_node_cleanup.sh
中找到,将在放置标记后通过
systemd.path
触发,因此会立即执行。
使用 resettable
功能的假设条件是,从 Rancher
去除节点/群集时的所需行为是擦除数据并强制重新注册。在这种情况下,必然会丢失数据,因此,请仅在您确定要执行自动重置时才使用此功能。
2.5 后续步骤 #
下面是使用本指南后建议阅读的一些资源:
第 6 章 “Fleet” 中的端到端自动化
第 10 章 “边缘网络”中的其他网络配置选项
3 使用 Edge Image Builder 配置独立群集 #
Edge Image Builder (EIB) 工具可以简化为引导计算机生成自定义的、随时可引导 (CRB) 磁盘映像的过程,即使在完全隔离式方案中也能做到这一点。EIB 用于创建所有三个 SUSE Edge 部署空间中使用的部署映像,因为它足够灵活,可以提供最简单的自定义,例如通过提供全面配置的映像来添加用户或设置时区。例如,该映像可以设置复杂的网络配置、部署多节点 Kubernetes 群集、部署客户工作负载,并通过 Rancher/Elemental 和 SUSE Manager 注册到集中式管理平台。EIB 以容器映像的形式运行,因此具有极高的跨平台可移植性,可确保所有必需的依赖项都是独立的,对系统中安装的用于操作该工具的软件包的影响极小。
有关详细信息,请阅读 Edge Image Builder 简介(第 9 章 “Edge Image Builder”)。
3.1 先决条件 #
一台运行 SLES 15 SP5、openSUSE Leap 15.5 或 openSUSE Tumbleweed 的 x86_64 物理主机(或虚拟机)。
一个可用的容器运行时(例如 Podman)
最新 SLE Micro 5.5 SelfInstall“GM2”ISO 映像的下载副本,可在此处找到。
只要有兼容的容器运行时,其他操作系统就可以正常运行,但尚未在其他平台上进行广泛的测试。文档重点介绍 Podman,但 Docker 应该也能实现相同的功能。
3.1.1 获取 EIB 映像 #
EIB 容器映像已公开提供,可以通过在映像构建主机上运行以下命令从 SUSE Edge 注册表下载:
podman pull registry.suse.com/edge/edge-image-builder:1.0.2
3.2 创建映像配置目录 #
由于 EIB 在容器中运行,我们需要从主机挂载一个配置目录,以便能够指定所需的配置,并使 EIB 能够在构建过程中访问任何所需的输入文件和支持项目。此目录必须遵循特定的结构。我们在主目录中创建此目录,并将其命名为“eib”:
export CONFIG_DIR=$HOME/eib mkdir -p $CONFIG_DIR/base-images
在上一步骤中,我们创建了“base-images”目录,用于托管 SLE Micro 5.5 输入映像,现在我们确保将下载的映像复制到配置目录:
cp /path/to/downloads/SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso $CONFIG_DIR/base-images/slemicro.iso
在 EIB 运行过程中,不会修改原始基础映像;在 EIB 配置目录的根目录中,会使用所需的配置创建新的自定义版本。
此时,配置目录应如下所示:
└── base-images/ └── slemicro.iso
3.3 创建映像定义文件 #
定义文件描述 Edge Image Builder 支持的大多数可配置选项,可以在此处找到选项的完整示例,我们建议您查看上游构建映像指南,以获取比本文中更详细的示例。首先,我们需要为操作系统映像创建一个非常简单的定义文件:
cat << EOF > $CONFIG_DIR/iso-definition.yaml apiVersion: 1.0 image: imageType: iso arch: x86_64 baseImage: slemicro.iso outputImageName: eib-image.iso EOF
此定义指定我们要为基于 x86_64
的系统生成输出映像。用作基础的、要进一步修改的映像是名为
slemicro.iso
的 iso
映像,其预期位置为
$CONFIG_DIR/base-images/slemicro.iso
。此定义还概述了在 EIB
修改完映像后,输出映像将命名为 eib-image.iso
,默认情况下,该输出映像驻留在
$CONFIG_DIR
中。
现在,我们的目录结构应如下所示:
├── iso-definition.yaml └── base-images/ └── slemicro.iso
下面的章节将演练几个常见操作的示例:
3.3.1 配置操作系统用户 #
EIB 允许您为用户预先配置登录信息(例如口令或 SSH 密钥),包括设置固定的 root 口令。作为此示例的一部分,我们将修复 root
口令,而第一步是使用 OpenSSL
创建一次性的已加密口令:
openssl passwd -6 SecurePassword
此命令将输出如下所示的内容:
$6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
然后,我们可以在定义文件中添加一个名为 operatingSystem
的部分,其中包含
users
数组。生成的文件应如下所示:
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
还可以添加其他用户、创建主目录、设置用户 ID、添加 ssh 密钥身份验证,以及修改组信息。请参见上游构建映像指南获取更多示例。
3.3.2 配置 RPM 软件包 #
EIB 的主要功能之一是提供一个机制来向映像添加更多软件包,以便在安装完成时,系统能够立即利用已安装的软件包。EIB 允许用户指定以下信息:
映像定义中按名称列出的软件包
要在其中搜索这些软件包的网络储存库
SUSE Customer Center (SCC) 身份凭证,用于在官方 SUSE 储存库中搜索列出的软件包
通过
$CONFIG_DIR/rpms
目录侧载网络储存库中不存在的自定义 RPM通过同一目录 (
$CONFIG_DIR/rpms/gpg-keys
) 指定 GPG 密钥,以便可以验证第三方软件包
然后,EIB 将在映像构建时运行软件包解析过程,将基础映像用作输入,并尝试提取和安装所有提供的软件包(通过列表指定或在本地提供)。EIB 将所有软件包(包括所有依赖项)下载到输出映像中存在的储存库,并指示系统在首次引导过程中安装这些软件包。在映像构建期间执行此过程可确保在首次引导期间成功将软件包安装在所需平台(例如边缘节点)上。在您要将其他软件包植入映像,而不是在操作时通过网络提取软件包的环境(例如隔离环境或网络受限的环境)中,此行为也很有利。
我们通过一个简单的示例来演示这一点:我们将安装由第三方供应商支持的 NVIDIA 储存库中的
nvidia-container-toolkit
RPM 软件包:
packages:
packageList:
- nvidia-container-toolkit
additionalRepos:
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
生成的定义文件如下所示:
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
packages:
packageList:
- nvidia-container-toolkit
additionalRepos:
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
上面是一个简单的示例,但为了完整性,请在运行映像生成之前下载 NVIDIA 软件包签名密钥:
$ mkdir -p $CONFIG_DIR/rpms/gpg-keys
$ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey > rpms/gpg-keys/nvidia.gpg
通过此方法添加其他 RPM 的目的是添加受支持的第三方组件或用户提供(和维护)的软件包;请不要使用此机制来添加通常不受 SLE Micro 支持的软件包。如果使用此机制从 openSUSE 储存库(不受支持)添加组件,包括从较新的版本或服务包添加组件,那么,尽管最终系统看似能够按预期运行,但您最终得到的可能是一种不受支持的配置,尤其是当依赖项解析导致操作系统的核心部分被替换时。如果您不确定,请联系您的 SUSE 代表,以帮助确定所需配置的支持性。
在上游安装软件包指南中可以找到更详细的指南和更多示例。
3.3.3 配置 Kubernetes 群集和用户工作负载 #
EIB 的另一个特点是,可以使用它来自动部署可“就地引导”(即,无需任何形式的集中式管理基础架构即可协调)的单节点和多节点高可用性 Kubernetes 群集。这种方法背后的主要推动因素是隔离式部署或网络受限的环境,但它也可以作为一种快速引导独立群集的方式,即使网络访问完全正常而不受限。
使用此方法不仅可以部署自定义的操作系统,还可以指定 Kubernetes 配置、通过 Helm chart 指定任何其他分层组件,以及通过提供的 Kubernetes 清单指定任何用户工作负载。但是,此方法幕后的设计原则是,我们默认假设用户想要隔离式部署,因此映像定义中指定的任何项目都将提取到映像中。这些项目包括用户提供的工作负载,在其中,EIB 将确保提供的定义所需的任何已发现映像都会在本地复制,并由最终部署的系统中的嵌入式映像注册表提供服务。
在下一个示例中,我们将采用现有的映像定义并指定 Kubernetes 配置(在本示例中,未列出系统及其角色,因此我们默认假设使用单节点群集),这会指示 EIB 置备单节点 RKE2 Kubernetes 群集。为了展示用户提供的工作负载(通过清单)和分层组件(通过 Helm)部署的自动化,我们将通过 SUSE Edge Helm chart 安装 KubeVirt,并通过 Kubernetes 清单安装 NGINX。需要追加到现有映像定义的附加配置如下:
kubernetes:
version: v1.28.9+rke2r1
manifests:
urls:
- https://k8s.io/examples/application/nginx-app.yaml
helm:
charts:
- name: kubevirt-chart
version: 0.2.4
repositoryName: suse-edge
repositories:
- name: suse-edge
url: oci://registry.suse.com/edge
生成的完整定义文件现在应如下所示:
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
packages:
packageList:
- nvidia-container-toolkit
additionalRepos:
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
kubernetes:
version: v1.28.9+rke2r1
manifests:
urls:
- https://k8s.io/examples/application/nginx-app.yaml
helm:
charts:
- name: kubevirt-chart
version: 0.2.4
repositoryName: suse-edge
repositories:
- name: suse-edge
url: oci://registry.suse.com/edge
在上游文档中可以找到多节点部署、自定义网络等选项和 Helm chart 选项/值的更多示例。
3.3.4 配置网络 #
在本快速入门的最后一个示例中,我们来配置在使用 EIB 生成的映像置备系统时启动的网络。请务必知道,除非提供网络配置,否则默认模型是在引导时发现的所有接口上使用的 DHCP。但是,这种配置并非都很理想,特别是当 DHCP 不可用,并且您需要提供静态配置时、需要设置更复杂的网络结构(例如绑定、LACP 和 VLAN)或者需要覆盖某些参数(例如主机名、DNS 服务器和路由)时。
EIB 能够提供每个节点的配置(其中的相关系统由其 MAC 地址唯一标识),或者为每台计算机提供相同配置的覆盖值,这在系统 MAC
地址未知时更有用。EIB 使用一个称为 Network Manager Configurator(简称为
nmc
)的附加工具,这是 SUSE Edge 团队构建的工具,用于基于 nmstate.io
声明式网络纲要应用自定义网络配置,在引导时识别其正在引导的节点,并在任何服务启动之前应用所需的网络配置。
我们现在通过在所需 network
目录中特定于节点的文件中(基于所需主机名)描述所需网络状态,为使用单一接口的系统应用静态网络配置:
mkdir $CONFIG_DIR/network cat << EOF > $CONFIG_DIR/network/host1.local.yaml routes: config: - destination: 0.0.0.0/0 metric: 100 next-hop-address: 192.168.122.1 next-hop-interface: eth0 table-id: 254 - destination: 192.168.122.0/24 metric: 100 next-hop-address: next-hop-interface: eth0 table-id: 254 dns-resolver: config: server: - 192.168.122.1 - 8.8.8.8 interfaces: - name: eth0 type: ethernet state: up mac-address: 34:8A:B1:4B:16:E7 ipv4: address: - ip: 192.168.122.50 prefix-length: 24 dhcp: false enabled: true ipv6: enabled: false EOF
上述示例是针对默认 192.168.122.0/24
子网设置的,假设测试在虚拟机上执行,请根据您的环境进行调整,不要忘记设置 MAC 地址。由于可以使用同一映像来置备多个节点,EIB(通过
nmc
)配置的网络取决于它是否能够根据其 MAC 地址唯一标识节点,因此在引导期间
nmc
将向每台计算机应用正确的网络配置。这意味着,您需要知道所要安装到的系统的 MAC
地址。或者,默认行为是依赖 DHCP,但您可以利用 configure-network.sh
挂钩将通用配置应用于所有节点 - 有关更多细节,请参见网络指南(第 10 章 “边缘网络”)。
生成的文件结构应如下所示:
├── iso-definition.yaml ├── base-images/ │ └── slemicro.iso └── network/ └── host1.local.yaml
我们刚刚创建的网络配置将被分析,必要的 NetworkManager 连接文件将自动生成并插入到 EIB 要创建的新安装映像中。这些文件将在主机置备期间应用,从而生成完整的网络配置。
有关上述配置的更详细解释以及此功能的示例,请参见“边缘网络”组件(第 10 章 “边缘网络”)。
3.4 构建映像 #
获得基础映像和可供 EIB 使用的映像定义后,接下来我们需要构建映像。为此,只需使用 podman
结合“build”命令调用 EIB 容器,并指定定义文件:
podman run --rm -it --privileged -v $CONFIG_DIR:/eib \
registry.suse.com/edge/edge-image-builder:1.0.2 \
build --definition-file iso-definition.yaml
该命令应输出如下所示的内容:
Setting up Podman API listener... Generating image customization components... Identifier ................... [SUCCESS] Custom Files ................. [SKIPPED] Time ......................... [SKIPPED] Network ...................... [SUCCESS] Groups ....................... [SKIPPED] Users ........................ [SUCCESS] Proxy ........................ [SKIPPED] Resolving package dependencies... Rpm .......................... [SUCCESS] Systemd ...................... [SKIPPED] Elemental .................... [SKIPPED] Suma ......................... [SKIPPED] Downloading file: dl-manifest-1.yaml 100% (498/498 B, 5.9 MB/s) Populating Embedded Artifact Registry... 100% (3/3, 11 it/min) Embedded Artifact Registry ... [SUCCESS] Keymap ....................... [SUCCESS] Configuring Kubernetes component... The Kubernetes CNI is not explicitly set, defaulting to 'cilium'. Downloading file: rke2_installer.sh Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (782/782 MB, 98 MB/s) Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (367/367 MB, 100 MB/s) Downloading file: rke2.linux-amd64.tar.gz 100% (34/34 MB, 101 MB/s) Downloading file: sha256sum-amd64.txt 100% (3.9/3.9 kB, 1.5 MB/s) Downloading file: dl-manifest-1.yaml 100% (498/498 B, 7.2 MB/s) Kubernetes ................... [SUCCESS] Certificates ................. [SKIPPED] Building ISO image... Kernel Params ................ [SKIPPED] Image build complete!
构建的 ISO 映像存储在 $CONFIG_DIR/eib-image.iso
中:
├── iso-definition.yaml ├── eib-image.iso ├── _build │ └── cache/ │ └── ... │ └── build-<timestamp>/ │ └── ... ├── base-images/ │ └── slemicro.iso └── network/ └── host1.local.yaml
每次构建都会在 $CONFIG_DIR/_build/
中创建一个带时间戳的文件夹,其中包含构建日志、构建期间使用的项目以及 combustion
和
artefacts
目录,这两个目录包含添加到 CRB 映像的所有脚本和项目。
此目录的内容如下所示:
├── build-<timestamp>/ │ │── combustion/ │ │ ├── 05-configure-network.sh │ │ ├── 10-rpm-install.sh │ │ ├── 12-keymap-setup.sh │ │ ├── 13b-add-users.sh │ │ ├── 20-k8s-install.sh │ │ ├── 26-embedded-registry.sh │ │ ├── 48-message.sh │ │ ├── network/ │ │ │ ├── host1.local/ │ │ │ │ └── eth0.nmconnection │ │ │ └── host_config.yaml │ │ ├── nmc │ │ └── script │ │── artefacts/ │ │ │── registry/ │ │ │ ├── hauler │ │ │ ├── nginx:1.14.2-registry.tar.zst │ │ │ ├── rancher_kubectl:v1.28.7-registry.tar.zst │ │ │ └── registry.suse.com_suse_sles_15.5_virt-operator:1.1.1-150500.8.12.1-registry.tar.zst │ │ │── rpms/ │ │ │ └── rpm-repo │ │ │ ├── addrepo0 │ │ │ │ └── x86_64 │ │ │ │ ├── nvidia-container-toolkit-1.15.0-1.x86_64.rpm │ │ │ │ ├── ... │ │ │ ├── repodata │ │ │ │ ├── ... │ │ │ └── zypper-success │ │ └── kubernetes/ │ │ ├── rke2_installer.sh │ │ ├── registries.yaml │ │ ├── server.yaml │ │ ├── images/ │ │ │ ├── rke2-images-cilium.linux-amd64.tar.zst │ │ │ └── rke2-images-core.linux-amd64.tar.zst │ │ ├── install/ │ │ │ ├── rke2.linux-amd64.tar.gz │ │ │ └── sha256sum-amd64.txt │ │ └── manifests/ │ │ ├── dl-manifest-1.yaml │ │ └── kubevirt-chart.yaml │ ├── createrepo.log │ ├── eib-build.log │ ├── embedded-registry.log │ ├── helm │ │ └── kubevirt-chart │ │ └── kubevirt-0.2.4.tgz │ ├── helm-pull.log │ ├── helm-template.log │ ├── iso-build.log │ ├── iso-build.sh │ ├── iso-extract │ │ └── ... │ ├── iso-extract.log │ ├── iso-extract.sh │ ├── modify-raw-image.sh │ ├── network-config.log │ ├── podman-image-build.log │ ├── podman-system-service.log │ ├── prepare-resolver-base-tarball-image.log │ ├── prepare-resolver-base-tarball-image.sh │ ├── raw-build.log │ ├── raw-extract │ │ └── ... │ └── resolver-image-build │ └──... └── cache └── ...
如果构建失败,首先会在 eib-build.log
中记录相关信息。该日志会指出哪个组件构建失败,方便您进行调试。
此时,您应该有了一个随时可用的映像,它可以:
部署 SLE Micro 5.5
配置 root 口令
安装
nvidia-container-toolkit
软件包配置嵌入式容器注册表以在本地处理内容
安装单节点 RKE2
配置静态网络
安装 KubeVirt
部署用户提供的清单
3.5 调试映像构建过程 #
如果映像构建过程失败,请参见上游调试指南。
3.6 测试新构建的映像 #
有关如何测试新构建的 CRB 映像的说明,请参见上游映像测试指南。
第 II 部分 使用的组件 #
Edge 的组件列表
- 4 Rancher
请参见 https://ranchermanager.docs.rancher.com 上的 Rancher 上游文档。
- 5 Rancher 仪表板扩展
用户、开发人员、合作伙伴及客户可以使用扩展来扩展和增强 Rancher UI。SUSE Edge 3.0 提供 KubeVirt 和 Akri 仪表板扩展。
- 6 Fleet
Fleet 是一个容器管理和部署引擎,旨在让用户更好地控制本地群集,并通过 GitOps 进行持续监控。Fleet 不仅注重缩放能力,而且还为用户提供很高的控制度和可见性,以准确监控群集上安装的组件。
- 7 SLE Micro
请参见 SLE Micro 官方文档
- 8 Metal3
Metal3 是一个 CNCF 项目,它为 Kubernetes 提供裸机基础架构管理功能。
- 9 Edge Image Builder
请参见官方储存库。
- 10 边缘网络
本章介绍 SUSE Edge 解决方案中的网络配置方法。我们将展示如何以声明方式在 SLE Micro 上配置 NetworkManager,并说明如何集成相关的工具。
- 11 Elemental
Elemental 是一个软件堆栈,可用于通过 Kubernetes 实现集中式云原生操作系统全面管理。Elemental 堆栈由驻留在 Rancher 本身或边缘节点上的许多组件构成。核心组件包括:
- 12 Akri
Akri 是一个 CNCF 沙箱项目,旨在发现叶设备并将其呈现为 Kubernetes 原生资源。它还允许为每个发现的设备调度一个 Pod 或作业。设备可以在节点本地,也可以联网,并可以使用多种协议。
- 13 K3s
K3s 是高度可用的、经过认证的 Kubernetes 发行版,专为无人照管、资源受限的远程位置或物联网设备内的生产工作负载而设计。
- 14 RKE2
请参见 RKE2 官方文档。
- 15 Longhorn
Longhorn 是专为 Kubernetes 设计的可靠且用户友好的轻量级分布式块存储系统。作为一个开源项目,Longhorn 最初由 Rancher Labs 开发,目前正在由 CNCF 孵化。
- 16 NeuVector
NeuVector 是适用于 Kubernetes 的安全解决方案,它在统一的软件包中提供 L7 网络安全性、运行时安全性、供应链安全性与合规性检查。
- 17 MetalLB
请参见 MetalLB 官方文档。
- 18 边缘虚拟化
本章介绍如何使用边缘虚拟化在边缘节点上运行虚拟机。必须指出的是,边缘虚拟化并非全面的解决方案,其功能有限;它会尝试解决需要基本虚拟机功能的轻量级虚拟化的要求。SUSE 通过 Harvester 提供更全面的虚拟化(和超融合基础架构)解决方案。
4 Rancher #
请参见 https://ranchermanager.docs.rancher.com 上的 Rancher 上游文档。
Rancher 是一个功能强大的开源 Kubernetes 管理平台,可以简化跨多个环境的 Kubernetes 群集的部署、操作和监控。无论您是在本地、云中还是边缘管理群集,Rancher 都能提供统一且集中的平台来满足您的所有 Kubernetes 需求。
4.1 Rancher 的主要功能 #
多群集管理:Rancher 的直观界面让您可以从任何位置(公有云、专用数据中心和边缘位置)管理 Kubernetes 群集。
安全性与合规性:Rancher 在您的 Kubernetes 环境中实施安全策略、基于角色的访问控制 (RBAC) 与合规性标准。
简化的群集操作:Rancher 可自动执行群集置备、升级和查错,并为各种规模的团队简化 Kubernetes 操作。
集中式应用程序目录:Rancher 应用程序目录提供多种 Helm chart 和 Kubernetes 操作器,使容器化应用程序的部署和管理变得简单。
持续交付:Rancher 支持 GitOps 和 CI/CD 管道,可以自动化和简化应用程序交付过程。
4.2 Rancher 在 SUSE Edge 中的使用 #
Rancher 为 SUSE Edge 堆栈提供多项核心功能:
4.2.1 集中式 Kubernetes 管理 #
在采用大量分布式群集的典型边缘部署中,Rancher 充当中心控制平面来管理这些 Kubernetes 群集。它提供统一的界面用于置备、升级、监控和查错、简化操作并确保一致性。
4.2.2 简化的群集部署 #
Rancher 简化了轻量级 SLE Micro (SUSE Linux Enterprise Micro) 操作系统上的 Kubernetes 群集创建,并通过稳健的 Kubernetes 功能简化了边缘基础架构的部署。
4.2.3 应用程序部署和管理 #
集成的 Rancher 应用程序目录可以简化跨 SUSE Edge 群集的容器化应用程序的部署和管理,实现无缝的边缘工作负载部署。
4.2.4 安全性和策略实施 #
Rancher 提供基于策略的治理工具、基于角色的访问控制 (RBAC),以及与外部身份验证提供程序的集成。这有助于 SUSE Edge 部署保持安全且合规,在分布式环境中,这一点至关重要。
4.3 最佳实践 #
4.3.1 GitOps #
Rancher 包含内置组件 Fleet。使用 Fleet 可以通过 git 中存储的代码管理群集配置和应用程序部署。
4.3.2 可观测性 #
Rancher 包含 Prometheus 和 Grafana 等内置监控和日志记录工具,可提供群集健康状况和性能的综合深入信息。
4.4 使用 Edge Image Builder 进行安装 #
SUSE Edge 使用第 9 章 “Edge Image Builder”来自定义基础 SLE Micro 操作系统映像。请按照第 21.6 节 “Rancher 安装”中所述,在 EIB 置备的 Kubernetes 群集上进行 Rancher 隔离式安装。
4.5 其他资源 #
5 Rancher 仪表板扩展 #
用户、开发人员、合作伙伴及客户可以使用扩展来扩展和增强 Rancher UI。SUSE Edge 3.0 提供 KubeVirt 和 Akri 仪表板扩展。
有关 Rancher 仪表板扩展的一般信息,请参见 Rancher
文档
。
5.1 先决条件 #
要启用扩展,需按照 Rancher 的要求安装 ui-plugin 操作器。使用 Rancher 仪表板 UI 时,导航到左侧 Configuration(配置)导航部分中的 Extensions(扩展)。如果未安装 ui-plugin
操作器,系统会提示您按此处
所述启用扩展支持。
也可以使用 Helm 安装该操作器:
helm repo add rancher-charts https://charts.rancher.io/
helm upgrade --create-namespace -n cattle-ui-plugin-system \
--install ui-plugin-operator rancher-charts/ui-plugin-operator
helm upgrade --create-namespace -n cattle-ui-plugin-system \
--install ui-plugin-operator-crd rancher-charts/ui-plugin-operator-crd
或者,可以在 Fleet 中创建专用的 GitRepo 资源。有关详细信息,请参见 Fleet 一章和 fleet-examples
储存库。
5.2 安装 #
所有 SUSE Edge 3.0 组件(包括仪表板扩展)均作为 OCI 项目分发。Rancher 仪表板 Apps/Marketplace
目前
不支持基于
OCI 的 Helm 储存库。因此,要安装 SUSE Edge 扩展,可以使用 Helm 或 Fleet:
5.2.1 使用 Helm 进行安装 #
# KubeVirt extension
helm install kubevirt-dashboard-extension oci://registry.suse.com/edge/kubevirt-dashboard-extension-chart --version 1.0.0 --namespace cattle-ui-plugin-system
# Akri extension
helm install akri-dashboard-extension oci://registry.suse.com/edge/akri-dashboard-extension-chart --version 1.0.0 --namespace cattle-ui-plugin-system
扩展需安装在 cattle-ui-plugin-system
名称空间中。
安装扩展后,需要重新加载 Rancher 仪表板 UI。
5.2.2 使用 Fleet 进行安装 #
使用 Fleet 安装仪表板扩展需要定义一个 gitRepo
资源,该资源指向包含自定义
fleet.yaml
捆绑包配置文件的 Git 储存库。
# KubeVirt extension fleet.yaml
defaultNamespace: cattle-ui-plugin-system
helm:
releaseName: kubevirt-dashboard-extension
chart: oci://registry.suse.com/edge/akri-dashboard-extension-chart
version: "1.0.0"
# Akri extension fleet.yaml
defaultNamespace: cattle-ui-plugin-system
helm:
releaseName: akri-dashboard-extension
chart: oci://registry.suse.com/edge/akri-dashboard-extension-chart
version: "1.0.0"
releaseName
属性是必需的,它需要与扩展名称匹配,才能让 ui-plugin-operator
正确安装扩展。
cat <<- EOF | kubectl apply -f -
apiVersion: fleet.cattle.io/v1alpha1
metadata:
name: edge-dashboard-extensions
namespace: fleet-local
spec:
repo: https://github.com/suse-edge/fleet-examples.git
branch: main
paths:
- fleets/kubevirt-dashboard-extension/
- fleets/akri-dashboard-extension/
EOF
有关详细信息,请参见 Fleet 一章和 fleet-examples
储存库。
安装扩展后,它们将列在 Installed(已安装)选项卡下的 Extensions(扩展)部分中。由于它们不是通过 Apps/Marketplace
安装的,因此带有 Third-Party
(第三方)标签。
5.3 KubeVirt 仪表板扩展 #
KubeVirt 扩展为 Rancher 仪表板 UI 提供基本虚拟机管理。边缘虚拟化中介绍了其功能。
5.4 Akri 仪表板扩展 #
Akri 是一个 Kubernetes 资源接口,让您可以轻松地将异构叶设备(例如 IP 摄像头和 USB 设备)公开为 Kubernetes 群集中的资源,同时还支持公开 GPU 和 FPGA 等嵌入式硬件资源。Akri 会持续检测有权访问这些设备的节点,并根据这些节点调度工作负载。
Akri 仪表板扩展允许您使用 Rancher 仪表板用户界面来管理和监控叶设备,并在发现这些设备后运行工作负载。
Akri 一章中更详细地介绍了扩展功能。
6 Fleet #
Fleet 是一个容器管理和部署引擎,旨在让用户更好地控制本地群集,并通过 GitOps 进行持续监控。Fleet 不仅注重缩放能力,而且还为用户提供很高的控制度和可见性,以准确监控群集上安装的组件。
Fleet 可以管理通过原始 Kubernetes YAML、Helm chart、Kustomize 的 Git 软件包或这三者的任意组合完成的部署。无论源是什么,所有资源都会动态转换为 Helm chart,并使用 Helm 作为引擎在群集中部署所有资源。因此,用户可以享受很高的群集控制度、一致性和可审计性。
有关 Fleet 工作原理的信息,请参见此处。
6.1 使用 Helm 安装 Fleet #
Fleet 已内置于 Rancher 中,但您也可以使用 Helm 将 Fleet 安装为任何 Kubernetes 群集上的独立应用程序。
6.2 使用 Rancher 中的 Fleet #
Rancher 使用 Fleet 在受管群集中部署应用程序。Fleet 的持续交付功能引入了大规模 GitOps,旨在管理在大量群集上运行的应用程序。
作为 Rancher 中不可或缺的组成部分,Fleet 的作用令人瞩目。使用 Rancher 管理的群集会在安装/导入过程中自动由 Fleet 代理部署,并且群集立即可由 Fleet 管理。
6.3 在 Rancher UI 中访问 Fleet #
Fleet 已预装在 Rancher 中,可以通过 Rancher UI 中的 Continuous Delivery(持续交付)选项进行管理。有关“Continuous Delivery”(持续交付)和其他 Fleet 查错提示的更多信息,请参见此处。
“Continuous Delivery”(持续交付)部分包括以下项目:
6.3.1 Dashboard(仪表板) #
所有工作空间中所有 GitOps 储存库的概览页面。仅显示包含储存库的工作空间。
6.3.2 Git repos(Git 储存库) #
所选工作空间中的 GitOps 储存库列表。使用页面顶部的下拉列表选择活动工作空间。
6.3.3 Clusters(群集) #
受管群集列表。默认情况下,Rancher 管理的所有群集都会添加到 fleet-default
工作空间。fleet-local
工作空间包含本地(管理)群集。在此处可以暂停
或强制更新
群集,或者将群集移动到另一个工作空间。可以通过编辑群集来更新用于群集分组的标签和批注。
6.3.4 Cluster groups(群集组) #
在此部分,可以使用选择器对工作空间内的群集进行自定义分组。
6.3.5 Advanced(高级) #
在“Advanced”(高级)部分可以管理工作空间和其他相关 Fleet 资源。
6.4 使用 Rancher 仪表板通过 Rancher 和 Fleet 安装 KubeVirt 的示例 #
创建包含
fleet.yaml
文件的 Git 储存库:defaultNamespace: kubevirt helm: chart: "oci://registry.suse.com/edge/kubevirt-chart" version: "0.2.4" # kubevirt namespace is created by kubevirt as well, we need to take ownership of it takeOwnership: true
在 Rancher 仪表板中,导航到 ☰ > Continuous Delivery(持续交付)> Git repos(Git 储存库),然后单击
Add Repository
(添加储存库)。储存库创建向导将指导您完成 Git 储存库创建步骤。提供名称、储存库 URL(引用上一步骤中创建的 Git 储存库),并选择适当的分支或修订版。对于较复杂的储存库,请指定路径以便在单个储存库中使用多个目录。
单击
Next
(下一步)。在下一步骤中,可以定义工作负载的部署位置。在群集选择方面,可以使用多个基本选项:可以不选择任何群集、选择所有群集,或者直接选择特定的受管群集或群集组(如果已定义)。“Advanced”(高级)选项允许通过 YAML 直接编辑选择器。
单击
Create
(创建)。随即会创建储存库。从现在起,工作负载将在与储存库定义匹配的群集上安装并保持同步。
6.5 调试和查错 #
“Advanced”(高级)导航部分提供了较低级 Fleet 资源的概览。捆绑包是一个内部资源,用于编排 Git 中的资源。扫描 Git 储存库时,会生成一个或多个捆绑包。
要查找与特定储存库相关的捆绑包,请转到 Git 储存库细节页面,并单击 Bundles
(捆绑包)选项卡。
对于每个群集,捆绑包将应用于创建的 BundleDeployment 资源。要查看 BundleDeployment 细节,请单击 Git
储存库细节页面右上角的 Graph
(图表)按钮。随即会加载 Repo(储存库)> Bundles(捆绑包)> BundleDeployment
图表。在图表中单击相应 BundleDeployment 可查看其细节,单击 ID
可查看
BundleDeployment YAML。
有关 Fleet 查错提示的更多信息,请参见此处。
6.6 Fleet 示例 #
Edge 团队维护的一个储存库包含了有关使用 Fleet 安装 Edge 项目的示例。
Fleet 项目包含 fleet-examples 储存库,其中涵盖了 Git 储存库结构的所有用例。
7 SLE Micro #
请参见 SLE Micro 官方文档
SUSE Linux Enterprise Micro 是一个安全的轻量级边缘操作系统。它将 SUSE Linux Enterprise 的企业强化组件与开发人员需要的各种功能融入一套不可变的新式操作系统,从而形成一个可靠的基础架构平台,不仅具有同类最佳的合规性,而且易于使用。
7.1 SUSE Edge 如何使用 SLE Micro? #
我们使用 SLE Micro 作为平台堆栈的基础操作系统。它为我们提供了安全、稳定且精简的构建基础。
SLE Micro 的独特之处在于使用文件系统 (Btrfs) 快照,因此如果在升级期间出错,我们就可以轻松回滚。这样,在出现问题时,即使无法进行物理访问,也可以对整个平台安全地进行远程升级。
7.2 最佳实践 #
7.2.1 安装媒体 #
SUSE Edge 使用 Edge Image Builder(第 9 章 “Edge Image Builder”)来预配置 SLE Micro 自行安装映像。
7.2.2 本地管理 #
SLE Micro 附带 Cockpit,让您可以通过 Web 应用程序对主机进行本地管理。
此服务默认已禁用,但可以通过启用 systemd 服务 cockpit.socket
来启动。
7.3 已知问题 #
SLE Micro 目前不提供桌面环境,但正在开发容器化解决方案。
8 Metal3 #
Metal3 是一个 CNCF 项目,它为 Kubernetes 提供裸机基础架构管理功能。
Metal3 提供 Kubernetes 原生资源来管理裸机服务器的生命周期,支持通过 Redfish 等带外协议进行管理。
它还为群集 API (CAPI) 提供成熟的支持,允许通过广泛采用的不区分供应商的 API 来管理跨多个基础架构提供商的基础架构资源。
8.1 SUSE Edge 如何使用 Metal3? #
此方法非常适合用于目标硬件支持带外管理,并且需要全自动化基础架构管理流程的方案。
此方法提供声明性 API 来对裸机服务器进行清单和状态管理,包括自动检查、清理和置备/取消置备。
8.2 已知问题 #
上游 IP 地址管理控制器目前不受支持,因为它与我们选择的网络配置工具尚不兼容。
相关的 IPAM 资源和 Metal3DataTemplate networkData 字段也不受支持。
目前仅支持通过 redfish-virtualmedia 进行部署。
9 Edge Image Builder #
请参见官方储存库。
Edge Image Builder (EIB) 工具可以简化为引导计算机生成自定义的、随时可引导 (CRB) 磁盘映像的过程。使用其中的一个映像就能实现整个 SUSE 软件堆栈的端到端部署。
虽然 EIB 可为所有置备方案创建 CRB 映像,但 EIB 在网络受限或完全隔离的隔离式部署中展示了巨大价值。
9.1 SUSE Edge 如何使用 Edge Image Builder? #
SUSE Edge 使用 EIB 来简化和快速配置自定义 SLE Micro 映像,以适应各种方案。这些方案包括通过以下方式引导虚拟机和裸机:
K3s/RKE2 Kubernetes 的完全隔离式部署(单节点和多节点)
完全隔离式 Helm chart和 Kubernetes 清单部署
通过 Elemental API 注册到 Rancher
Metal3
自定义网络(例如静态 IP、主机名、VLAN、绑定等)
自定义操作系统配置(例如用户、组、口令、SSH 密钥、代理、NTP、自定义 SSL 证书等)
主机级和侧载 RPM 软件包的隔离式安装(包括依赖项解析)
注册到 SUSE Manager 进行操作系统管理
嵌入式容器映像
内核命令行参数
引导时启用/禁用的 Systemd 单元
用于任何手动任务的自定义脚本和文件
9.2 入门 #
有关 Edge Image Builder 用法和测试的综合文档可在此处找到。
此处还提供了 Edge Image Builder 的快速入门指南(第 3 章 “使用 Edge Image Builder 配置独立群集”),其中包括基本部署方案。
9.3 已知问题 #
EIB 通过模板化 Helm chart 并分析模板中的所有映像来隔离 Helm chart。如果 Helm chart 未将其所有映像保留在模板中,而是侧载映像,则 EIB 将无法自动隔离这些映像。此问题的解决方法是手动将任何未检测到的映像添加到定义文件的
embeddedArtifactRegistry
部分。
10 边缘网络 #
本章介绍 SUSE Edge 解决方案中的网络配置方法。我们将展示如何以声明方式在 SLE Micro 上配置 NetworkManager,并说明如何集成相关的工具。
10.1 NetworkManager 概述 #
NetworkManager 是用于管理主网络连接和其他连接接口的工具。
NetworkManager 将网络配置存储为包含所需状态的连接文件。这些连接以文件的形式存储在
/etc/NetworkManager/system-connections/
目录中。
有关 NetworkManager 的细节,请参见上游 SLE Micro 文档。
10.2 nmstate 概述 #
nmstate 是广泛采用的库(附带 CLI 工具),它提供声明性 API 用于通过预定义的纲要进行网络配置。
有关 nmstate 的细节,请参见上游文档。
10.3 NetworkManager Configurator (nmc) 概述 #
SUSE Edge 中提供的网络自定义选项是通过一个称为 NetworkManager Configurator(简称为 nmc)的 CLI 工具实现的。此工具利用 nmstate 库提供的功能,因此完全能够配置静态 IP 地址、DNS 服务器、VLAN、绑定、网桥等。我们可以使用此工具从预定义的所需状态生成网络配置,并自动将这些配置应用于许多不同的节点。
有关 NetworkManager Configurator (nmc) 的细节,请参见上游储存库。
10.4 SUSE Edge 如何使用 NetworkManager Configurator? #
SUSE Edge 利用 nmc 在各种不同的置备模型中进行网络自定义:
定向网络置备方案中的自定义网络配置(第 1 章 “使用 Metal3 实现 BMC 自动化部署”)
基于映像的置备方案中的声明性静态配置(第 3 章 “使用 Edge Image Builder 配置独立群集”)
10.5 使用 Edge Image Builder 进行配置 #
Edge Image Builder (EIB) 是可用于通过单个操作系统映像配置多个主机的工具。本节将介绍如何使用声明性方法来描述所需网络状态,如何将这些状态转换为相应的 NetworkManager 连接,然后在置备过程中应用这些连接。
10.5.1 先决条件 #
如果您要学习本指南,事先需要做好以下准备:
一台运行 SLES 15 SP5 或 openSUSE Leap 15.5 的 x86_64 物理主机(或虚拟机)
一个可用的容器运行时(例如 Podman)
SLE Micro 5.5 RAW 映像的副本,可在此处找到
10.5.2 获取 Edge Image Builder 容器映像 #
EIB 容器映像已公开提供,可以通过运行以下命令从 SUSE Edge 注册表下载:
podman pull registry.suse.com/edge/edge-image-builder:1.0.2
10.5.3 创建映像配置目录 #
我们来开始创建配置目录:
export CONFIG_DIR=$HOME/eib mkdir -p $CONFIG_DIR/base-images
确保下载的基础映像副本已移动到配置目录:
mv /path/to/downloads/SLE-Micro.x86_64-5.5.0-Default-GM.raw $CONFIG_DIR/base-images/
注意EIB 永远不会修改基础映像输入。
此时,配置目录应如下所示:
└── base-images/ └── SLE-Micro.x86_64-5.5.0-Default-GM.raw
10.5.4 创建映像定义文件 #
定义文件描述了 Edge Image Builder 支持的大多数可配置选项。
首先,我们为操作系统映像创建一个非常简单的定义文件:
cat << EOF > $CONFIG_DIR/definition.yaml apiVersion: 1.0 image: arch: x86_64 imageType: raw baseImage: SLE-Micro.x86_64-5.5.0-Default-GM.raw outputImageName: modified-image.raw operatingSystem: users: - username: root encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/ EOF
image
部分是必需的,它指定输入映像、输入映像的体系结构和类型,以及输出映像的名称。operatingSystem
部分是可选的,其中包含的配置可用于通过 root/eib
用户名/口令登录到置备的系统。
注意您可以运行
openssl passwd -6 <password>
任意使用自己的已加密口令。
此时,配置目录应如下所示:
├── definition.yaml └── base-images/ └── SLE-Micro.x86_64-5.5.0-Default-GM.raw
10.5.5 定义网络配置 #
所需网络配置不是我们刚刚创建的映像定义文件的一部分。现在我们在特殊的 network/
目录下填充这些配置。我们来创建该目录:
mkdir -p $CONFIG_DIR/network
如前所述,NetworkManager Configurator (nmc) 工具要求提供预定义纲要形式的输入。您可以在上游 NMState 示例文档中了解如何设置各种不同的网络选项。
本指南将介绍如何在三个不同的节点上配置网络:
使用两个以太网接口的节点
使用网络绑定的节点
使用网桥的节点
不建议在生产构建中使用完全不同的网络设置,尤其是在配置 Kubernetes 群集时。网络配置通常应在节点之间或至少在给定群集内的角色之间保持同质。本指南包含的各种不同选项仅供参考。
注意以下示例采用 IP 地址范围为
192.168.122.1/24
的默认libvirt
网络。如果您的环境与此不同,请相应地进行调整。
我们来为第一个节点(名为 node1.suse.com
)创建所需状态:
cat << EOF > $CONFIG_DIR/network/node1.suse.com.yaml routes: config: - destination: 0.0.0.0/0 metric: 100 next-hop-address: 192.168.122.1 next-hop-interface: eth0 table-id: 254 - destination: 192.168.122.0/24 metric: 100 next-hop-address: next-hop-interface: eth0 table-id: 254 dns-resolver: config: server: - 192.168.122.1 - 8.8.8.8 interfaces: - name: eth0 type: ethernet state: up mac-address: 34:8A:B1:4B:16:E1 ipv4: address: - ip: 192.168.122.50 prefix-length: 24 dhcp: false enabled: true ipv6: enabled: false - name: eth3 type: ethernet state: down mac-address: 34:8A:B1:4B:16:E2 ipv4: address: - ip: 192.168.122.55 prefix-length: 24 dhcp: false enabled: true ipv6: enabled: false EOF
在此示例中,我们将定义两个以太网接口(eth0 和 eth3)的所需状态、其请求 IP 地址、路由和 DNS 解析。
必须确保列出了所有以太网接口的 MAC 地址。这些地址在置备过程中用作节点的标识符,用于确定要应用哪些配置。这就是我们使用单个 ISO 或 RAW 映像配置多个节点的方式。
接下来对第二个节点(名为 node2.suse.com
)进行操作,该节点使用网络绑定:
cat << EOF > $CONFIG_DIR/network/node2.suse.com.yaml routes: config: - destination: 0.0.0.0/0 metric: 100 next-hop-address: 192.168.122.1 next-hop-interface: bond99 table-id: 254 - destination: 192.168.122.0/24 metric: 100 next-hop-address: next-hop-interface: bond99 table-id: 254 dns-resolver: config: server: - 192.168.122.1 - 8.8.8.8 interfaces: - name: bond99 type: bond state: up ipv4: address: - ip: 192.168.122.60 prefix-length: 24 enabled: true link-aggregation: mode: balance-rr options: miimon: '140' port: - eth0 - eth1 - name: eth0 type: ethernet state: up mac-address: 34:8A:B1:4B:16:E3 ipv4: enabled: false ipv6: enabled: false - name: eth1 type: ethernet state: up mac-address: 34:8A:B1:4B:16:E4 ipv4: enabled: false ipv6: enabled: false EOF
在此示例中,我们将定义两个未启用 IP 寻址的以太网接口(eth0 和 eth1)的所需状态,以及采用轮替策略的绑定及其用于转发网络流量的相应地址。
最后,我们将创建第三个(也是最后一个)所需状态文件,该文件利用网桥,我们将其命名为 node3.suse.com
:
cat << EOF > $CONFIG_DIR/network/node3.suse.com.yaml routes: config: - destination: 0.0.0.0/0 metric: 100 next-hop-address: 192.168.122.1 next-hop-interface: linux-br0 table-id: 254 - destination: 192.168.122.0/24 metric: 100 next-hop-address: next-hop-interface: linux-br0 table-id: 254 dns-resolver: config: server: - 192.168.122.1 - 8.8.8.8 interfaces: - name: eth0 type: ethernet state: up mac-address: 34:8A:B1:4B:16:E5 ipv4: enabled: false ipv6: enabled: false - name: linux-br0 type: linux-bridge state: up ipv4: address: - ip: 192.168.122.70 prefix-length: 24 dhcp: false enabled: true bridge: options: group-forward-mask: 0 mac-ageing-time: 300 multicast-snooping: true stp: enabled: true forward-delay: 15 hello-time: 2 max-age: 20 priority: 32768 port: - name: eth0 stp-hairpin-mode: false stp-path-cost: 100 stp-priority: 32 EOF
此时,配置目录应如下所示:
├── definition.yaml ├── network/ │ │── node1.suse.com.yaml │ │── node2.suse.com.yaml │ └── node3.suse.com.yaml └── base-images/ └── SLE-Micro.x86_64-5.5.0-Default-GM.raw
注意
network/
目录中的文件是有意命名的。它们对应于在置备过程中要设置的主机名。
10.5.6 构建操作系统映像 #
完成所有必要配置后,接下来我们只需运行以下命令来构建映像:
podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/edge-image-builder:1.0.2 build --definition-file definition.yaml
输出应如下所示:
Generating image customization components... Identifier ................... [SUCCESS] Custom Files ................. [SKIPPED] Time ......................... [SKIPPED] Network ...................... [SUCCESS] Groups ....................... [SKIPPED] Users ........................ [SUCCESS] Proxy ........................ [SKIPPED] Rpm .......................... [SKIPPED] Systemd ...................... [SKIPPED] Elemental .................... [SKIPPED] Suma ......................... [SKIPPED] Embedded Artifact Registry ... [SKIPPED] Keymap ....................... [SUCCESS] Kubernetes ................... [SKIPPED] Certificates ................. [SKIPPED] Building RAW image... Kernel Params ................ [SKIPPED] Image build complete!
以上输出片段告诉我们网络
组件已成功配置,我们可以继续置备边缘节点。
注意可以在运行映像的带时间戳目录下生成的
_build
目录中,检查日志文件 (network-config.log
) 和相应的 NetworkManager 连接文件。
10.5.7 置备边缘节点 #
我们来复制生成的 RAW 映像:
mkdir edge-nodes && cd edge-nodes for i in {1..4}; do cp $CONFIG_DIR/modified-image.raw node$i.raw; done
您会发现,我们复制了构建的映像四次,但仅指定了三个节点的网络配置。这是因为,我们还想展示当置备的节点与任何所需配置都不匹配时会发生什么。
注意本指南将为节点置备示例使用虚拟化。请确保在 BIOS 中启用必要的扩展(有关细节,请参见此处)。
我们将运行 virt-install
使用复制的原始磁盘来创建虚拟机。每个虚拟机使用 10 GB RAM 和 6
个 vCPU。
10.5.7.1 置备第一个节点 #
我们来创建虚拟机:
virt-install --name node1 --ram 10000 --vcpus 6 --disk path=node1.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E1 --network default,mac=34:8A:B1:4B:16:E2 --virt-type kvm --import
注意要创建的网络接口的 MAC 地址必须与上述所需状态中使用的 MAC 地址相同。
操作完成后,我们将看到如下所示的输出:
Starting install... Creating domain... Running text console command: virsh --connect qemu:///system console node1 Connected to domain 'node1' Escape character is ^] (Ctrl + ]) Welcome to SUSE Linux Enterprise Micro 5.5 (x86_64) - Kernel 5.14.21-150500.55.19-default (ttyS0). SSH host key: SHA256:XN/R5Tw43reG+QsOw480LxCnhkc/1uqMdwlI6KUBY70 (RSA) SSH host key: SHA256:/96yGrPGKlhn04f1rb9cXv/2WJt4TtrIN5yEcN66r3s (DSA) SSH host key: SHA256:Dy/YjBQ7LwjZGaaVcMhTWZNSOstxXBsPsvgJTJq5t00 (ECDSA) SSH host key: SHA256:TNGqY1LRddpxD/jn/8dkT/9YmVl9hiwulqmayP+wOWQ (ED25519) eth0: 192.168.122.50 eth1: Configured with the Edge Image Builder Activate the web console with: systemctl enable --now cockpit.socket node1 login:
现在我们可以使用 root:eib
身份凭证对登录。如果需要,我们也可以通过 SSH
连接到主机,而不是如此处所示使用 virsh 控制台
进行连接。
登录后,我们需要确认是否正确完成了所有设置。
校验是否正确设置了主机名:
node1:~ # hostnamectl Static hostname: node1.suse.com ...
校验是否正确配置了路由:
node1:~ # ip r default via 192.168.122.1 dev eth0 proto static metric 100 192.168.122.0/24 dev eth0 proto static scope link metric 100 192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.50 metric 100
校验互联网连接是否可用:
node1:~ # ping google.com PING google.com (142.250.72.78) 56(84) bytes of data. 64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=1 ttl=56 time=13.2 ms 64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=2 ttl=56 time=13.4 ms ^C --- google.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 13.248/13.304/13.361/0.056 ms
校验是否刚好配置了两个以太网接口,并且只有其中的一个接口处于活动状态:
node1:~ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e1 brd ff:ff:ff:ff:ff:ff altname enp0s2 altname ens2 inet 192.168.122.50/24 brd 192.168.122.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e2 brd ff:ff:ff:ff:ff:ff altname enp0s3 altname ens3 node1:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show NAME UUID TYPE DEVICE FILENAME eth0 dfd202f5-562f-5f07-8f2a-a7717756fb70 ethernet eth0 /etc/NetworkManager/system-connections/eth0.nmconnection eth1 7e211aea-3d14-59cf-a4fa-be91dac5dbba ethernet -- /etc/NetworkManager/system-connections/eth1.nmconnection
您会发现,在所需网络状态中,第二个接口是 eth1
,而不是预定义的
eth3
。之所以出现这种情况,是因为 NetworkManager Configurator
(nmc) 能够检测到操作系统为 MAC 地址为
34:8a:b1:4b:16:e2
的 NIC 指定了不同的名称,并相应地调整了其设置。
通过检查置备的 Combustion 阶段来校验是否确实发生了这种情况:
node1:~ # journalctl -u combustion | grep nmc Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO nmc::apply_conf] Identified host: node1.suse.com Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO nmc::apply_conf] Set hostname: node1.suse.com Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO nmc::apply_conf] Processing interface 'eth0'... Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO nmc::apply_conf] Processing interface 'eth3'... Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO nmc::apply_conf] Using interface name 'eth1' instead of the preconfigured 'eth3' Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO nmc] Successfully applied config
我们现在将置备其余节点,但只会显示最终配置中的差异。您可以随意对即将置备的所有节点应用上述任意检查或所有检查。
10.5.7.2 置备第二个节点 #
我们来创建虚拟机:
virt-install --name node2 --ram 10000 --vcpus 6 --disk path=node2.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E3 --network default,mac=34:8A:B1:4B:16:E4 --virt-type kvm --import
虚拟机启动并运行后,我们可以确认此节点是否正在使用绑定的接口:
node2:~ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond99 state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff altname enp0s2 altname ens2 3: eth1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond99 state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff permaddr 34:8a:b1:4b:16:e4 altname enp0s3 altname ens3 4: bond99: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff inet 192.168.122.60/24 brd 192.168.122.255 scope global noprefixroute bond99 valid_lft forever preferred_lft forever
确认路由是否正在使用绑定:
node2:~ # ip r default via 192.168.122.1 dev bond99 proto static metric 100 192.168.122.0/24 dev bond99 proto static scope link metric 100 192.168.122.0/24 dev bond99 proto kernel scope link src 192.168.122.60 metric 300
确保正确利用静态连接文件:
node2:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show NAME UUID TYPE DEVICE FILENAME bond99 4a920503-4862-5505-80fd-4738d07f44c6 bond bond99 /etc/NetworkManager/system-connections/bond99.nmconnection eth0 dfd202f5-562f-5f07-8f2a-a7717756fb70 ethernet eth0 /etc/NetworkManager/system-connections/eth0.nmconnection eth1 0523c0a1-5f5e-5603-bcf2-68155d5d322e ethernet eth1 /etc/NetworkManager/system-connections/eth1.nmconnection
10.5.7.3 置备第三个节点 #
我们来创建虚拟机:
virt-install --name node3 --ram 10000 --vcpus 6 --disk path=node3.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E5 --virt-type kvm --import
虚拟机启动并运行后,我们可以确认此节点是否正在使用网桥:
node3:~ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master linux-br0 state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e5 brd ff:ff:ff:ff:ff:ff altname enp0s2 altname ens2 3: linux-br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 34:8a:b1:4b:16:e5 brd ff:ff:ff:ff:ff:ff inet 192.168.122.70/24 brd 192.168.122.255 scope global noprefixroute linux-br0 valid_lft forever preferred_lft forever
确认路由是否正在使用网桥:
node3:~ # ip r default via 192.168.122.1 dev linux-br0 proto static metric 100 192.168.122.0/24 dev linux-br0 proto static scope link metric 100 192.168.122.0/24 dev linux-br0 proto kernel scope link src 192.168.122.70 metric 425
确保正确利用静态连接文件:
node3:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show NAME UUID TYPE DEVICE FILENAME linux-br0 1f8f1469-ed20-5f2c-bacb-a6767bee9bc0 bridge linux-br0 /etc/NetworkManager/system-connections/linux-br0.nmconnection eth0 dfd202f5-562f-5f07-8f2a-a7717756fb70 ethernet eth0 /etc/NetworkManager/system-connections/eth0.nmconnection
10.5.7.4 置备第四个节点 #
最后,我们将置备 MAC 地址与任何预定义配置都不匹配的节点。在这种情况下,我们将默认使用 DHCP 来配置网络接口。
我们来创建虚拟机:
virt-install --name node4 --ram 10000 --vcpus 6 --disk path=node4.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --virt-type kvm --import
虚拟机启动并运行后,我们可以确认此节点是否正在为其网络接口使用随机 IP 地址:
localhost:~ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:56:63:71 brd ff:ff:ff:ff:ff:ff altname enp0s2 altname ens2 inet 192.168.122.86/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0 valid_lft 3542sec preferred_lft 3542sec inet6 fe80::5054:ff:fe56:6371/64 scope link noprefixroute valid_lft forever preferred_lft forever
校验 nmc 是否无法为此节点应用静态配置:
localhost:~ # journalctl -u combustion | grep nmc Apr 23 12:15:45 localhost.localdomain combustion[1357]: [2024-04-23T12:15:45Z ERROR nmc] Applying config failed: None of the preconfigured hosts match local NICs
校验是否通过 DHCP 配置了以太网接口:
localhost:~ # journalctl | grep eth0 Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7801] manager: (eth0): new Ethernet device (/org/freedesktop/NetworkManager/Devices/2) Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7802] device (eth0): state change: unmanaged -> unavailable (reason 'managed', sys-iface-state: 'external') Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7929] device (eth0): carrier: link connected Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7931] device (eth0): state change: unavailable -> disconnected (reason 'carrier-changed', sys-iface-state: 'managed') Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7944] device (eth0): Activation: starting connection 'Wired Connection' (300ed658-08d4-4281-9f8c-d1b8882d29b9) Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7945] device (eth0): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'managed') Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7947] device (eth0): state change: prepare -> config (reason 'none', sys-iface-state: 'managed') Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7953] device (eth0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed') Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info> [1713874529.7964] dhcp4 (eth0): activation: beginning transaction (timeout in 90 seconds) Apr 23 12:15:33 localhost.localdomain NetworkManager[704]: <info> [1713874533.1272] dhcp4 (eth0): state changed new lease, address=192.168.122.86 localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show NAME UUID TYPE DEVICE FILENAME Wired Connection 300ed658-08d4-4281-9f8c-d1b8882d29b9 ethernet eth0 /var/run/NetworkManager/system-connections/default_connection.nmconnection
10.5.8 统一节点配置 #
有时我们无法依赖已知的 MAC 地址。在这种情况下,我们可以选择所谓的统一配置,这样就可以在
_all.yaml
文件中指定设置,然后将这些设置应用于所有已置备的节点。
我们将使用不同的配置结构来构建和置备边缘节点。请按照从第 10.5.3 节 “创建映像配置目录”到第 10.5.5 节 “定义网络配置”的所有步骤进行操作。
在此示例中,我们将定义两个以太网接口(eth0 和 eth1)的所需状态 - 一个接口使用 DHCP,另一个接口使用静态 IP 地址。
mkdir -p $CONFIG_DIR/network cat <<- EOF > $CONFIG_DIR/network/_all.yaml interfaces: - name: eth0 type: ethernet state: up ipv4: dhcp: true enabled: true ipv6: enabled: false - name: eth1 type: ethernet state: up ipv4: address: - ip: 10.0.0.1 prefix-length: 24 enabled: true dhcp: false ipv6: enabled: false EOF
我们来构建映像:
podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/edge-image-builder:1.0.2 build --definition-file definition.yaml
成功构建映像后,我们将使用它来创建虚拟机:
virt-install --name node1 --ram 10000 --vcpus 6 --disk path=$CONFIG_DIR/modified-image.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --network default --virt-type kvm --import
置备过程可能需要几分钟时间。完成后,使用提供的身份凭证登录到系统。
校验是否正确配置了路由:
localhost:~ # ip r default via 192.168.122.1 dev eth0 proto dhcp src 192.168.122.100 metric 100 10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.1 metric 101 192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.100 metric 100
校验互联网连接是否可用:
localhost:~ # ping google.com PING google.com (142.250.72.46) 56(84) bytes of data. 64 bytes from den16s08-in-f14.1e100.net (142.250.72.46): icmp_seq=1 ttl=56 time=14.3 ms 64 bytes from den16s08-in-f14.1e100.net (142.250.72.46): icmp_seq=2 ttl=56 time=14.2 ms ^C --- google.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 14.196/14.260/14.324/0.064 ms
校验以太网接口是否已配置并处于活动状态:
localhost:~ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:26:44:7a brd ff:ff:ff:ff:ff:ff altname enp1s0 inet 192.168.122.100/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0 valid_lft 3505sec preferred_lft 3505sec 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:ec:57:9e brd ff:ff:ff:ff:ff:ff altname enp7s0 inet 10.0.0.1/24 brd 10.0.0.255 scope global noprefixroute eth1 valid_lft forever preferred_lft forever localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show NAME UUID TYPE DEVICE FILENAME eth0 dfd202f5-562f-5f07-8f2a-a7717756fb70 ethernet eth0 /etc/NetworkManager/system-connections/eth0.nmconnection eth1 0523c0a1-5f5e-5603-bcf2-68155d5d322e ethernet eth1 /etc/NetworkManager/system-connections/eth1.nmconnection localhost:~ # cat /etc/NetworkManager/system-connections/eth0.nmconnection [connection] autoconnect=true autoconnect-slaves=-1 id=eth0 interface-name=eth0 type=802-3-ethernet uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70 [ipv4] dhcp-client-id=mac dhcp-send-hostname=true dhcp-timeout=2147483647 ignore-auto-dns=false ignore-auto-routes=false method=auto never-default=false [ipv6] addr-gen-mode=0 dhcp-timeout=2147483647 method=disabled localhost:~ # cat /etc/NetworkManager/system-connections/eth1.nmconnection [connection] autoconnect=true autoconnect-slaves=-1 id=eth1 interface-name=eth1 type=802-3-ethernet uuid=0523c0a1-5f5e-5603-bcf2-68155d5d322e [ipv4] address0=10.0.0.1/24 dhcp-timeout=2147483647 method=manual [ipv6] addr-gen-mode=0 dhcp-timeout=2147483647 method=disabled
10.5.9 自定义网络配置 #
我们已介绍 Edge Image Builder 的依赖于 NetworkManager Configurator 的默认网络配置。但是,还可以选择通过自定义脚本来修改这种配置。虽然这种方法非常灵活而且不依赖于 MAC 地址,但它的局限性在于,在使用单个映像引导多个节点时,这种方法不太方便。
注意建议通过
/network
目录下描述所需网络状态的文件来使用默认网络配置。请仅在该行为不适用于您的用例时,才选择自定义脚本。
我们将使用不同的配置结构来构建和置备边缘节点。请按照从第 10.5.3 节 “创建映像配置目录”到第 10.5.5 节 “定义网络配置”的所有步骤进行操作。
在此示例中,我们将创建一个自定义脚本来对所有已置备节点上的 eth0
接口应用静态配置,同时去除并禁用
NetworkManager
自动创建的有线连接。如果您想要确保群集中每个节点都采用相同的网络配置,则这种做法非常有利,这样,您就不需要在创建映像之前考虑每个节点的 MAC 地址。
首先,我们将连接文件存储在 /custom/files
目录中:
mkdir -p $CONFIG_DIR/custom/files cat << EOF > $CONFIG_DIR/custom/files/eth0.nmconnection [connection] autoconnect=true autoconnect-slaves=-1 autoconnect-retries=1 id=eth0 interface-name=eth0 type=802-3-ethernet uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70 wait-device-timeout=60000 [ipv4] dhcp-timeout=2147483647 method=auto [ipv6] addr-gen-mode=eui64 dhcp-timeout=2147483647 method=disabled EOF
创建静态配置后,我们再创建自定义网络脚本:
mkdir -p $CONFIG_DIR/network cat << EOF > $CONFIG_DIR/network/configure-network.sh #!/bin/bash set -eux # Remove and disable wired connections mkdir -p /etc/NetworkManager/conf.d/ printf "[main]\nno-auto-default=*\n" > /etc/NetworkManager/conf.d/no-auto-default.conf rm -f /var/run/NetworkManager/system-connections/* || true # Copy pre-configured network configuration files into NetworkManager mkdir -p /etc/NetworkManager/system-connections/ cp eth0.nmconnection /etc/NetworkManager/system-connections/ chmod 600 /etc/NetworkManager/system-connections/*.nmconnection EOF chmod a+x $CONFIG_DIR/network/configure-network.sh
注意默认情况下仍会包含 nmc 二进制文件,因此如果需要,也可以在
configure-network.sh
脚本中使用它。
必须始终在配置目录中的 /network/configure-network.sh
下提供自定义脚本。将忽略存在的所有其他文件。无法同时使用 YAML 格式的静态配置和自定义脚本来配置网络。
此时,配置目录应如下所示:
├── definition.yaml ├── custom/ │ └── files/ │ └── eth0.nmconnection ├── network/ │ └── configure-network.sh └── base-images/ └── SLE-Micro.x86_64-5.5.0-Default-GM.raw
我们来构建映像:
podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/edge-image-builder:1.0.2 build --definition-file definition.yaml
成功构建映像后,我们将使用它来创建虚拟机:
virt-install --name node1 --ram 10000 --vcpus 6 --disk path=$CONFIG_DIR/modified-image.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --virt-type kvm --import
置备过程可能需要几分钟时间。完成后,使用提供的身份凭证登录到系统。
校验是否正确配置了路由:
localhost:~ # ip r default via 192.168.122.1 dev eth0 proto dhcp src 192.168.122.185 metric 100 192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.185 metric 100
校验互联网连接是否可用:
localhost:~ # ping google.com PING google.com (142.250.72.78) 56(84) bytes of data. 64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=1 ttl=56 time=13.6 ms 64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=2 ttl=56 time=13.6 ms ^C --- google.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 13.592/13.599/13.606/0.007 ms
校验是否使用连接文件静态配置了以太网接口,并且该接口处于活动状态:
localhost:~ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:31:d0:1b brd ff:ff:ff:ff:ff:ff altname enp0s2 altname ens2 inet 192.168.122.185/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0 localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show NAME UUID TYPE DEVICE FILENAME eth0 dfd202f5-562f-5f07-8f2a-a7717756fb70 ethernet eth0 /etc/NetworkManager/system-connections/eth0.nmconnection localhost:~ # cat /etc/NetworkManager/system-connections/eth0.nmconnection [connection] autoconnect=true autoconnect-slaves=-1 autoconnect-retries=1 id=eth0 interface-name=eth0 type=802-3-ethernet uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70 wait-device-timeout=60000 [ipv4] dhcp-timeout=2147483647 method=auto [ipv6] addr-gen-mode=eui64 dhcp-timeout=2147483647 method=disabled
11 Elemental #
Elemental 是一个软件堆栈,可用于通过 Kubernetes 实现集中式云原生操作系统全面管理。Elemental 堆栈由驻留在 Rancher 本身或边缘节点上的许多组件构成。核心组件包括:
elemental-operator - 驻留在 Rancher 上的核心操作器,用于处理来自客户端的注册请求。
elemental-register - 在边缘节点上运行的客户端,支持通过
elemental-operator
进行注册。elemental-system-agent - 驻留在边缘节点上的代理;其配置由
elemental-register
馈送,接收用于配置rancher-system-agent
的计划
。rancher-system-agent - 完全注册边缘节点后,此组件将接管
elemental-system-agent
,并等待 Rancher Manager 接下来的计划
(例如 Kubernetes 安装)。
有关 Elemental 及其与 Rancher 的关系的完整信息,请参见 Elemental 上游文档。
11.1 SUSE Edge 如何使用 Elemental? #
我们将使用 Elemental 的部分功能来管理无法使用 Metal3 的远程设备(例如,没有
BMC 的设备,或者设备位于 NAT 网关后面)。在知道设备何时运送或运送到何处之前,操作员可以使用此工具在实验室中引导其设备。也就是说,我们利用
elemental-register
和
elemental-system-agent
组件将 SLE Micro 主机初始配置到
Rancher,以支持“电告总部”网络置备用例。使用 Edge Image Builder (EIB) 创建部署映像时,可以通过在 EIB
的配置目录中指定注册配置,来使用 Elemental 通过 Rancher 完成自动注册。
在 SUSE Edge 3.0 中,我们不会利用 Elemental 的操作系统管理功能,因此无法通过 Rancher 管理操作系统修补。SUSE Edge 不会使用 Elemental 工具来构建部署映像,而是使用 Edge Image Builder 工具,而后者利用注册配置。
11.2 最佳实践 #
11.2.1 安装媒体 #
SUSE Edge 建议的、可以在“电告总部网络置备”部署空间中利用 Elemental 注册到 Rancher 的部署映像构建方法是,遵循有关使用 Elemental 进行远程主机初始配置(第 2 章 “使用 Elemental 进行远程主机初始配置”)快速入门中详述的说明。
11.2.2 标签 #
Elemental 使用 MachineInventory
CRD
跟踪其清单,并提供选择清单的方法,例如,根据标签选择要将 Kubernetes
群集部署到的计算机。这样,用户就可以在购买硬件之前,预定义其大部分(甚至所有)基础架构需求。另外,由于节点可以在其相应清单对象上添加/去除标签(结合附加标志
--label "FOO=BAR"
重新运行
elemental-register
),我们可以编写脚本来发现节点的引导位置并告诉 Rancher。
11.3 已知问题 #
Elemental UI 目前不知道如何构建安装媒体或更新非“Elemental Teal”操作系统。此问题在将来的版本中应会得到解决。
12 Akri #
Akri 是一个 CNCF 沙箱项目,旨在发现叶设备并将其呈现为 Kubernetes 原生资源。它还允许为每个发现的设备调度一个 Pod 或作业。设备可以在节点本地,也可以联网,并可以使用多种协议。
https://docs.akri.sh 上提供了 Akri 的上游文档
12.1 SUSE Edge 如何使用 Akri? #
Akri 目前在 SUSE Edge 堆栈中以技术预览的形式提供。
每当需要发现叶设备以及针对叶设备调度工作负载时,都可以使用 Edge 堆栈中包含的 Akri。
12.1.1 安装 Akri #
Akri 在 Edge Helm 储存库中作为 Helm chart 提供。建议的 Akri 配置方法是使用给定的 Helm chart 部署不同的组件(代理、控制器、发现处理程序),然后使用您偏好的部署机制部署 Akri 的配置 CRD。
12.1.2 配置 Akri #
使用 akri.sh/Configuration
对象来配置
Akri,该对象包含有关如何发现设备,以及发现了匹配的设备时要执行哪种操作的所有信息。
下面列出了示例配置的明细,其中解释了所有字段:
apiVersion: akri.sh/v0
kind: Configuration
metadata:
name: sample-configuration
spec:
此部分描述发现处理程序的配置,您必须指定处理程序的名称(作为 Akri chart 一部分提供的处理程序包括
udev
、opcua
、onvif
)。discoveryDetails
与特定的处理程序相关,有关其配置方法,请参见处理程序的文档。
discoveryHandler:
name: debugEcho
discoveryDetails: |+
descriptions:
- "foo"
- "bar"
此部分定义要为每个已发现设备部署的工作负载。该示例显示了 brokerPodSpec
中
Pod
配置的最低版本,在此处可以使用 Pod 规范的所有常规字段。其中还显示了
resources
部分中用于请求设备的 Akri 特定语法。
您也可以使用作业来代替 Pod,方法是改用 brokerJobSpec
键,并在其中提供作业的规范部分。
brokerSpec:
brokerPodSpec:
containers:
- name: broker-container
image: rancher/hello-world
resources:
requests:
"{{PLACEHOLDER}}" : "1"
limits:
"{{PLACEHOLDER}}" : "1"
这两个部分显示如何配置 Akri 以便为每个中介程序部署一个服务
(instanceService
),或指向所有中介程序
(configurationService
)。这些部分包含与常规服务相关的所有元素。
instanceServiceSpec:
type: ClusterIp
ports:
- name: http
port: 80
protocol: tcp
targetPort: 80
configurationServiceSpec:
type: ClusterIp
ports:
- name: https
port: 443
protocol: tcp
targetPort: 443
brokerProperties
字段是一个键/值存储,它将作为附加环境变量公开给请求已发现设备的任何 Pod。
capacity 是已发现设备的并发用户的允许数量。
brokerProperties:
key: value
capacity: 1
12.1.3 编写和部署更多发现处理程序 #
如果现有的发现处理程序无法涵盖您的设备使用的协议,您可以遵循此指南编写自己的发现处理程序。
12.1.4 Akri Rancher 仪表板扩展 #
Akri 仪表板扩展允许您使用 Rancher 仪表板用户界面来管理和监控叶设备,并在发现这些设备后运行工作负载。
安装扩展后,您可以使用群集资源管理器导航到任何已启用 Akri 的受管群集。在 Akri 导航组下,可以看到“Configurations”(配置)和“Instances”(实例)部分。
配置列表提供了有关配置发现处理程序和实例数量的信息。单击名称会打开配置细节页面。
您还可以编辑或创建新的配置。扩展允许您选择发现处理程序、设置中介程序 Pod 或作业、配置配置和实例服务,以及设置配置容量。
实例列表中会列出已发现的设备。
单击实例名称会打开细节页面,在其中可以查看工作负载和实例服务。
13 K3s #
K3s 是高度可用的、经过认证的 Kubernetes 发行版,专为无人照管、资源受限的远程位置或物联网设备内的生产工作负载而设计。
它打包为单个较小二进制文件,因此可以快速轻松地安装和更新。
13.1 SUSE Edge 如何使用 K3s #
K3s 可用作支持 SUSE Edge 堆栈的 Kubernetes 发行版。它适合安装在 SLE Micro 操作系统上。
仅当用作后端的 etcd 不能满足您的约束条件时,才建议使用 K3s 作为 SUSE Edge 堆栈 Kubernetes 发行版。如果 etcd 可用作后端,则最好使用 RKE2(第 14 章 “RKE2”)。
13.2 最佳实践 #
13.2.1 安装 #
将 K3s 安装为 SUSE Edge 堆栈一部分的建议方法是使用 Edge Image Builder (EIB)。有关如何配置 EIB 来部署 K3s 的更多细节,请参见其文档(第 9 章 “Edge Image Builder”)。
K3s 原生支持 HA 设置以及 Elemental 设置。
13.2.2 用于 GitOps 工作流程的 Fleet #
SUSE Edge 堆栈使用 Fleet 作为其首选 GitOps 工具。有关 Fleet 安装和用法的详细信息,请参见本文档中的“Fleet”一章(第 6 章 “Fleet”)。
13.2.3 存储管理 #
K3s 预配置了本地路径存储,这种存储适用于单节点群集。对于跨多个节点的群集,我们建议使用 Longhorn(第 15 章 “Longhorn”)。
13.2.4 负载平衡和 HA #
如果您使用 EIB 安装了 K3s,请参见 EIB 文档中的“HA”一章,其中已介绍本节所述的内容。
否则,您需要按照 MetalLB 文档(第 19 章 “K3s 上的 MetalLB(使用 L2)”)安装和配置 MetalLB。
14 RKE2 #
请参见 RKE2 官方文档。
RKE2 是注重安全性与合规性的完全符合规范的 Kubernetes 发行版,因为它可以:
提供默认设置和配置选项,使群集能够在操作员极少干预的情况下通过 CIS Kubernetes 基准 v1.6 或 v1.23
实现 FIPS 140-2 合规
在 RKE2 构建管道中使用 trivy 定期扫描组件中存在的 CVE
RKE2 将控制平面组件作为 kubelet 管理的静态 Pod 进行启动。嵌入式容器运行时为 containerd。
注意:RKE2 也称为 RKE 政府版,表示它目前面向另一种用例和市场领域。
14.1 RKE2 与 K3s 的比较 #
K3s 是完全合规的轻量级 Kubernetes 发行版,主要用于 Edge、IoT 和 ARM,在无法精通 K8s 群集学的情况下也可以使用它。
RKE2 结合了 1.x 版 RKE(后文称为 RKE1)和 K3s 的最大优点。
它承袭了 K3s 的易用性、易操作性和部署模型。
它承袭了 RKE1 与上游 Kubernetes 的紧密一致性。在某些地方,K3s 与上游 Kubernetes 有所不同,目的是针对边缘部署进行优化,但 RKE1 和 RKE2 可以与上游保持紧密一致性。
14.2 SUSE Edge 如何使用 RKE2? #
RKE2 是 SUSE Edge 堆栈的根本性组成部分。它位于 SUSE Linux Micro(第 7 章 “SLE Micro”)的顶层,提供部署 Edge 工作负载所需的标准 Kubernetes 接口,且占用的空间极小。
14.3 最佳实践 #
14.3.1 安装 #
将 RKE2 安装为 SUSE Edge 堆栈一部分的建议方法是使用 Edge Image Builder (EIB)。有关如何配置 EIB 来部署 RKE2 的更多细节,请参见 EIB 文档(第 9 章 “Edge Image Builder”)。
EIB 足够灵活,支持 RKE2 所需的任何参数(例如指定 RKE2 版本、服务器或代理配置),涵盖所有 Edge 用例。
对于涉及 Metal3 的其他用例,也可以使用和安装 RKE2。在这种特殊情况下,群集 API 提供程序 RKE2 会自动在使用 Edge Stack 通过 Metal3 置备的群集上部署 RKE2。
在这种情况下,必须在涉及的不同 CRD 上应用 RKE2 配置。以下示例说明如何使用
RKE2ControlPlane
CRD 提供不同的 CNI:
apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
metadata:
name: single-node-cluster
namespace: default
spec:
serverConfig:
cni: calico
cniMultusEnable: true
...
有关 Metal3 用例的详细信息,请参见第 8 章 “Metal3”。
14.3.2 高可用性 #
对于 HA 部署,EIB 会自动部署并配置 MetalLB(第 17 章 “MetalLB”)和 Endpoint Copier Operator,以向外部公开 RKE2 API 端点。
14.3.3 网络 #
Edge Stack 支持的 CNI 为 Cilium,您可选择性地添加元插件 Multus,但 RKE2 也支持其他几个插件。
14.3.4 存储 #
RKE2 不提供任何类型的永久存储类或操作器。对于跨多个节点的群集,建议使用 Longhorn(第 15 章 “Longhorn”)。
15 Longhorn #
Longhorn 是专为 Kubernetes 设计的可靠且用户友好的轻量级分布式块存储系统。作为一个开源项目,Longhorn 最初由 Rancher Labs 开发,目前正在由 CNCF 孵化。
15.1 先决条件 #
如果您要学习本指南,事先需要做好以下准备:
至少一台装有 SLE Micro 5.5 的主机,可以是物理主机,也可以是虚拟主机
已安装一个 Kubernetes 群集,可以是 K3s 或 RKE2
Helm
15.2 手动安装 Longhorn #
15.2.1 安装 Open-iSCSI #
要部署并使用 Longhorn,需满足的一项核心要求是安装 open-iscsi
软件包并在所有
Kubernetes 节点上运行 iscsid
守护程序。之所以有此要求,是因为 Longhorn 依赖于主机上的
iscsiadm
来为 Kubernetes 提供永久卷。
我们来安装此软件包:
transactional-update pkg install open-iscsi
请务必注意,在操作完成后,该软件包只会安装到新快照中,因为 SLE Micro 是不可变的操作系统。要加载该软件包并让
iscsid
守护程序开始运行,我们必须重引导至刚刚创建的新快照。准备就绪后,发出 reboot 命令:
reboot
在安装 open-iscsi 时如需更多帮助,请参见官方 Longhorn 文档。
15.2.2 安装 Longhorn #
可通过多种方式在 Kubernetes 群集上安装 Longhorn。本指南将介绍如何通过 Helm 安装,但如果您想要采用其他方法,请按照官方文档操作。
添加 Longhorn Helm 储存库:
helm repo add longhorn https://charts.longhorn.io
从储存库提取最新的 chart:
helm repo update
在 longhorn-system 名称空间中安装 Longhorn:
helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace --version 1.6.1
确认部署是否成功:
kubectl -n longhorn-system get pods
localhost:~ # kubectl -n longhorn-system get pod NAMESPACE NAME READY STATUS RESTARTS AGE longhorn-system longhorn-ui-5fc9fb76db-z5dc9 1/1 Running 0 90s longhorn-system longhorn-ui-5fc9fb76db-dcb65 1/1 Running 0 90s longhorn-system longhorn-manager-wts2v 1/1 Running 1 (77s ago) 90s longhorn-system longhorn-driver-deployer-5d4f79ddd-fxgcs 1/1 Running 0 90s longhorn-system instance-manager-a9bf65a7808a1acd6616bcd4c03d925b 1/1 Running 0 70s longhorn-system engine-image-ei-acb7590c-htqmp 1/1 Running 0 70s longhorn-system csi-attacher-5c4bfdcf59-j8xww 1/1 Running 0 50s longhorn-system csi-provisioner-667796df57-l69vh 1/1 Running 0 50s longhorn-system csi-attacher-5c4bfdcf59-xgd5z 1/1 Running 0 50s longhorn-system csi-provisioner-667796df57-dqkfr 1/1 Running 0 50s longhorn-system csi-attacher-5c4bfdcf59-wckt8 1/1 Running 0 50s longhorn-system csi-resizer-694f8f5f64-7n2kq 1/1 Running 0 50s longhorn-system csi-snapshotter-959b69d4b-rp4gk 1/1 Running 0 50s longhorn-system csi-resizer-694f8f5f64-r6ljc 1/1 Running 0 50s longhorn-system csi-resizer-694f8f5f64-k7429 1/1 Running 0 50s longhorn-system csi-snapshotter-959b69d4b-5k8pg 1/1 Running 0 50s longhorn-system csi-provisioner-667796df57-n5w9s 1/1 Running 0 50s longhorn-system csi-snapshotter-959b69d4b-x7b7t 1/1 Running 0 50s longhorn-system longhorn-csi-plugin-bsc8c 3/3 Running 0 50s
15.3 创建 Longhorn 卷 #
Longhorn 利用名为 StorageClass
的 Kubernetes 资源来自动为 Pod 置备
PersistentVolume
对象。可以将 StorageClass
视为管理员描述其提供的存储类或配置文件的一种方式。
我们需要创建一个采用默认选项的 StorageClass
:
kubectl apply -f - <<EOF kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: longhorn-example provisioner: driver.longhorn.io allowVolumeExpansion: true parameters: numberOfReplicas: "3" staleReplicaTimeout: "2880" # 48 hours in minutes fromBackup: "" fsType: "ext4" EOF
创建 StorageClass
后,我们需要提供一个
PersistentVolumeClaim
来引用它。PersistentVolumeClaim
(PVC) 是用户发出的存储请求。PVC 使用
PersistentVolume
资源。声明可以请求特定的大小和访问模式(例如,可以以读/写模式挂载声明一次,或以只读模式挂载声明多次)。
我们来创建 PersistentVolumeClaim
:
kubectl apply -f - <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: longhorn-volv-pvc namespace: longhorn-system spec: accessModes: - ReadWriteOnce storageClassName: longhorn-example resources: requests: storage: 2Gi EOF
大功告成!创建 PersistentVolumeClaim
后,我们可以继续将其挂接到
Pod
。部署 Pod
时,如果有可用存储,Kubernetes 会创建
Longhorn 卷并将其绑定到 Pod
。
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: volume-test namespace: longhorn-system spec: containers: - name: volume-test image: nginx:stable-alpine imagePullPolicy: IfNotPresent volumeMounts: - name: volv mountPath: /data ports: - containerPort: 80 volumes: - name: volv persistentVolumeClaim: claimName: longhorn-volv-pvc EOF
Kubernetes 中的存储概念是一个复杂但又重要的主题。我们简单地提及了一些最常见的 Kubernetes 资源,不过建议您熟悉 Longhorn 提供的术语文档。
对于此示例,结果应如下所示:
localhost:~ # kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE longhorn (default) driver.longhorn.io Delete Immediate true 12m longhorn-example driver.longhorn.io Delete Immediate true 24s localhost:~ # kubectl get pvc -n longhorn-system NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE longhorn-volv-pvc Bound pvc-f663a92e-ac32-49ae-b8e5-8a6cc29a7d1e 2Gi RWO longhorn-example 54s localhost:~ # kubectl get pods -n longhorn-system NAME READY STATUS RESTARTS AGE csi-attacher-5c4bfdcf59-qmjtz 1/1 Running 0 14m csi-attacher-5c4bfdcf59-s7n65 1/1 Running 0 14m csi-attacher-5c4bfdcf59-w9xgs 1/1 Running 0 14m csi-provisioner-667796df57-fmz2d 1/1 Running 0 14m csi-provisioner-667796df57-p7rjr 1/1 Running 0 14m csi-provisioner-667796df57-w9fdq 1/1 Running 0 14m csi-resizer-694f8f5f64-2rb8v 1/1 Running 0 14m csi-resizer-694f8f5f64-z9v9x 1/1 Running 0 14m csi-resizer-694f8f5f64-zlncz 1/1 Running 0 14m csi-snapshotter-959b69d4b-5dpvj 1/1 Running 0 14m csi-snapshotter-959b69d4b-lwwkv 1/1 Running 0 14m csi-snapshotter-959b69d4b-tzhwc 1/1 Running 0 14m engine-image-ei-5cefaf2b-hvdv5 1/1 Running 0 14m instance-manager-0ee452a2e9583753e35ad00602250c5b 1/1 Running 0 14m longhorn-csi-plugin-gd2jx 3/3 Running 0 14m longhorn-driver-deployer-9f4fc86-j6h2b 1/1 Running 0 15m longhorn-manager-z4lnl 1/1 Running 0 15m longhorn-ui-5f4b7bbf69-bln7h 1/1 Running 3 (14m ago) 15m longhorn-ui-5f4b7bbf69-lh97n 1/1 Running 3 (14m ago) 15m volume-test 1/1 Running 0 26s
15.4 访问 UI #
如果您使用 kubectl 或 Helm 安装了 Longhorn,则需要设置入口控制器,使外部流量能够进入群集。默认不会启用身份验证。如果使用了 Rancher 目录应用程序,Rancher 已自动创建一个提供访问控制的入口控制器 (rancher-proxy)。
获取 Longhorn 的外部服务 IP 地址:
kubectl -n longhorn-system get svc
检索到
longhorn-frontend
IP 地址后,您可以通过在浏览器中导航到该前端来开始使用 UI。
15.5 使用 Edge Image Builder 进行安装 #
SUSE Edge 使用第 9 章 “Edge Image Builder”来自定义基础 SLE Micro 操作系统映像。本节将演示如何执行自定义操作,以置备 RKE2 群集并在其上安装 Longhorn。
我们来创建定义文件:
export CONFIG_DIR=$HOME/eib mkdir -p $CONFIG_DIR cat << EOF > $CONFIG_DIR/iso-definition.yaml apiVersion: 1.0 image: imageType: iso baseImage: SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso arch: x86_64 outputImageName: eib-image.iso kubernetes: version: v1.28.9+rke2r1 helm: charts: - name: longhorn version: 1.6.1 repositoryName: longhorn targetNamespace: longhorn-system createNamespace: true installationNamespace: kube-system repositories: - name: longhorn url: https://charts.longhorn.io operatingSystem: packages: sccRegistrationCode: <reg-code> packageList: - open-iscsi users: - username: root encryptedPassword: \$6\$jHugJNNd3HElGsUZ\$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/ EOF
可以通过 helm.charts[].valuesFile
下提供的独立文件自定义任何 Helm chart
值。有关细节,请参见上游文档。
我们来构建映像:
podman run --rm --privileged -it -v $CONFIG_DIR:/eib registry.suse.com/edge/edge-image-builder:1.0.2 build --definition-file $CONFIG_DIR/iso-definition.yaml
构建映像后,可以使用它在物理主机或虚拟主机上安装操作系统。置备完成后,可以使用 root:eib
身份凭证对登录到系统。
确保 Longhorn 已成功部署:
localhost:~ # /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml -n longhorn-system get pods NAME READY STATUS RESTARTS AGE csi-attacher-5c4bfdcf59-qmjtz 1/1 Running 0 103s csi-attacher-5c4bfdcf59-s7n65 1/1 Running 0 103s csi-attacher-5c4bfdcf59-w9xgs 1/1 Running 0 103s csi-provisioner-667796df57-fmz2d 1/1 Running 0 103s csi-provisioner-667796df57-p7rjr 1/1 Running 0 103s csi-provisioner-667796df57-w9fdq 1/1 Running 0 103s csi-resizer-694f8f5f64-2rb8v 1/1 Running 0 103s csi-resizer-694f8f5f64-z9v9x 1/1 Running 0 103s csi-resizer-694f8f5f64-zlncz 1/1 Running 0 103s csi-snapshotter-959b69d4b-5dpvj 1/1 Running 0 103s csi-snapshotter-959b69d4b-lwwkv 1/1 Running 0 103s csi-snapshotter-959b69d4b-tzhwc 1/1 Running 0 103s engine-image-ei-5cefaf2b-hvdv5 1/1 Running 0 109s instance-manager-0ee452a2e9583753e35ad00602250c5b 1/1 Running 0 109s longhorn-csi-plugin-gd2jx 3/3 Running 0 103s longhorn-driver-deployer-9f4fc86-j6h2b 1/1 Running 0 2m28s longhorn-manager-z4lnl 1/1 Running 0 2m28s longhorn-ui-5f4b7bbf69-bln7h 1/1 Running 3 (2m7s ago) 2m28s longhorn-ui-5f4b7bbf69-lh97n 1/1 Running 3 (2m10s ago) 2m28s
此安装不适用于完全隔离的环境。对于这种情况,请参见第 21.8 节 “Longhorn 安装”。
16 NeuVector #
NeuVector 是适用于 Kubernetes 的安全解决方案,它在统一的软件包中提供 L7 网络安全性、运行时安全性、供应链安全性与合规性检查。
NeuVector 部署为由多个容器组成的平台,这些容器通过各种端口和接口相互通讯。部署的各种容器如下:
管理器:提供基于 Web 的控制台的无状态容器。通常只需一个,可在任何位置运行。管理器发生故障不会影响控制器或执行器的任何操作。但是,某些通知(事件)和最近的连接数据将由管理器缓存在内存中,因此查看这些信息会受到影响。
控制器:NeuVector 的“控制平面”必须部署在 HA 配置中,这样,配置就不会在节点发生故障时丢失。这些容器可在任何位置运行,不过,由于它们的重要性,客户通常会将它们放在“管理”节点、主节点或基础架构节点上。
执行器:此容器部署为 DaemonSet,因此每个要保护的节点上都有一个执行器。通常会部署到每个工作节点,但可为主节点和基础架构节点启用调度,以便将这些容器同时部署到这些节点。注意:如果执行器不在群集节点上,并且连接来自该节点上的 Pod,则 NeuVector 会将这些容器标记为“不受管”工作负载。
扫描器:根据控制器的指示,使用内置 CVE 数据库执行漏洞扫描。可以部署多个扫描器来提高扫描能力。扫描器可在任何位置运行,但通常在运行控制器的节点上运行。请参见下文了解扫描器节点的大小调整注意事项。在用于构建阶段的扫描时,还可以独立调用扫描器,例如,在触发扫描、检索结果和停止扫描器的管道中。扫描器包含最新的 CVE 数据库,因此应每日更新。
更新器:需要更新 CVE 数据库时,更新器会通过 Kubernetes cron 作业触发扫描器的更新。请务必根据您的环境配置此设置。
在此处可以找到更深入的 NeuVector 初始配置信息和最佳实践文档。
16.1 SUSE Edge 如何使用 NeuVector? #
SUSE Edge 提供了精简的 NeuVector 配置作为边缘部署的着手点。
在此处可到找到 NeuVector 配置更改。
16.2 重要注意事项 #
扫描器
容器必须有足够的内存,以便能够将要扫描的映像提取到内存并对其进行扩展。要扫描 1 GB 以上的映像,请将扫描器的内存增加至略高于最大预期映像大小。在保护模式下需要高速网络连接。处于保护(内联防火墙阻止)模式的
执行器
需要占用 CPU 和内存来保持和检查连接以及可能的有效负载 (DLP)。增加内存并专门分配一个 CPU 核心供执行器
使用可确保拥有足够的包过滤能力。
16.3 使用 Edge Image Builder 进行安装 #
SUSE Edge 使用第 9 章 “Edge Image Builder”来自定义基础 SLE Micro 操作系统映像。请按照第 21.7 节 “NeuVector 安装”中所述,在 EIB 置备的 Kubernetes 群集上进行 NeuVector 隔离式安装。
17 MetalLB #
请参见 MetalLB 官方文档。
MetalLB 是使用标准路由协议的裸机 Kubernetes 群集的负载平衡器实现。
在裸机环境中,设置网络负载平衡器比在云环境中要复杂得多。与云设置中的直接 API 调用不同,裸机需要通过专用网络设备或者负载平衡器和虚拟 IP (VIP) 配置的组合,来管理高可用性 (HA) 或解决单节点负载平衡器固有的潜在单一故障点 (SPOF)。这些配置不容易自动化,在组件会动态扩展和缩减的 Kubernetes 部署中带来了挑战。
MetalLB 可以解决这些挑战,因为它利用 Kubernetes 模型创建 LoadBalancer 类型的服务,就如同这些服务是在云环境中运行一样,即使在裸机设置中,也能做到这一点。
为此可以采用两种不同的方法:通过 L2 模式(使用 ARP 技巧)或通过 BGP。大体而言,L2 不需要任何特殊网络设备,但 BGP 通常效果更好。使用哪种方法取决于用例。
17.1 SUSE Edge 如何使用 MetalLB? #
SUSE Edge 通过两种主要方式使用 MetalLB:
作为负载平衡器解决方案:MetalLB 充当裸机的负载平衡器解决方案。
对于 HA K3s/RKE2 设置:MetalLB 允许使用虚拟 IP 地址对 Kubernetes API 进行负载平衡。
为了能够公开 API,会使用 endpoint-copier-operator
将 K8s API
端点从“kubernetes”服务同步到“kubernetes-vip”LoadBalancer 服务。
17.2 最佳实践 #
MetalLB 指南(第 19 章 “K3s 上的 MetalLB(使用 L2)”)中详细介绍了 L2 模式的 MetalLB 安装。
有关在 kube-api-server 前面安装 MetalLB 以实现 HA 设置的指南,请参见“Kubernetes API 服务器前面的 MetalLB”(第 20 章 “Kubernetes API 服务器前面的 MetalLB”)教程。
17.3 已知问题 #
K3S 负载平衡器解决方案:K3S 附带负载平衡器解决方案
Klipper
。要使用 MetalLB,必须禁用 Klipper。为此,可以按照 K3s 文档中所述,使用--disable servicelb
选项启动 K3s 服务器。
18 边缘虚拟化 #
本章介绍如何使用边缘虚拟化在边缘节点上运行虚拟机。必须指出的是,边缘虚拟化并非全面的解决方案,其功能有限;它会尝试解决需要基本虚拟机功能的轻量级虚拟化的要求。SUSE 通过 Harvester 提供更全面的虚拟化(和超融合基础架构)解决方案。
SUSE 边缘虚拟化支持两种虚拟机运行方法:
在主机级别通过 libvirt+qemu-kvm 手动部署虚拟机
部署 KubeVirt 操作器来实现基于 Kubernetes 的虚拟机管理
这两种方法都有效,但下面仅介绍第二种方法。如果您要使用 SLE Micro 现成提供的标准虚拟化机制,可在此处找到详细的指南,尽管该指南主要是针对 SUSE Linux Enterprise Server 编写的,但概念几乎相同。
本指南首先介绍如何将其他虚拟化组件部署到已预先部署的系统,然后使用一个章节介绍如何通过 Edge Image Builder 将此配置嵌入到初始部署中。如果您不想了解基础知识并想要手动完成设置,请直接跳到该章节。
18.1 KubeVirt 概述 #
KubeVirt 让您可以通过 Kubernetes 管理虚拟机及其他容器化工作负载。它通过在容器中运行 Linux 虚拟化堆栈的用户空间部分来实现此目的。这样可以最大程度地降低对主机系统的要求,从而简化设置和管理。
有关 KubeVirt 体系结构的细节,请参见上游文档。
18.2 先决条件 #
如果您要学习本指南,事先需要做好以下准备:
18.3 手动安装边缘虚拟化 #
本指南不会指导您完成 Kubernetes 的部署过程,而是假设您已安装适用于 SUSE Edge 的 K3s 或 RKE2 版本,并已相应地配置了
kubeconfig,以便能够以超级用户身份执行标准的 kubectl
命令。假设您的节点构成单节点群集,不过,此过程与多节点部署预期不会有太大的差异。
具体而言,将通过以下三个独立的 Helm chart 来部署 SUSE 边缘虚拟化:
KubeVirt:核心虚拟化组件,即 Kubernetes CRD、操作器,以及使 Kubernetes 能够部署和管理虚拟机的其他组件。
KubeVirt 仪表板扩展:可选的 Rancher UI 扩展,用于实现基本的虚拟机管理,例如启动/停止虚拟机以及访问控制台。
Containerized Data Importer (CDI):一个附加组件,可为 KubeVirt 实现永久存储集成,使虚拟机能够使用现有 Kubernetes 存储后端来存储数据,同时使用户能够导入或克隆虚拟机的数据卷。
其中的每个 Helm chart 将根据您当前使用的 SUSE Edge 版本进行版本控制。对于生产/支持的用途,请采用 SUSE 注册表中提供的项目。
首先,请确保可以正常进行 kubectl
访问:
$ kubectl get nodes
此命令应会显示如下所示的输出:
NAME STATUS ROLES AGE VERSION node1.edge.rdo.wales Ready control-plane,etcd,master 4h20m v1.28.9+rke2r1 node2.edge.rdo.wales Ready control-plane,etcd,master 4h15m v1.28.9+rke2r1 node3.edge.rdo.wales Ready control-plane,etcd,master 4h15m v1.28.9+rke2r1
现在您可以继续安装 KubeVirt 和 Containerized Data Importer (CDI) Helm chart:
$ helm install kubevirt oci://registry.suse.com/edge/kubevirt-chart --namespace kubevirt-system --create-namespace $ helm install cdi oci://registry.suse.com/edge/cdi-chart --namespace cdi-system --create-namespace
几分钟后,所有 KubeVirt 和 CDI 组件应会部署完成。您可以通过检查 kubevirt-system
和
cdi-system
名称空间中部署的所有资源进行验证。
校验 KubeVirt 资源:
$ kubectl get all -n kubevirt-system
此命令应会显示如下所示的输出:
NAME READY STATUS RESTARTS AGE pod/virt-operator-5fbcf48d58-p7xpm 1/1 Running 0 2m24s pod/virt-operator-5fbcf48d58-wnf6s 1/1 Running 0 2m24s pod/virt-handler-t594x 1/1 Running 0 93s pod/virt-controller-5f84c69884-cwjvd 1/1 Running 1 (64s ago) 93s pod/virt-controller-5f84c69884-xxw6q 1/1 Running 1 (64s ago) 93s pod/virt-api-7dfc54cf95-v8kcl 1/1 Running 1 (59s ago) 118s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubevirt-prometheus-metrics ClusterIP None <none> 443/TCP 2m1s service/virt-api ClusterIP 10.43.56.140 <none> 443/TCP 2m1s service/kubevirt-operator-webhook ClusterIP 10.43.201.121 <none> 443/TCP 2m1s service/virt-exportproxy ClusterIP 10.43.83.23 <none> 443/TCP 2m1s NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/virt-handler 1 1 1 1 1 kubernetes.io/os=linux 93s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/virt-operator 2/2 2 2 2m24s deployment.apps/virt-controller 2/2 2 2 93s deployment.apps/virt-api 1/1 1 1 118s NAME DESIRED CURRENT READY AGE replicaset.apps/virt-operator-5fbcf48d58 2 2 2 2m24s replicaset.apps/virt-controller-5f84c69884 2 2 2 93s replicaset.apps/virt-api-7dfc54cf95 1 1 1 118s NAME AGE PHASE kubevirt.kubevirt.io/kubevirt 2m24s Deployed
校验 CDI 资源:
$ kubectl get all -n cdi-system
此命令应会显示如下所示的输出:
NAME READY STATUS RESTARTS AGE pod/cdi-operator-55c74f4b86-692xb 1/1 Running 0 2m24s pod/cdi-apiserver-db465b888-62lvr 1/1 Running 0 2m21s pod/cdi-deployment-56c7d74995-mgkfn 1/1 Running 0 2m21s pod/cdi-uploadproxy-7d7b94b968-6kxc2 1/1 Running 0 2m22s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/cdi-uploadproxy ClusterIP 10.43.117.7 <none> 443/TCP 2m22s service/cdi-api ClusterIP 10.43.20.101 <none> 443/TCP 2m22s service/cdi-prometheus-metrics ClusterIP 10.43.39.153 <none> 8080/TCP 2m21s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/cdi-operator 1/1 1 1 2m24s deployment.apps/cdi-apiserver 1/1 1 1 2m22s deployment.apps/cdi-deployment 1/1 1 1 2m21s deployment.apps/cdi-uploadproxy 1/1 1 1 2m22s NAME DESIRED CURRENT READY AGE replicaset.apps/cdi-operator-55c74f4b86 1 1 1 2m24s replicaset.apps/cdi-apiserver-db465b888 1 1 1 2m21s replicaset.apps/cdi-deployment-56c7d74995 1 1 1 2m21s replicaset.apps/cdi-uploadproxy-7d7b94b968 1 1 1 2m22s
要校验是否已部署 VirtualMachine
自定义资源定义 (CRD),请使用以下命令:
$ kubectl explain virtualmachine
此命令应会列显 VirtualMachine
对象的定义,如下所示:
GROUP: kubevirt.io KIND: VirtualMachine VERSION: v1 DESCRIPTION: VirtualMachine handles the VirtualMachines that are not running or are in a stopped state The VirtualMachine contains the template to create the VirtualMachineInstance. It also mirrors the running state of the created VirtualMachineInstance in its status. (snip)
18.4 部署虚拟机 #
部署 KubeVirt 和 CDI 后,我们需要基于 openSUSE Tumbleweed 定义一个简单的虚拟机。此虚拟机采用最简单的配置,与任何其他 Pod 一样使用标准的“Pod 网络”进行网络配置。与任何没有 PVC 的容器一样,它也采用非永久存储,因此可确保存储是临时性的。
$ kubectl apply -f - <<EOF apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: tumbleweed namespace: default spec: runStrategy: Always template: spec: domain: devices: {} machine: type: q35 memory: guest: 2Gi resources: {} volumes: - containerDisk: image: registry.opensuse.org/home/roxenham/tumbleweed-container-disk/containerfile/cloud-image:latest name: tumbleweed-containerdisk-0 - cloudInitNoCloud: userDataBase64: I2Nsb3VkLWNvbmZpZwpkaXNhYmxlX3Jvb3Q6IGZhbHNlCnNzaF9wd2F1dGg6IFRydWUKdXNlcnM6CiAgLSBkZWZhdWx0CiAgLSBuYW1lOiBzdXNlCiAgICBncm91cHM6IHN1ZG8KICAgIHNoZWxsOiAvYmluL2Jhc2gKICAgIHN1ZG86ICBBTEw9KEFMTCkgTk9QQVNTV0Q6QUxMCiAgICBsb2NrX3Bhc3N3ZDogRmFsc2UKICAgIHBsYWluX3RleHRfcGFzc3dkOiAnc3VzZScK name: cloudinitdisk EOF
此命令列显的输出应会指出已创建 VirtualMachine
:
virtualmachine.kubevirt.io/tumbleweed created
此 VirtualMachine
定义极其简洁,几乎未指定配置信息。它只是概括性地指明,此计算机的类型为“q35”,具有 2 GB 内存,使用基于临时
containerDisk
的磁盘映像(即,存储在远程映像储存库中某个容器映像内的磁盘映像)。此定义还指定了一个 base64 编码的 cloudInit
磁盘,该磁盘仅用于在引导时创建用户和执行口令(可使用 base64-d
对其进行解码)。
注意此虚拟机映像仅用于测试。该映像不受官方支持,仅用作文档示例。
此虚拟机需要几分钟时间才能完成引导,因为它需要下载 openSUSE Tumbleweed 磁盘映像,但一旦完成此过程,您可以通过检查虚拟机信息来查看有关该虚拟机的更多细节:
$ kubectl get vmi
此命令应会列显启动虚拟机的节点以及虚拟机的 IP 地址。请记住,由于它使用 Pod 网络,因此报告的 IP 地址与任何其他 Pod 一样并且可路由:
NAME AGE PHASE IP NODENAME READY tumbleweed 4m24s Running 10.42.2.98 node3.edge.rdo.wales True
在使用 CNI(例如 Cilium)将流量直接路由到 Pod 的情况下,在 Kubernetes 群集节点本身上运行这些命令时,您应该可以通过
ssh
直接连接到该虚拟机本身。请将下面的 IP 地址替换为分配给您的虚拟机的 IP 地址:
$ ssh suse@10.42.2.98 (password is "suse")
进入此虚拟机后,可对其进行任意操作,但请记住,它的资源有限,磁盘空间只有 1 GB。完成后,请按 Ctrl-D
或输入 exit
断开连接 SSH 会话。
虚拟机进程仍包装在标准 Kubernetes Pod 中。VirtualMachine
CRD
代表所需的虚拟机,但与任何其他应用程序一样,实际启动虚拟机的过程是通过 virt-launcher
Pod(标准 Kubernetes Pod)进行的。对于启动的每个虚拟机,都有一个对应的
virt-launcher
Pod:
$ kubectl get pods
此命令应会针对我们定义的 Tumbleweed 虚拟机显示一个 virt-launcher
Pod:
NAME READY STATUS RESTARTS AGE virt-launcher-tumbleweed-8gcn4 3/3 Running 0 10m
如果深入查看这个 virt-launcher
Pod,您会看到它正在执行
libvirt
和 qemu-kvm
进程。我们可以进入该 Pod
本身并查看其内部工作。请注意您需要根据自己的 Pod 名称修改以下命令:
$ kubectl exec -it virt-launcher-tumbleweed-8gcn4 -- bash
进入 Pod 后,尝试运行 virsh
命令并查看进程。您会看到
qemu-system-x86_64
二进制文件正在运行,以及用于监控虚拟机的某些进程。您还会看到磁盘映像的位置以及网络(作为 tap 设备)的插接方式:
qemu@tumbleweed:/> ps ax PID TTY STAT TIME COMMAND 1 ? Ssl 0:00 /usr/bin/virt-launcher-monitor --qemu-timeout 269s --name tumbleweed --uid b9655c11-38f7-4fa8-8f5d-bfe987dab42c --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kube 12 ? Sl 0:01 /usr/bin/virt-launcher --qemu-timeout 269s --name tumbleweed --uid b9655c11-38f7-4fa8-8f5d-bfe987dab42c --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kubevirt/con 24 ? Sl 0:00 /usr/sbin/virtlogd -f /etc/libvirt/virtlogd.conf 25 ? Sl 0:01 /usr/sbin/virtqemud -f /var/run/libvirt/virtqemud.conf 83 ? Sl 0:31 /usr/bin/qemu-system-x86_64 -name guest=default_tumbleweed,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/run/kubevirt-private/libvirt/qemu/lib/domain-1-default_tumbleweed/master-key.aes"} -machine pc-q35-7.1,usb 286 pts/0 Ss 0:00 bash 320 pts/0 R+ 0:00 ps ax qemu@tumbleweed:/> virsh list --all Id Name State ------------------------------------ 1 default_tumbleweed running qemu@tumbleweed:/> virsh domblklist 1 Target Source --------------------------------------------------------------------------------------------- sda /var/run/kubevirt-ephemeral-disks/disk-data/tumbleweed-containerdisk-0/disk.qcow2 sdb /var/run/kubevirt-ephemeral-disks/cloud-init-data/default/tumbleweed/noCloud.iso qemu@tumbleweed:/> virsh domiflist 1 Interface Type Source Model MAC ------------------------------------------------------------------------------ tap0 ethernet - virtio-non-transitional e6:e9:1a:05:c0:92 qemu@tumbleweed:/> exit exit
最后,我们需要删除此虚拟机以清理资源:
$ kubectl delete vm/tumbleweed virtualmachine.kubevirt.io "tumbleweed" deleted
18.5 使用 virtctl #
除了标准的 Kubernetes CLI 工具 kubectl
之外,KubeVirt 还附带了 CLI
实用程序用于与群集连接,这种连接方式可以弥合虚拟化领域与 Kubernetes
适用领域之间的差距。例如,virtctl
工具提供管理虚拟机生命周期(启动、停止、重启动等)的功能,可用于访问虚拟控制台、上载虚拟机映像,以及与 Kubernetes
构造(例如服务)连接,而无需直接使用 API 或 CRD。
我们来下载最新的稳定版 virtctl
工具:
$ export VERSION=v1.1.0 $ wget https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-linux-amd64
如果您使用的是其他体系结构或非 Linux 计算机,可在此处找到其他版本。需要先将其转换为可执行文件才能继续,将其移动到
$PATH
中的某个位置可能会有帮助:
$ mv virtctl-${VERSION}-linux-amd64 /usr/local/bin/virtctl $ chmod a+x /usr/local/bin/virtctl
然后,可以使用 virtctl
命令行工具创建虚拟机。我们来复制前面创建的虚拟机,请注意我们会通过管道将输出直接传入 kubectl apply
:
$ virtctl create vm --name virtctl-example --memory=1Gi \ --volume-containerdisk=src:registry.opensuse.org/home/roxenham/tumbleweed-container-disk/containerfile/cloud-image:latest \ --cloud-init-user-data "I2Nsb3VkLWNvbmZpZwpkaXNhYmxlX3Jvb3Q6IGZhbHNlCnNzaF9wd2F1dGg6IFRydWUKdXNlcnM6CiAgLSBkZWZhdWx0CiAgLSBuYW1lOiBzdXNlCiAgICBncm91cHM6IHN1ZG8KICAgIHNoZWxsOiAvYmluL2Jhc2gKICAgIHN1ZG86ICBBTEw9KEFMTCkgTk9QQVNTV0Q6QUxMCiAgICBsb2NrX3Bhc3N3ZDogRmFsc2UKICAgIHBsYWluX3RleHRfcGFzc3dkOiAnc3VzZScK" | kubectl apply -f -
此命令应会显示虚拟机正在运行(由于容器映像将被缓存,因此这一次虚拟机的启动速度更快一些):
$ kubectl get vmi NAME AGE PHASE IP NODENAME READY virtctl-example 52s Running 10.42.2.29 node3.edge.rdo.wales True
现在我们可以使用 virtctl
直接连接到该虚拟机:
$ virtctl ssh suse@virtctl-example (password is "suse" - Ctrl-D to exit)
virtctl
还可以使用其他许多命令。例如,如果网络出现故障,您可以使用 virtctl
console
访问串行控制台;可以使用 virtctl guestosinfo
获取详细的操作系统信息,前提是已在 Guest 上安装并运行 qemu-guest-agent
。
最后,我们需要暂停再恢复该虚拟机:
$ virtctl pause vm virtctl-example VMI virtctl-example was scheduled to pause
您会发现,VirtualMachine
对象显示为 Paused,而 VirtualMachineInstance
对象则显示为 Running,但同时显示了 READY=False:
$ kubectl get vm NAME AGE STATUS READY virtctl-example 8m14s Paused False $ kubectl get vmi NAME AGE PHASE IP NODENAME READY virtctl-example 8m15s Running 10.42.2.29 node3.edge.rdo.wales False
您还会发现不再可以连接到该虚拟机:
$ virtctl ssh suse@virtctl-example can't access VMI virtctl-example: Operation cannot be fulfilled on virtualmachineinstance.kubevirt.io "virtctl-example": VMI is paused
我们需要恢复该虚拟机并重试:
$ virtctl unpause vm virtctl-example VMI virtctl-example was scheduled to unpause
现在我们应该可以重新建立连接:
$ virtctl ssh suse@virtctl-example suse@vmi/virtctl-example.default's password: suse@virtctl-example:~> exit logout
最后,我们需要去除该虚拟机:
$ kubectl delete vm/virtctl-example virtualmachine.kubevirt.io "virtctl-example" deleted
18.6 简单入口网络 #
本节介绍如何将虚拟机公开为标准 Kubernetes 服务,并通过 Kubernetes 入口服务(例如 RKE2 中的 NGINX 或 K3s 中的 Traefik)来提供这些虚拟机。本文档假设已正确配置这些组件,并且有一个适当的 DNS 指针指向 Kubernetes 服务器节点或入口虚拟 IP(例如通过通配符来指向),以正确解析入口。
注意在 SUSE Edge 3.0+ 中,如果您在多服务器节点配置中使用 K3s,则可能需要为入口配置基于 MetalLB 的 VIP;对于 RKE2 则不需要这样做。
在示例环境中,部署了另一个 openSUSE Tumbleweed 虚拟机,cloud-init 用于在引导时将 NGINX 安装为简单 Web
服务器,此外,已配置为返回一条简单讯息,以校验在发出调用时该虚拟机是否按预期工作。要了解如何执行此操作,只需对以下输出中的 cloud-init
部分运行 base64 -d
即可。
现在我们来创建此虚拟机:
$ kubectl apply -f - <<EOF apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: ingress-example namespace: default spec: runStrategy: Always template: metadata: labels: app: nginx spec: domain: devices: {} machine: type: q35 memory: guest: 2Gi resources: {} volumes: - containerDisk: image: registry.opensuse.org/home/roxenham/tumbleweed-container-disk/containerfile/cloud-image:latest name: tumbleweed-containerdisk-0 - cloudInitNoCloud: userDataBase64: I2Nsb3VkLWNvbmZpZwpkaXNhYmxlX3Jvb3Q6IGZhbHNlCnNzaF9wd2F1dGg6IFRydWUKdXNlcnM6CiAgLSBkZWZhdWx0CiAgLSBuYW1lOiBzdXNlCiAgICBncm91cHM6IHN1ZG8KICAgIHNoZWxsOiAvYmluL2Jhc2gKICAgIHN1ZG86ICBBTEw9KEFMTCkgTk9QQVNTV0Q6QUxMCiAgICBsb2NrX3Bhc3N3ZDogRmFsc2UKICAgIHBsYWluX3RleHRfcGFzc3dkOiAnc3VzZScKcnVuY21kOgogIC0genlwcGVyIGluIC15IG5naW54CiAgLSBzeXN0ZW1jdGwgZW5hYmxlIC0tbm93IG5naW54CiAgLSBlY2hvICJJdCB3b3JrcyEiID4gL3Nydi93d3cvaHRkb2NzL2luZGV4Lmh0bQo= name: cloudinitdisk EOF
此虚拟机成功启动后,我们可以使用 virtctl
命令公开
VirtualMachineInstance
,其外部端口为
8080
,目标端口为 80
(NGINX 默认侦听此端口)。此处我们之所以使用
virtctl
命令,是因为它能够识别虚拟机对象与 Pod 之间的映射。这为我们创建了新服务:
$ virtctl expose vmi ingress-example --port=8080 --target-port=80 --name=ingress-example Service ingress-example successfully exposed for vmi ingress-example
然后会自动创建一个适当的服务:
$ kubectl get svc/ingress-example NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-example ClusterIP 10.43.217.19 <none> 8080/TCP 9s
接下来,如果您使用 kubectl create ingress
,则可以创建一个指向此服务的 ingress
对象。此处请根据您的 DNS 配置修改 URL(在 ingress
对象中称为“host”),并确保将其指向端口 8080
:
$ kubectl create ingress ingress-example --rule=ingress-example.suse.local/=ingress-example:8080
正确配置 DNS 后,可以立即对 URL 运行 curl 命令:
$ curl ingress-example.suse.local It works!
我们来通过去除此虚拟机及其服务和入口资源进行清理:
$ kubectl delete vm/ingress-example svc/ingress-example ingress/ingress-example virtualmachine.kubevirt.io "ingress-example" deleted service "ingress-example" deleted ingress.networking.k8s.io "ingress-example" deleted
18.7 使用 Rancher UI 扩展 #
SUSE 边缘虚拟化为 Rancher Manager 提供了 UI 扩展,让您可以使用 Rancher 仪表板 UI 进行基本的虚拟机管理。
18.7.1 安装 #
请参见 Rancher 仪表板扩展的相关章节获取安装指导。
18.7.2 使用 KubeVirt Rancher 仪表板扩展 #
该扩展在群集资源管理器中引入了新的 KubeVirt 部分。此部分已添加到装有 KubeVirt 的任何受管群集。
使用该扩展可以直接与以下两个 KubeVirt 资源交互:
虚拟机实例
— 代表单个正在运行的虚拟机实例的资源。虚拟机
— 用于管理虚拟机生命周期的资源。
18.7.2.1 创建虚拟机 #
单击左侧导航栏中已启用 KubeVirt 的受管群集,导航到 Cluster Explorer(群集资源管理器)。
导航到 KubeVirt > Virtual Machines(虚拟机)页面,然后单击屏幕右上角的
Create from YAML
(从 YAML 创建)。填写或粘贴虚拟机定义,然后按
Create
(创建)。使用“部署虚拟机”一节中创建的虚拟机定义作为灵感来源。
18.7.2.2 启动和停止虚拟机 #
使用操作菜单(可通过每个虚拟机右侧的 ⋮ 下拉列表访问)来启动和停止虚拟机,或者选择虚拟机并使用列表顶部的组操作对其执行操作。
只能对定义了 spec.running
属性的虚拟机运行启动和停止操作。如果使用了
spec.runStrategy
,则无法直接启动和停止此类计算机。有关详细信息,请参见 KubeVirt
文档。
18.7.2.3 访问虚拟机控制台 #
“Virtual machines”(虚拟机)列表提供了控制台
下拉列表,用于通过 VNC 或串行控制台连接到虚拟机。此操作仅适用于正在运行的虚拟机。
在某些情况下,需要等待一段时间才能在全新启动的虚拟机上访问控制台。
18.8 使用 Edge Image Builder 进行安装 #
SUSE Edge 使用第 9 章 “Edge Image Builder”来自定义基础 SLE Micro 操作系统映像。请按照第 21.9 节 “KubeVirt 和 CDI 安装”中所述,在 EIB 置备的 Kubernetes 群集上进行 KubeVirt 和 CDI 隔离式安装。
第 III 部分 操作指南 #
操作指南和最佳实践
- 19 K3s 上的 MetalLB(使用 L2)
MetalLB 是使用标准路由协议的裸机 Kubernetes 群集的负载平衡器实现。
- 20 Kubernetes API 服务器前面的 MetalLB
本指南演示如何使用 MetalLB 服务在包含三个控制平面节点的 HA K3s 群集上向外部公开 K3s API。为此,需要手动创建类型为 LoadBalancer 的 Kubernetes 服务,并创建端点。端点保留群集中所有控制平面节点的 IP。为了使端点与群集中发生的事件(添加/去除节点或节点脱机)持续保持同步,需要部署 Endpoint Copier Operator。该操作器监控默认 kubernetes 端点中发生的事件,并自动更新受管服务以使其保持同步。由于受管服务的类型为 LoadBalancer,因此 MetalLB 为其分配了静态 ExternalIP。此 External…
- 21 使用 Edge Image Builder 进行隔离式部署
本指南将介绍如何使用 Edge Image Builder (EIB)(第 9 章 “Edge Image Builder”)在 SLE Micro 5.5 上以完全隔离的方式部署多个 SUSE Edge 组件。使用此方法可以引导至 EIB 所创建的自定义的、随时可引导 (CRB) 的映像,并在 RKE2 或 K3s 群集上部署指定的组件,而无需连接到互联网,也无需执行任何手动步骤。对于想要将部署所需的所有项目预先植入其操作系统映像的客户而言,此配置非常理想,这样就可以在引导时立即使用这些项目。
19 K3s 上的 MetalLB(使用 L2) #
MetalLB 是使用标准路由协议的裸机 Kubernetes 群集的负载平衡器实现。
本指南演示如何以第 2 层模式部署 MetalLB。
19.1 为何使用此方法 #
在第 2 层模式下,一个节点负责向本地网络播发服务。从网络的角度看,似乎为该计算机的网络接口分配了多个 IP 地址。
第 2 层模式的主要优势在于其通用性:它可以在任何以太网上正常工作,不需要任何特殊硬件,甚至不需要各种形式的路由器。
19.2 K3s 上的 MetalLB(使用 L2) #
本快速入门将使用 L2 模式,这意味着我们不需要任何特殊网络设备,而只需设置网络范围内的几个可用 IP(最好是 DHCP 池以外的 IP,因为这些 IP 尚未分配)。
在此示例中,192.168.122.0/24
网络的 DHCP 池为
192.168.122.100-192.168.122.200
(是的,有三个 IP,有关出现额外 IP
的原因,请参见“Traefik 和 MetalLB”一节(第 19.3.3 节 “Traefik 和 MetalLB”)),因此可以使用此范围以外的任何 IP(对于网关和其他可能已运行的主机也是如此!)
19.3 先决条件 #
要在其中部署 MetalLB 的 K3s 群集。
K3S 附带自身的服务负载平衡器(名为 Klipper)。需要禁用 Klipper 才能运行
MetalLB。要禁用 Klipper,需使用 ‑‑disable=servicelb
标志安装
K3s。
Helm
我们的网络范围内有少量多个可用 IP,在本例中为
192.168.122.10-192.168.122.12
19.3.1 部署 #
MetalLB 利用 Helm(及其他方法),因此请运行:
helm repo add metallb https://metallb.github.io/metallb
helm install --create-namespace -n metallb-system metallb metallb/metallb
while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
--timeout=10s; do
sleep 2
done
19.3.2 配置 #
安装现已完成。接下来请使用示例值进行配置:
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ip-pool
namespace: metallb-system
spec:
addresses:
- 192.168.122.10/32
- 192.168.122.11/32
- 192.168.122.12/32
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- ip-pool
EOF
现在,MetalLB 可供您使用。可以自定义 L2 模式的许多设置,例如:
还可以对 BGP 进行其他许多自定义设置。
19.3.3 Traefik 和 MetalLB #
默认情况下,Traefik 会随 K3s 一起部署(可以使用 --disable=traefik
禁用
Traefik),并作为 LoadBalancer
公开(与 Klipper 一起使用)。但是,由于需要禁用
Klipper,用于入口的 Traefik 服务仍是 LoadBalancer
类型。因此在部署 MetalLB
的那一刻,第一个 IP 将自动分配给 Traefik 入口。
# Before deploying MetalLB kubectl get svc -n kube-system traefik NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE traefik LoadBalancer 10.43.44.113 <pending> 80:31093/TCP,443:32095/TCP 28s # After deploying MetalLB kubectl get svc -n kube-system traefik NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE traefik LoadBalancer 10.43.44.113 192.168.122.10 80:31093/TCP,443:32095/TCP 3m10s
我们将在稍后的过程(第 19.4 节 “MetalLB 的入口”)中应用此操作。
19.3.4 用法 #
我们来创建示例部署:
cat <<- EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadata:
name: hello-kubernetes
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: hello-kubernetes
template:
metadata:
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
serviceAccountName: hello-kubernetes
containers:
- name: hello-kubernetes
image: "paulbouwer/hello-kubernetes:1.10"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
env:
- name: HANDLER_PATH_PREFIX
value: ""
- name: RENDER_PATH_PREFIX
value: ""
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: CONTAINER_IMAGE
value: "paulbouwer/hello-kubernetes:1.10"
EOF
最后创建服务:
cat <<- EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: hello-kubernetes
EOF
我们来看看此示例的实际效果:
kubectl get svc -n hello-kubernetes NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-kubernetes LoadBalancer 10.43.127.75 192.168.122.11 80:31461/TCP 8s curl http://192.168.122.11 <!DOCTYPE html> <html> <head> <title>Hello Kubernetes!</title> <link rel="stylesheet" type="text/css" href="/css/main.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" > </head> <body> <div class="main"> <img src="/images/kubernetes.png"/> <div class="content"> <div id="message"> Hello world! </div> <div id="info"> <table> <tr> <th>namespace:</th> <td>hello-kubernetes</td> </tr> <tr> <th>pod:</th> <td>hello-kubernetes-7c8575c848-2c6ps</td> </tr> <tr> <th>node:</th> <td>allinone (Linux 5.14.21-150400.24.46-default)</td> </tr> </table> </div> <div id="footer"> paulbouwer/hello-kubernetes:1.10 (linux/amd64) </div> </div> </div> </body> </html>
19.4 MetalLB 的入口 #
由于 Traefik 已用作入口控制器,我们可以通过 Ingress
对象公开任何 HTTP / HTTPS
流量,例如:
IP=$(kubectl get svc -n kube-system traefik -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cat <<- EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
namespace: hello-kubernetes
spec:
rules:
- host: hellok3s.${IP}.sslip.io
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: hello-kubernetes
port:
name: http
EOF
然后运行:
curl http://hellok3s.${IP}.sslip.io <!DOCTYPE html> <html> <head> <title>Hello Kubernetes!</title> <link rel="stylesheet" type="text/css" href="/css/main.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" > </head> <body> <div class="main"> <img src="/images/kubernetes.png"/> <div class="content"> <div id="message"> Hello world! </div> <div id="info"> <table> <tr> <th>namespace:</th> <td>hello-kubernetes</td> </tr> <tr> <th>pod:</th> <td>hello-kubernetes-7c8575c848-fvqm2</td> </tr> <tr> <th>node:</th> <td>allinone (Linux 5.14.21-150400.24.46-default)</td> </tr> </table> </div> <div id="footer"> paulbouwer/hello-kubernetes:1.10 (linux/amd64) </div> </div> </div> </body> </html>
另外,要校验 MetalLB 是否正常工作,可如下所示使用 arping
:
arping hellok3s.${IP}.sslip.io
预期结果:
ARPING 192.168.64.210 60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=0 time=1.169 msec 60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=1 time=2.992 msec 60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=2 time=2.884 msec
在以上示例中,流量的流动方式如下:
hellok3s.${IP}.sslip.io
解析为实际 IP。然后,流量由
metallb-speaker
Pod 处理。metallb-speaker
将流量重定向到traefik
控制器。最后,Traefik 将请求转发到
hello-kubernetes
服务。
20 Kubernetes API 服务器前面的 MetalLB #
本指南演示如何使用 MetalLB 服务在包含三个控制平面节点的 HA K3s 群集上向外部公开 K3s API。为此,需要手动创建类型为
LoadBalancer
的 Kubernetes 服务,并创建端点。端点保留群集中所有控制平面节点的
IP。为了使端点与群集中发生的事件(添加/去除节点或节点脱机)持续保持同步,需要部署 Endpoint
Copier Operator。该操作器监控默认 kubernetes
端点中发生的事件,并自动更新受管服务以使其保持同步。由于受管服务的类型为 LoadBalancer
,因此
MetalLB
为其分配了静态 ExternalIP
。此
ExternalIP
用于与 API 服务器通讯。
20.1 先决条件 #
要在其上部署 K3s 的三台主机。
请确保这些主机的主机名不同。
对于测试目的,这些主机可以是虚拟机
网络中至少有 2 个可用 IP(一个用于 Traefik,另一个用于受管服务)。
Helm
20.2 安装 K3s #
如果您不想创建新群集,而是想要使用现有群集,请跳过此步骤并转到下一步。
首先,必须在网络中预留一个可用 IP,该 IP 稍后将用作受管服务的 ExternalIP
。
通过 SSH 连接到第一台主机并以群集模式安装 K3s
,如下所示:
# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init \
--disable=servicelb --write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
--tls-san=https://${VIP_SERVICE_IP}.sslip.io" K3S_TOKEN=foobar sh -
确保在 k3s server
命令中提供
--disable=servicelb
标志。
从现在开始,应在本地计算机上运行命令。
要从外部访问 API 服务器,需使用 K3s VM 的 IP。
# Replace <node-ip> with the actual IP of the machine
export NODE_IP=<node-ip>
scp ${NODE_IP}:/etc/rancher/k3s/k3s.yaml ~/.kube/config && sed \
-i '' "s/127.0.0.1/${NODE_IP}/g" ~/.kube/config && chmod 600 ~/.kube/config
20.3 配置现有的 K3s 群集 #
仅当您要使用现有的 K3s 群集时,此步骤才有效。
要使用现有的 K3s 群集,应禁用 servicelb
LB 并修改
tls-san
标志。
要更改 K3s 标志,应在群集中的所有 VM 上修改
/etc/systemd/system/k3s.service
。
标志应插入到 ExecStart
中。例如:
# Replace the <vip-service-ip> with the actual ip ExecStart=/usr/local/bin/k3s \ server \ '--cluster-init' \ '--write-kubeconfig-mode=644' \ '--disable=servicelb' \ '--tls-san=<vip-service-ip>' \ '--tls-san=https://<vip-service-ip>.sslip.io' \
然后应执行以下命令,让 K3s 加载新配置:
systemctl daemon-reload
systemctl restart k3s
20.4 安装 MetalLB #
要部署 MetalLB
,可以使用 K3s 上的
MetalLB 指南。
注意:确保 ip-pool
IPAddressPool 的 IP 地址不与先前为 LoadBalancer
服务选择的 IP 地址重叠。
单独创建一个仅供受管服务使用的 IpAddressPool
。
# Export the VIP_SERVICE_IP on the local machine
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- ${VIP_SERVICE_IP}/32
serviceAllocation:
priority: 100
namespaces:
- default
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- ip-pool
- kubernetes-vip-ip-pool
EOF
20.5 安装 Endpoint Copier Operator #
helm repo add endpoint-copier-operator \
https://suse-edge.github.io/endpoint-copier-operator
helm install --create-namespace -n endpoint-copier-operator \
endpoint-copier-operator endpoint-copier-operator/endpoint-copier-operator
以上命令将在群集中部署三个不同的资源:
包含两个复本的
endpoint-copier-operator
操作器部署。其中一个复本是领导者,另一个复本在需要时接管领导者角色。default
名称空间中名为kubernetes-vip
的 Kubernetes 服务,它是kubernetes
服务的副本,但类型为LoadBalancer
。default
名称空间中名为kubernetes-vip
的端点资源,它是kubernetes
端点的副本。
校验 kubernetes-vip
服务是否使用正确的 IP 地址:
kubectl get service kubernetes-vip -n default \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}'
确保 default
名称空间中的 kubernetes-vip
和
kubernetes
端点资源指向相同的 IP。
kubectl get endpoints kubernetes kubernetes-vip
如果所有设置正确,剩下的最后一项操作就是在 Kubeconfig
中使用
VIP_SERVICE_IP
。
sed -i '' "s/${NODE_IP}/${VIP_SERVICE_IP}/g" ~/.kube/config
从现在开始,所有 kubectl
命令都将通过 kubernetes-vip
服务运行。
20.6 添加控制平面节点 #
要监控整个过程,可以打开另外两个终端选项卡。
第一个终端:
watch kubectl get nodes
第二个终端:
watch kubectl get endpoints
现在,在第二和第三个节点上执行以下命令。
# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
--server https://${VIP_SERVICE_IP}:6443 --disable=servicelb \
--write-kubeconfig-mode=644" K3S_TOKEN=foobar sh -
21 使用 Edge Image Builder 进行隔离式部署 #
21.1 简介 #
本指南将介绍如何使用 Edge Image Builder (EIB)(第 9 章 “Edge Image Builder”)在 SLE Micro 5.5 上以完全隔离的方式部署多个 SUSE Edge 组件。使用此方法可以引导至 EIB 所创建的自定义的、随时可引导 (CRB) 的映像,并在 RKE2 或 K3s 群集上部署指定的组件,而无需连接到互联网,也无需执行任何手动步骤。对于想要将部署所需的所有项目预先植入其操作系统映像的客户而言,此配置非常理想,这样就可以在引导时立即使用这些项目。
本指南将介绍以下组件的隔离式安装:
EIB 将分析并预先下载提供的 Helm chart 和 Kubernetes 清单中引用的所有映像。但是,其中一些操作可能会尝试提取容器映像并在运行时基于这些映像创建 Kubernetes 资源。在这种情况下,如果我们想要设置完全隔离的环境,则必须在定义文件中手动指定所需的映像。
21.2 先决条件 #
我们假设本指南的读者已事先熟悉 EIB(第 9 章 “Edge Image Builder”)。如果您不熟悉,请阅读快速入门指南(第 3 章 “使用 Edge Image Builder 配置独立群集”)来更好地理解以下实践中所述的概念。
21.3 Libvirt 网络配置 #
为了演示隔离式部署,本指南将使用模拟的 libvirt
隔离网络,并根据该网络定制以下配置。对于您自己的部署,可能需要修改下一步骤中将介绍的
host1.local.yaml
配置。
如果您要使用相同的 libvirt
网络配置,请继续阅读。否则请跳到第 21.4 节 “基础目录配置”。
我们来为 DHCP 创建 IP 地址范围为 192.168.100.2/24
的隔离网络配置:
cat << EOF > isolatednetwork.xml <network> <name>isolatednetwork</name> <bridge name='virbr1' stp='on' delay='0'/> <ip address='192.168.100.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.100.2' end='192.168.100.254'/> </dhcp> </ip> </network> EOF
现在,唯一剩下的操作就是创建并启动网络:
virsh net-define isolatednetwork.xml virsh net-start isolatednetwork
21.4 基础目录配置 #
基础目录配置在所有组件中是相同的,现在我们就设置此配置。
首先创建所需的子目录:
export CONFIG_DIR=$HOME/config mkdir -p $CONFIG_DIR/base-images mkdir -p $CONFIG_DIR/network mkdir -p $CONFIG_DIR/kubernetes/helm/values
请确保将您要使用的任何基础映像添加到 base-images
目录中。本指南将重点介绍此处提供的自行安装 ISO 映像。
我们来复制已下载的映像:
cp SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso $CONFIG_DIR/base-images/slemicro.iso
EIB 永远不会修改基础映像输入。
我们来创建一个包含所需网络配置的文件:
cat << EOF > $CONFIG_DIR/network/host1.local.yaml routes: config: - destination: 0.0.0.0/0 metric: 100 next-hop-address: 192.168.100.1 next-hop-interface: eth0 table-id: 254 - destination: 192.168.100.0/24 metric: 100 next-hop-address: next-hop-interface: eth0 table-id: 254 dns-resolver: config: server: - 192.168.100.1 - 8.8.8.8 interfaces: - name: eth0 type: ethernet state: up mac-address: 34:8A:B1:4B:16:E7 ipv4: address: - ip: 192.168.100.50 prefix-length: 24 dhcp: false enabled: true ipv6: enabled: false EOF
此配置确保置备的系统上存在以下设置(使用指定的 MAC 地址):
采用静态 IP 地址的以太网接口
路由
DNS
主机名 (
host1.local
)
生成的文件结构现在应如下所示:
├── kubernetes/ │ └── helm/ │ └── values/ ├── base-images/ │ └── slemicro.iso └── network/ └── host1.local.yaml
21.5 基础定义文件 #
Edge Image Builder 使用定义文件来修改 SLE Micro 映像。这些文件包含大部分可配置选项。其中的许多选项将在不同的组件部分中重复出现,因此下面列出并解释了这些选项。
定义文件中自定义选项的完整列表可以在上游文档中找到
我们来看看所有定义文件中的以下字段:
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
version: v1.28.9+rke2r1
embeddedArtifactRegistry:
images:
- ...
image
部分是必需的,用于指定输入映像、输入映像的体系结构和类型,以及输出映像的名称。
operatingSystem
部分是可选的,其中包含的配置可用于通过
root/eib
用户名/口令登录到置备的系统。
kubernetes
部分是可选的,用于定义 Kubernetes 类型和版本。我们默认将使用
Kubernetes 1.28.9 和 RKE2。如果需要 K3s,请改用 kubernetes.version:
v1.28.9+k3s1
。除非通过 kubernetes.nodes
字段明确配置,否则本指南中引导的所有群集都是单节点群集。
embeddedArtifactRegistry
部分包含仅在运行时为特定组件引用和提取的所有映像。
21.6 Rancher 安装 #
为便于演示,我们将大幅精简演示用的 Rancher(第 4 章 “Rancher”)部署。对于实际部署,可能需要根据您的配置添加其他项目。
Rancher
v2.8.4 版本资产包含 rancher-images.txt
文件,其中列出了隔离式安装所需的所有映像。
总共有大约 602 个容器映像,这意味着,生成的 CRB 映像的大小约为 28GB 以上。对于我们的 Rancher 安装,我们将精简该列表,使之与最小有效配置相当。在该列表中,可以重新添加部署所需的任何映像。
创建定义文件并在其中包含精简的映像列表:
apiVersion: 1.0 image: imageType: iso arch: x86_64 baseImage: slemicro.iso outputImageName: eib-image.iso operatingSystem: users: - username: root encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/ kubernetes: version: v1.28.9+rke2r1 network: apiVIP: 192.168.100.151 manifests: urls: - https://github.com/cert-manager/cert-manager/releases/download/v1.14.2/cert-manager.crds.yaml helm: charts: - name: rancher version: 2.8.4 repositoryName: rancher-prime valuesFile: rancher-values.yaml targetNamespace: cattle-system createNamespace: true installationNamespace: kube-system - name: cert-manager installationNamespace: kube-system createNamespace: true repositoryName: jetstack targetNamespace: cert-manager version: 1.14.2 repositories: - name: jetstack url: https://charts.jetstack.io - name: rancher-prime url: https://charts.rancher.com/server-charts/prime embeddedArtifactRegistry: images: - name: registry.rancher.com/rancher/backup-restore-operator:v4.0.2 - name: registry.rancher.com/rancher/calico-cni:v3.27.0-rancher1 - name: registry.rancher.com/rancher/cis-operator:v1.0.13 - name: registry.rancher.com/rancher/coreos-kube-state-metrics:v1.9.7 - name: registry.rancher.com/rancher/coreos-prometheus-config-reloader:v0.38.1 - name: registry.rancher.com/rancher/coreos-prometheus-operator:v0.38.1 - name: registry.rancher.com/rancher/flannel-cni:v0.3.0-rancher9 - name: registry.rancher.com/rancher/fleet-agent:v0.9.4 - name: registry.rancher.com/rancher/fleet:v0.9.4 - name: registry.rancher.com/rancher/gitjob:v0.9.7 - name: registry.rancher.com/rancher/grafana-grafana:7.1.5 - name: registry.rancher.com/rancher/hardened-addon-resizer:1.8.20-build20240410 - name: registry.rancher.com/rancher/hardened-calico:v3.27.3-build20240423 - name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.8.10-build20240124 - name: registry.rancher.com/rancher/hardened-cni-plugins:v1.4.1-build20240325 - name: registry.rancher.com/rancher/hardened-coredns:v1.11.1-build20240305 - name: registry.rancher.com/rancher/hardened-dns-node-cache:1.22.28-build20240125 - name: registry.rancher.com/rancher/hardened-etcd:v3.5.9-k3s1-build20240418 - name: registry.rancher.com/rancher/hardened-flannel:v0.25.1-build20240423 - name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.7.1-build20240401 - name: registry.rancher.com/rancher/hardened-kubernetes:v1.28.9-rke2r1-build20240416 - name: registry.rancher.com/rancher/hardened-multus-cni:v4.0.2-build20240208 - name: registry.rancher.com/rancher/hardened-node-feature-discovery:v0.14.1-build20230926 - name: registry.rancher.com/rancher/hardened-whereabouts:v0.6.3-build20240208 - name: registry.rancher.com/rancher/helm-project-operator:v0.2.1 - name: registry.rancher.com/rancher/istio-kubectl:1.5.10 - name: registry.rancher.com/rancher/jimmidyson-configmap-reload:v0.3.0 - name: registry.rancher.com/rancher/k3s-upgrade:v1.28.9-k3s1 - name: registry.rancher.com/rancher/klipper-helm:v0.8.3-build20240228 - name: registry.rancher.com/rancher/klipper-lb:v0.4.7 - name: registry.rancher.com/rancher/kube-api-auth:v0.2.1 - name: registry.rancher.com/rancher/kubectl:v1.28.7 - name: registry.rancher.com/rancher/library-nginx:1.19.2-alpine - name: registry.rancher.com/rancher/local-path-provisioner:v0.0.26 - name: registry.rancher.com/rancher/machine:v0.15.0-rancher112 - name: registry.rancher.com/rancher/mirrored-cluster-api-controller:v1.4.4 - name: registry.rancher.com/rancher/nginx-ingress-controller:nginx-1.9.6-rancher1 - name: registry.rancher.com/rancher/pause:3.6 - name: registry.rancher.com/rancher/prom-alertmanager:v0.21.0 - name: registry.rancher.com/rancher/prom-node-exporter:v1.0.1 - name: registry.rancher.com/rancher/prom-prometheus:v2.18.2 - name: registry.rancher.com/rancher/prometheus-auth:v0.2.2 - name: registry.rancher.com/rancher/prometheus-federator:v0.3.4 - name: registry.rancher.com/rancher/pushprox-client:v0.1.0-rancher2-client - name: registry.rancher.com/rancher/pushprox-proxy:v0.1.0-rancher2-proxy - name: registry.rancher.com/rancher/rancher-agent:v2.8.4 - name: registry.rancher.com/rancher/rancher-csp-adapter:v3.0.1 - name: registry.rancher.com/rancher/rancher-webhook:v0.4.5 - name: registry.rancher.com/rancher/rancher:v2.8.4 - name: registry.rancher.com/rancher/rke-tools:v0.1.96 - name: registry.rancher.com/rancher/rke2-cloud-provider:v1.29.3-build20240412 - name: registry.rancher.com/rancher/rke2-runtime:v1.28.9-rke2r1 - name: registry.rancher.com/rancher/rke2-upgrade:v1.28.9-rke2r1 - name: registry.rancher.com/rancher/security-scan:v0.2.15 - name: registry.rancher.com/rancher/shell:v0.1.24 - name: registry.rancher.com/rancher/system-agent-installer-k3s:v1.28.9-k3s1 - name: registry.rancher.com/rancher/system-agent-installer-rke2:v1.28.9-rke2r1 - name: registry.rancher.com/rancher/system-agent:v0.3.6-suc - name: registry.rancher.com/rancher/system-upgrade-controller:v0.13.1 - name: registry.rancher.com/rancher/ui-plugin-catalog:1.3.0 - name: registry.rancher.com/rancher/ui-plugin-operator:v0.1.1 - name: registry.rancher.com/rancher/webhook-receiver:v0.2.5 - name: registry.rancher.com/rancher/kubectl:v1.20.2
与包含 602 个容器映像的完整列表相比,此精简版本仅包含 62 个容器映像,因此新 CRB 映像的大小只有大约 7GB。
我们还需要为 Rancher 创建 Helm values 文件:
cat << EOF > $CONFIG_DIR/kubernetes/helm/values/rancher-values.yaml hostname: 192.168.100.50.sslip.io replicas: 1 bootstrapPassword: "adminadminadmin" systemDefaultRegistry: registry.rancher.com useBundledSystemChart: true EOF
将 systemDefaultRegistry
设置为
registry.rancher.com
可让 Rancher 在引导时,在 CRB
映像内启动的嵌入式项目注册表中自动查找映像。省略此字段可能会导致无法在节点上找到容器映像。
我们来构建映像:
podman run --rm -it --privileged -v $CONFIG_DIR:/eib \ registry.suse.com/edge/edge-image-builder:1.0.2 \ build --definition-file eib-iso-definition.yaml
输出应如下所示:
Generating image customization components... Identifier ................... [SUCCESS] Custom Files ................. [SKIPPED] Time ......................... [SKIPPED] Network ...................... [SUCCESS] Groups ....................... [SKIPPED] Users ........................ [SUCCESS] Proxy ........................ [SKIPPED] Rpm .......................... [SKIPPED] Systemd ...................... [SKIPPED] Elemental .................... [SKIPPED] Suma ......................... [SKIPPED] Downloading file: dl-manifest-1.yaml 100% (437/437 kB, 17 MB/s) Populating Embedded Artifact Registry... 100% (69/69, 26 it/min) Embedded Artifact Registry ... [SUCCESS] Keymap ....................... [SUCCESS] Configuring Kubernetes component... The Kubernetes CNI is not explicitly set, defaulting to 'cilium'. Downloading file: rke2_installer.sh Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (780/780 MB, 115 MB/s) Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (367/367 MB, 108 MB/s) Downloading file: rke2.linux-amd64.tar.gz 100% (34/34 MB, 117 MB/s) Downloading file: sha256sum-amd64.txt 100% (3.9/3.9 kB, 34 MB/s) Downloading file: dl-manifest-1.yaml 100% (437/437 kB, 106 MB/s) Kubernetes ................... [SUCCESS] Certificates ................. [SKIPPED] Building ISO image... Kernel Params ................ [SKIPPED] Image build complete!
置备使用构建映像的节点后,可以校验 Rancher 安装:
/var/lib/rancher/rke2/bin/kubectl get all -A --kubeconfig /etc/rancher/rke2/rke2.yaml
输出应类似于以下内容,这表明已成功部署所有组件:
NAMESPACE NAME READY STATUS RESTARTS AGE cattle-fleet-local-system pod/fleet-agent-68f4d5d5f7-tdlk7 1/1 Running 0 34s cattle-fleet-system pod/fleet-controller-85564cc978-pbtvk 1/1 Running 0 5m51s cattle-fleet-system pod/gitjob-9dc58fb5b-7cwsw 1/1 Running 0 5m51s cattle-provisioning-capi-system pod/capi-controller-manager-5c57b4b8f7-wlp5k 1/1 Running 0 4m52s cattle-system pod/helm-operation-4fk5c 0/2 Completed 0 37s cattle-system pod/helm-operation-6zgbq 0/2 Completed 0 4m54s cattle-system pod/helm-operation-cjds5 0/2 Completed 0 5m37s cattle-system pod/helm-operation-kt5c2 0/2 Completed 0 5m21s cattle-system pod/helm-operation-ppgtw 0/2 Completed 0 5m30s cattle-system pod/helm-operation-tvcwk 0/2 Completed 0 5m54s cattle-system pod/helm-operation-wpxd4 0/2 Completed 0 53s cattle-system pod/rancher-58575f9575-svrg2 1/1 Running 0 6m34s cattle-system pod/rancher-webhook-5c6556f7ff-vgmkt 1/1 Running 0 5m19s cert-manager pod/cert-manager-6c69f9f796-fkm8f 1/1 Running 0 7m14s cert-manager pod/cert-manager-cainjector-584f44558c-wg7p6 1/1 Running 0 7m14s cert-manager pod/cert-manager-webhook-76f9945d6f-lv2nv 1/1 Running 0 7m14s endpoint-copier-operator pod/endpoint-copier-operator-58964b659b-l64dk 1/1 Running 0 7m16s endpoint-copier-operator pod/endpoint-copier-operator-58964b659b-z9t9d 1/1 Running 0 7m16s kube-system pod/cilium-fht55 1/1 Running 0 7m32s kube-system pod/cilium-operator-558bbf6cfd-gwfwf 1/1 Running 0 7m32s kube-system pod/cilium-operator-558bbf6cfd-qsxb5 0/1 Pending 0 7m32s kube-system pod/cloud-controller-manager-host1.local 1/1 Running 0 7m21s kube-system pod/etcd-host1.local 1/1 Running 0 7m8s kube-system pod/helm-install-cert-manager-fvbtt 0/1 Completed 0 8m12s kube-system pod/helm-install-endpoint-copier-operator-5kkgw 0/1 Completed 0 8m12s kube-system pod/helm-install-metallb-zfphb 0/1 Completed 0 8m12s kube-system pod/helm-install-rancher-nc4nt 0/1 Completed 2 8m12s kube-system pod/helm-install-rke2-cilium-7wq87 0/1 Completed 0 8m12s kube-system pod/helm-install-rke2-coredns-nl4gc 0/1 Completed 0 8m12s kube-system pod/helm-install-rke2-ingress-nginx-svjqd 0/1 Completed 0 8m12s kube-system pod/helm-install-rke2-metrics-server-gqgqz 0/1 Completed 0 8m12s kube-system pod/helm-install-rke2-snapshot-controller-crd-r6b5p 0/1 Completed 0 8m12s kube-system pod/helm-install-rke2-snapshot-controller-ss9v4 0/1 Completed 1 8m12s kube-system pod/helm-install-rke2-snapshot-validation-webhook-vlkpn 0/1 Completed 0 8m12s kube-system pod/kube-apiserver-host1.local 1/1 Running 0 7m29s kube-system pod/kube-controller-manager-host1.local 1/1 Running 0 7m30s kube-system pod/kube-proxy-host1.local 1/1 Running 0 7m30s kube-system pod/kube-scheduler-host1.local 1/1 Running 0 7m42s kube-system pod/rke2-coredns-rke2-coredns-6c8d9bb6d-qlwc8 1/1 Running 0 7m31s kube-system pod/rke2-coredns-rke2-coredns-autoscaler-55fb4bbbcf-j5r2z 1/1 Running 0 7m31s kube-system pod/rke2-ingress-nginx-controller-4h2mm 1/1 Running 0 7m3s kube-system pod/rke2-metrics-server-544c8c66fc-lsrc6 1/1 Running 0 7m15s kube-system pod/rke2-snapshot-controller-59cc9cd8f4-4wx75 1/1 Running 0 7m14s kube-system pod/rke2-snapshot-validation-webhook-54c5989b65-5kp2x 1/1 Running 0 7m15s metallb-system pod/metallb-controller-5895d8446d-z54lm 1/1 Running 0 7m15s metallb-system pod/metallb-speaker-fxwgk 1/1 Running 0 7m15s NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cattle-fleet-system service/gitjob ClusterIP 10.43.30.8 <none> 80/TCP 5m51s cattle-provisioning-capi-system service/capi-webhook-service ClusterIP 10.43.7.100 <none> 443/TCP 4m52s cattle-system service/rancher ClusterIP 10.43.100.229 <none> 80/TCP,443/TCP 6m34s cattle-system service/rancher-webhook ClusterIP 10.43.121.133 <none> 443/TCP 5m19s cert-manager service/cert-manager ClusterIP 10.43.140.65 <none> 9402/TCP 7m14s cert-manager service/cert-manager-webhook ClusterIP 10.43.108.158 <none> 443/TCP 7m14s default service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 8m26s default service/kubernetes-vip LoadBalancer 10.43.138.138 192.168.100.151 9345:31006/TCP,6443:31599/TCP 8m21s kube-system service/cilium-agent ClusterIP None <none> 9964/TCP 7m32s kube-system service/rke2-coredns-rke2-coredns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP 7m31s kube-system service/rke2-ingress-nginx-controller-admission ClusterIP 10.43.157.19 <none> 443/TCP 7m3s kube-system service/rke2-metrics-server ClusterIP 10.43.4.123 <none> 443/TCP 7m15s kube-system service/rke2-snapshot-validation-webhook ClusterIP 10.43.91.161 <none> 443/TCP 7m16s metallb-system service/metallb-webhook-service ClusterIP 10.43.71.192 <none> 443/TCP 7m15s NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/cilium 1 1 1 1 1 kubernetes.io/os=linux 7m32s kube-system daemonset.apps/rke2-ingress-nginx-controller 1 1 1 1 1 kubernetes.io/os=linux 7m3s metallb-system daemonset.apps/metallb-speaker 1 1 1 1 1 kubernetes.io/os=linux 7m15s NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE cattle-fleet-local-system deployment.apps/fleet-agent 1/1 1 1 34s cattle-fleet-system deployment.apps/fleet-controller 1/1 1 1 5m51s cattle-fleet-system deployment.apps/gitjob 1/1 1 1 5m51s cattle-provisioning-capi-system deployment.apps/capi-controller-manager 1/1 1 1 4m52s cattle-system deployment.apps/rancher 1/1 1 1 6m34s cattle-system deployment.apps/rancher-webhook 1/1 1 1 5m19s cert-manager deployment.apps/cert-manager 1/1 1 1 7m14s cert-manager deployment.apps/cert-manager-cainjector 1/1 1 1 7m14s cert-manager deployment.apps/cert-manager-webhook 1/1 1 1 7m14s endpoint-copier-operator deployment.apps/endpoint-copier-operator 2/2 2 2 7m16s kube-system deployment.apps/cilium-operator 1/2 2 1 7m32s kube-system deployment.apps/rke2-coredns-rke2-coredns 1/1 1 1 7m31s kube-system deployment.apps/rke2-coredns-rke2-coredns-autoscaler 1/1 1 1 7m31s kube-system deployment.apps/rke2-metrics-server 1/1 1 1 7m15s kube-system deployment.apps/rke2-snapshot-controller 1/1 1 1 7m14s kube-system deployment.apps/rke2-snapshot-validation-webhook 1/1 1 1 7m15s metallb-system deployment.apps/metallb-controller 1/1 1 1 7m15s NAMESPACE NAME DESIRED CURRENT READY AGE cattle-fleet-local-system replicaset.apps/fleet-agent-68f4d5d5f7 1 1 1 34s cattle-fleet-system replicaset.apps/fleet-controller-85564cc978 1 1 1 5m51s cattle-fleet-system replicaset.apps/gitjob-9dc58fb5b 1 1 1 5m51s cattle-provisioning-capi-system replicaset.apps/capi-controller-manager-5c57b4b8f7 1 1 1 4m52s cattle-system replicaset.apps/rancher-58575f9575 1 1 1 6m34s cattle-system replicaset.apps/rancher-webhook-5c6556f7ff 1 1 1 5m19s cert-manager replicaset.apps/cert-manager-6c69f9f796 1 1 1 7m14s cert-manager replicaset.apps/cert-manager-cainjector-584f44558c 1 1 1 7m14s cert-manager replicaset.apps/cert-manager-webhook-76f9945d6f 1 1 1 7m14s endpoint-copier-operator replicaset.apps/endpoint-copier-operator-58964b659b 2 2 2 7m16s kube-system replicaset.apps/cilium-operator-558bbf6cfd 2 2 1 7m32s kube-system replicaset.apps/rke2-coredns-rke2-coredns-6c8d9bb6d 1 1 1 7m31s kube-system replicaset.apps/rke2-coredns-rke2-coredns-autoscaler-55fb4bbbcf 1 1 1 7m31s kube-system replicaset.apps/rke2-metrics-server-544c8c66fc 1 1 1 7m15s kube-system replicaset.apps/rke2-snapshot-controller-59cc9cd8f4 1 1 1 7m14s kube-system replicaset.apps/rke2-snapshot-validation-webhook-54c5989b65 1 1 1 7m15s metallb-system replicaset.apps/metallb-controller-5895d8446d 1 1 1 7m15s NAMESPACE NAME COMPLETIONS DURATION AGE kube-system job.batch/helm-install-cert-manager 1/1 85s 8m21s kube-system job.batch/helm-install-endpoint-copier-operator 1/1 59s 8m21s kube-system job.batch/helm-install-metallb 1/1 60s 8m21s kube-system job.batch/helm-install-rancher 1/1 100s 8m21s kube-system job.batch/helm-install-rke2-cilium 1/1 44s 8m18s kube-system job.batch/helm-install-rke2-coredns 1/1 45s 8m18s kube-system job.batch/helm-install-rke2-ingress-nginx 1/1 76s 8m16s kube-system job.batch/helm-install-rke2-metrics-server 1/1 60s 8m16s kube-system job.batch/helm-install-rke2-snapshot-controller 1/1 61s 8m15s kube-system job.batch/helm-install-rke2-snapshot-controller-crd 1/1 60s 8m16s kube-system job.batch/helm-install-rke2-snapshot-validation-webhook 1/1 60s 8m14s
当我们访问 https://192.168.100.50.sslip.io
并使用先前设置的 adminadminadmin
口令登录后,Rancher 仪表板即会显示:
21.7 NeuVector 安装 #
与 Rancher 安装不同,NeuVector 安装不需要在 EIB 中进行任何特殊处理。EIB 将自动隔离 NeuVector 所需的每个映像。
创建定义文件:
apiVersion: 1.0 image: imageType: iso arch: x86_64 baseImage: slemicro.iso outputImageName: eib-image.iso operatingSystem: users: - username: root encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/ kubernetes: version: v1.28.9+rke2r1 helm: charts: - name: neuvector-crd version: 103.0.3+up2.7.6 repositoryName: rancher-charts targetNamespace: neuvector createNamespace: true installationNamespace: kube-system valuesFile: neuvector-values.yaml - name: neuvector version: 103.0.3+up2.7.6 repositoryName: rancher-charts targetNamespace: neuvector createNamespace: true installationNamespace: kube-system valuesFile: neuvector-values.yaml repositories: - name: rancher-charts url: https://charts.rancher.io/
另外,为 NeuVector 创建 Helm values 文件:
cat << EOF > $CONFIG_DIR/kubernetes/helm/values/neuvector-values.yaml controller: replicas: 1 manager: enabled: false cve: scanner: enabled: false replicas: 1 k3s: enabled: true crdwebhook: enabled: false EOF
我们来构建映像:
podman run --rm -it --privileged -v $CONFIG_DIR:/eib \ registry.suse.com/edge/edge-image-builder:1.0.2 \ build --definition-file eib-iso-definition.yaml
输出应如下所示:
Generating image customization components... Identifier ................... [SUCCESS] Custom Files ................. [SKIPPED] Time ......................... [SKIPPED] Network ...................... [SUCCESS] Groups ....................... [SKIPPED] Users ........................ [SUCCESS] Proxy ........................ [SKIPPED] Rpm .......................... [SKIPPED] Systemd ...................... [SKIPPED] Elemental .................... [SKIPPED] Suma ......................... [SKIPPED] Populating Embedded Artifact Registry... 100% (6/6, 20 it/min) Embedded Artifact Registry ... [SUCCESS] Keymap ....................... [SUCCESS] Configuring Kubernetes component... The Kubernetes CNI is not explicitly set, defaulting to 'cilium'. Downloading file: rke2_installer.sh Kubernetes ................... [SUCCESS] Certificates ................. [SKIPPED] Building ISO image... Kernel Params ................ [SKIPPED] Image build complete!
置备使用构建映像的节点后,可以校验 NeuVector 安装:
/var/lib/rancher/rke2/bin/kubectl get all -n neuvector --kubeconfig /etc/rancher/rke2/rke2.yaml
输出应类似于以下内容,这表明已成功部署所有组件:
NAME READY STATUS RESTARTS AGE pod/neuvector-controller-pod-bc74745cf-x9fsc 1/1 Running 0 13m pod/neuvector-enforcer-pod-vzw7t 1/1 Running 0 13m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/neuvector-svc-admission-webhook ClusterIP 10.43.240.25 <none> 443/TCP 13m service/neuvector-svc-controller ClusterIP None <none> 18300/TCP,18301/TCP,18301/UDP 13m NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/neuvector-enforcer-pod 1 1 1 1 1 <none> 13m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/neuvector-controller-pod 1/1 1 1 13m NAME DESIRED CURRENT READY AGE replicaset.apps/neuvector-controller-pod-bc74745cf 1 1 1 13m NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE cronjob.batch/neuvector-updater-pod 0 0 * * * False 0 <none> 13m
21.8 Longhorn 安装 #
Longhorn 的官方文档包含
longhorn-images.txt
文件,其中列出了隔离式安装所需的所有映像。我们将在定义文件中包含这些映像。我们来创建定义文件:
apiVersion: 1.0 image: imageType: iso arch: x86_64 baseImage: slemicro.iso outputImageName: eib-image.iso operatingSystem: users: - username: root encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/ kubernetes: version: v1.28.9+rke2r1 helm: charts: - name: longhorn repositoryName: longhorn targetNamespace: longhorn-system createNamespace: true version: 1.6.1 repositories: - name: longhorn url: https://charts.longhorn.io embeddedArtifactRegistry: images: - name: longhornio/csi-attacher:v4.4.2 - name: longhornio/csi-provisioner:v3.6.2 - name: longhornio/csi-resizer:v1.9.2 - name: longhornio/csi-snapshotter:v6.3.2 - name: longhornio/csi-node-driver-registrar:v2.9.2 - name: longhornio/livenessprobe:v2.12.0 - name: longhornio/backing-image-manager:v1.6.1 - name: longhornio/longhorn-engine:v1.6.1 - name: longhornio/longhorn-instance-manager:v1.6.1 - name: longhornio/longhorn-manager:v1.6.1 - name: longhornio/longhorn-share-manager:v1.6.1 - name: longhornio/longhorn-ui:v1.6.1 - name: longhornio/support-bundle-kit:v0.0.36
我们来构建映像:
podman run --rm -it --privileged -v $CONFIG_DIR:/eib \ registry.suse.com/edge/edge-image-builder:1.0.2 \ build --definition-file eib-iso-definition.yaml
输出应如下所示:
Generating image customization components... Identifier ................... [SUCCESS] Custom Files ................. [SKIPPED] Time ......................... [SKIPPED] Network ...................... [SUCCESS] Groups ....................... [SKIPPED] Users ........................ [SUCCESS] Proxy ........................ [SKIPPED] Rpm .......................... [SKIPPED] Systemd ...................... [SKIPPED] Elemental .................... [SKIPPED] Suma ......................... [SKIPPED] Populating Embedded Artifact Registry... 100% (13/13, 20 it/min) Embedded Artifact Registry ... [SUCCESS] Keymap ....................... [SUCCESS] Configuring Kubernetes component... The Kubernetes CNI is not explicitly set, defaulting to 'cilium'. Downloading file: rke2_installer.sh Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (782/782 MB, 108 MB/s) Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (367/367 MB, 104 MB/s) Downloading file: rke2.linux-amd64.tar.gz 100% (34/34 MB, 108 MB/s) Downloading file: sha256sum-amd64.txt 100% (3.9/3.9 kB, 7.5 MB/s) Kubernetes ................... [SUCCESS] Certificates ................. [SKIPPED] Building ISO image... Kernel Params ................ [SKIPPED] Image build complete!
置备使用构建映像的节点后,可以校验 Longhorn 安装:
/var/lib/rancher/rke2/bin/kubectl get all -n longhorn-system --kubeconfig /etc/rancher/rke2/rke2.yaml
输出应类似于以下内容,这表明已成功部署所有组件:
NAME READY STATUS RESTARTS AGE pod/csi-attacher-5c4bfdcf59-9hgvv 1/1 Running 0 35s pod/csi-attacher-5c4bfdcf59-dt6jl 1/1 Running 0 35s pod/csi-attacher-5c4bfdcf59-swpwq 1/1 Running 0 35s pod/csi-provisioner-667796df57-dfrzw 1/1 Running 0 35s pod/csi-provisioner-667796df57-tvsrt 1/1 Running 0 35s pod/csi-provisioner-667796df57-xszsx 1/1 Running 0 35s pod/csi-resizer-694f8f5f64-6khlb 1/1 Running 0 35s pod/csi-resizer-694f8f5f64-gnr45 1/1 Running 0 35s pod/csi-resizer-694f8f5f64-sbl4k 1/1 Running 0 35s pod/csi-snapshotter-959b69d4b-2k4v8 1/1 Running 0 35s pod/csi-snapshotter-959b69d4b-9d8wl 1/1 Running 0 35s pod/csi-snapshotter-959b69d4b-l2w95 1/1 Running 0 35s pod/engine-image-ei-5cefaf2b-cwd8f 1/1 Running 0 43s pod/instance-manager-f0d17f96bc92f3cc44787a2a347f6a98 1/1 Running 0 43s pod/longhorn-csi-plugin-szv7t 3/3 Running 0 35s pod/longhorn-driver-deployer-9f4fc86-q8fz2 1/1 Running 0 83s pod/longhorn-manager-zp66l 1/1 Running 0 83s pod/longhorn-ui-5f4b7bbf69-k645d 1/1 Running 3 (65s ago) 83s pod/longhorn-ui-5f4b7bbf69-t7xt4 1/1 Running 3 (62s ago) 83s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/longhorn-admission-webhook ClusterIP 10.43.74.59 <none> 9502/TCP 83s service/longhorn-backend ClusterIP 10.43.45.206 <none> 9500/TCP 83s service/longhorn-conversion-webhook ClusterIP 10.43.83.108 <none> 9501/TCP 83s service/longhorn-engine-manager ClusterIP None <none> <none> 83s service/longhorn-frontend ClusterIP 10.43.84.55 <none> 80/TCP 83s service/longhorn-recovery-backend ClusterIP 10.43.75.200 <none> 9503/TCP 83s service/longhorn-replica-manager ClusterIP None <none> <none> 83s NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/engine-image-ei-5cefaf2b 1 1 1 1 1 <none> 43s daemonset.apps/longhorn-csi-plugin 1 1 1 1 1 <none> 35s daemonset.apps/longhorn-manager 1 1 1 1 1 <none> 83s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/csi-attacher 3/3 3 3 35s deployment.apps/csi-provisioner 3/3 3 3 35s deployment.apps/csi-resizer 3/3 3 3 35s deployment.apps/csi-snapshotter 3/3 3 3 35s deployment.apps/longhorn-driver-deployer 1/1 1 1 83s deployment.apps/longhorn-ui 2/2 2 2 83s NAME DESIRED CURRENT READY AGE replicaset.apps/csi-attacher-5c4bfdcf59 3 3 3 35s replicaset.apps/csi-provisioner-667796df57 3 3 3 35s replicaset.apps/csi-resizer-694f8f5f64 3 3 3 35s replicaset.apps/csi-snapshotter-959b69d4b 3 3 3 35s replicaset.apps/longhorn-driver-deployer-9f4fc86 1 1 1 83s replicaset.apps/longhorn-ui-5f4b7bbf69 2 2 2 83s
21.9 KubeVirt 和 CDI 安装 #
KubeVirt 和 CDI 的 Helm chart 只会安装各自的操作器。余下的系统将由操作器来部署,这意味着,我们必须在定义文件中包含所有必要的容器映像。我们来创建定义文件:
apiVersion: 1.0 image: imageType: iso arch: x86_64 baseImage: slemicro.iso outputImageName: eib-image.iso operatingSystem: users: - username: root encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/ kubernetes: version: v1.28.9+rke2r1 helm: charts: - name: kubevirt-chart repositoryName: suse-edge version: 0.2.4 targetNamespace: kubevirt-system createNamespace: true installationNamespace: kube-system - name: cdi-chart repositoryName: suse-edge version: 0.2.3 targetNamespace: cdi-system createNamespace: true installationNamespace: kube-system repositories: - name: suse-edge url: oci://registry.suse.com/edge embeddedArtifactRegistry: images: - name: registry.suse.com/suse/sles/15.5/cdi-uploadproxy:1.58.0-150500.6.12.1 - name: registry.suse.com/suse/sles/15.5/cdi-uploadserver:1.58.0-150500.6.12.1 - name: registry.suse.com/suse/sles/15.5/cdi-apiserver:1.58.0-150500.6.12.1 - name: registry.suse.com/suse/sles/15.5/cdi-controller:1.58.0-150500.6.12.1 - name: registry.suse.com/suse/sles/15.5/cdi-importer:1.58.0-150500.6.12.1 - name: registry.suse.com/suse/sles/15.5/cdi-cloner:1.58.0-150500.6.12.1 - name: registry.suse.com/suse/sles/15.5/virt-api:1.1.1-150500.8.12.1 - name: registry.suse.com/suse/sles/15.5/virt-controller:1.1.1-150500.8.12.1 - name: registry.suse.com/suse/sles/15.5/virt-launcher:1.1.1-150500.8.12.1 - name: registry.suse.com/suse/sles/15.5/virt-handler:1.1.1-150500.8.12.1 - name: registry.suse.com/suse/sles/15.5/virt-exportproxy:1.1.1-150500.8.12.1 - name: registry.suse.com/suse/sles/15.5/virt-exportserver:1.1.1-150500.8.12.1
我们来构建映像:
podman run --rm -it --privileged -v $CONFIG_DIR:/eib \ registry.suse.com/edge/edge-image-builder:1.0.2 \ build --definition-file eib-iso-definition.yaml
输出应如下所示:
Generating image customization components... Identifier ................... [SUCCESS] Custom Files ................. [SKIPPED] Time ......................... [SKIPPED] Network ...................... [SUCCESS] Groups ....................... [SKIPPED] Users ........................ [SUCCESS] Proxy ........................ [SKIPPED] Rpm .......................... [SKIPPED] Systemd ...................... [SKIPPED] Elemental .................... [SKIPPED] Suma ......................... [SKIPPED] Populating Embedded Artifact Registry... 100% (13/13, 6 it/min) Embedded Artifact Registry ... [SUCCESS] Keymap ....................... [SUCCESS] Configuring Kubernetes component... The Kubernetes CNI is not explicitly set, defaulting to 'cilium'. Downloading file: rke2_installer.sh Kubernetes ................... [SUCCESS] Certificates ................. [SKIPPED] Building ISO image... Kernel Params ................ [SKIPPED] Image build complete!
置备使用构建映像的节点后,可以校验 KubeVirt 和 CDI 的安装。
校验 KubeVirt:
/var/lib/rancher/rke2/bin/kubectl get all -n kubevirt-system --kubeconfig /etc/rancher/rke2/rke2.yaml
输出应类似于以下内容,这表明已成功部署所有组件:
NAME READY STATUS RESTARTS AGE pod/virt-api-7c45477984-z226r 1/1 Running 0 2m4s pod/virt-controller-664d9986b5-8p8gm 1/1 Running 0 98s pod/virt-controller-664d9986b5-v2n4h 1/1 Running 0 98s pod/virt-handler-2fx8c 1/1 Running 0 98s pod/virt-operator-5cf69867dc-hz5s8 1/1 Running 0 2m30s pod/virt-operator-5cf69867dc-kp266 1/1 Running 0 2m30s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubevirt-operator-webhook ClusterIP 10.43.210.235 <none> 443/TCP 2m7s service/kubevirt-prometheus-metrics ClusterIP None <none> 443/TCP 2m7s service/virt-api ClusterIP 10.43.226.140 <none> 443/TCP 2m7s service/virt-exportproxy ClusterIP 10.43.213.201 <none> 443/TCP 2m7s NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/virt-handler 1 1 1 1 1 kubernetes.io/os=linux 98s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/virt-api 1/1 1 1 2m4s deployment.apps/virt-controller 2/2 2 2 98s deployment.apps/virt-operator 2/2 2 2 2m30s NAME DESIRED CURRENT READY AGE replicaset.apps/virt-api-7c45477984 1 1 1 2m4s replicaset.apps/virt-controller-664d9986b5 2 2 2 98s replicaset.apps/virt-operator-5cf69867dc 2 2 2 2m30s
校验 CDI:
/var/lib/rancher/rke2/bin/kubectl get all -n cdi-system --kubeconfig /etc/rancher/rke2/rke2.yaml
输出应类似于以下内容,这表明已成功部署所有组件:
NAME READY STATUS RESTARTS AGE pod/cdi-apiserver-db465b888-mdsmm 1/1 Running 0 3m6s pod/cdi-deployment-56c7d74995-vt9sw 1/1 Running 0 3m6s pod/cdi-operator-55c74f4b86-gkt58 1/1 Running 0 3m10s pod/cdi-uploadproxy-7d7b94b968-msg2h 1/1 Running 0 3m6s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/cdi-api ClusterIP 10.43.161.135 <none> 443/TCP 3m6s service/cdi-prometheus-metrics ClusterIP 10.43.161.159 <none> 8080/TCP 3m6s service/cdi-uploadproxy ClusterIP 10.43.25.136 <none> 443/TCP 3m6s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/cdi-apiserver 1/1 1 1 3m6s deployment.apps/cdi-deployment 1/1 1 1 3m6s deployment.apps/cdi-operator 1/1 1 1 3m10s deployment.apps/cdi-uploadproxy 1/1 1 1 3m6s NAME DESIRED CURRENT READY AGE replicaset.apps/cdi-apiserver-db465b888 1 1 1 3m6s replicaset.apps/cdi-deployment-56c7d74995 1 1 1 3m6s replicaset.apps/cdi-operator-55c74f4b86 1 1 1 3m10s replicaset.apps/cdi-uploadproxy-7d7b94b968 1 1 1 3m6s
21.10 查错 #
如果您在构建映像时遇到任何问题,或者想要进一步测试和调试该过程,请参见上游文档。
第 IV 部分 第三方集成 #
如何集成第三方工具
- 22 NATS
NATS 是为日益发展的超级互联世界而开发的连接技术。仅凭这一项技术,应用程序就能在云供应商、本地、边缘、Web 和移动设备的任意组合之间安全地通讯。NATS 由一系列开源产品组成,这些产品紧密集成,但可以轻松独立部署。NATS 已由全球数千家公司使用,涵盖微服务、边缘计算、移动通讯和 IoT 等用例,并可用于增强或取代传统的讯息交换。
- 23 SLE Micro 上的 NVIDIA GPU
本指南将演示如何通过预构建的开源驱动程序在 SLE Micro 5.5 上实现主机级别的 NVIDIA GPU 支持。这些驱动程序将植入到操作系统中,而不是由 NVIDIA 的 GPU Operator 动态加载。对于想要将部署所需的所有项目预先植入映像,并且不需要动态选择驱动程序版本(即,由用户通过 Kubernetes 选择驱动程序版本)的客户而言,此配置非常理想。本指南首先介绍如何将其他组件部署到已预先部署的系统,然后使用一个章节介绍如何通过 Edge Image Builder 将此配置嵌入到初始部署中。如果您不想了解基础知识并想要手动完成设置,请直接跳到该章节。
22 NATS #
NATS 是为日益发展的超级互联世界而开发的连接技术。仅凭这一项技术,应用程序就能在云供应商、本地、边缘、Web 和移动设备的任意组合之间安全地通讯。NATS 由一系列开源产品组成,这些产品紧密集成,但可以轻松独立部署。NATS 已由全球数千家公司使用,涵盖微服务、边缘计算、移动通讯和 IoT 等用例,并可用于增强或取代传统的讯息交换。
22.1 体系结构 #
NATS 是能够在应用程序之间以讯息形式实现数据交换的基础架构。
22.1.1 NATS 客户端应用程序 #
应用程序可以使用 NATS
客户端库在不同的实例之间发布和订阅讯息,以及发出请求和做出答复。这些应用程序通常称作客户端应用程序
。
22.1.2 NATS 服务基础架构 #
NATS 服务由一个或多个 NATS 服务器进程提供,这些进程配置为彼此互连并提供 NATS 服务基础架构。NATS 服务基础架构可以从一个终端设备上运行的单个 NATS 服务器进程,扩展为由许多群集组成的全球公用超级群集,这些群集跨越所有主要云提供商和全球所有区域。
22.1.3 简单讯息交换设计 #
NATS 使应用程序能够通过发送和接收讯息来轻松进行通讯。这些讯息按照主题字符串进行寻址和标识,并且不依赖于网络位置。数据经过编码,并构造为由发布者发送的讯息。该讯息由一个或多个订阅者接收、解码和处理。
22.1.4 NATS JetStream #
NATS 有一个称为 JetStream 的内置分布式保存系统。JetStream 旨在解决当今技术存在的流式传输问题 — 复杂性、脆弱性和可伸缩性不足的问题。JetStream 还能解决发布者和订阅者之间的耦合问题(订阅者需要启动并运行才能收到发布的讯息)。有关 NATS JetStream 的详细信息,请参见此处。
22.2 安装 #
22.2.1 在 K3s 上安装 NATS #
NATS 是为多种体系结构构建的,因此可以在 K3s 上轻松安装。(第 13 章 “K3s”)
我们创建 values 文件来重写 NATS 的默认值。
cat > values.yaml <<EOF
cluster:
# Enable the HA setup of the NATS
enabled: true
replicas: 3
nats:
jetstream:
# Enable JetStream
enabled: true
memStorage:
enabled: true
size: 2Gi
fileStorage:
enabled: true
size: 1Gi
storageDirectory: /data/
EOF
现在我们需要通过 Helm 安装 NATS:
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
helm install nats nats/nats --namespace nats --values values.yaml \
--create-namespace
在上面创建的 values.yaml
文件中,需将以下组件放在 nats
名称空间中:
HA 版本的 NATS 有状态副本集,其中包含三个容器:NATS 服务器、配置重载器和指标分支。
NATS 箱容器,其中附带一组可用于校验设置的
NATS
实用程序。JetStream 还会利用其键值后端,该后端附带与 Pod 绑定的
PVC
。
22.2.1.1 测试设置 #
kubectl exec -n nats -it deployment/nats-box -- /bin/sh -l
为测试主题创建订阅:
nats sub test &
向测试对象发送讯息:
nats pub test hi
22.2.1.2 清理 #
helm -n nats uninstall nats
rm values.yaml
22.2.2 NATS 用作 K3s 的后端 #
K3s 利用的一个组件是 KINE,它是一个填充码,用于将 etcd 替换为最初面向关系数据库的备用存储后端。由于 JetStream 提供了键值 API,因此可以将 NATS 用作 K3s 群集的后端。
有一个已经合并的 PR 可以直接将内置的 NATS 包含在 K3s 中,但这项更改仍未包含在 K3s 版本中。
出于此原因,应该手动构建 K3s 二进制文件。
本教程使用了 SLE Micro on OSX on Apple Silicon (UTM) VM。
在 OSX PC 上运行以下命令。
22.2.2.1 构建 K3s #
git clone --depth 1 https://github.com/k3s-io/k3s.git && cd k3s
以下命令在构建标记中添加 nats
,以在 K3s 中启用 NATS 内置功能:
sed -i '' 's/TAGS="ctrd/TAGS="nats ctrd/g' scripts/build
make local
请将 <node-ip> 替换为启动 K3s 的节点的实际 IP:
export NODE_IP=<node-ip>
sudo scp dist/artifacts/k3s-arm64 ${NODE_IP}:/usr/local/bin/k3s
在本地构建 K3s 需要 buildx Docker CLI 插件。如果 $ make local
失败,可以手动安装该插件。
22.2.2.2 安装 NATS CLI #
TMPDIR=$(mktemp -d)
nats_version="nats-0.0.35-linux-arm64"
curl -o "${TMPDIR}/nats.zip" -sfL https://github.com/nats-io/natscli/releases/download/v0.0.35/${nats_version}.zip
unzip "${TMPDIR}/nats.zip" -d "${TMPDIR}"
sudo scp ${TMPDIR}/${nats_version}/nats ${NODE_IP}:/usr/local/bin/nats
rm -rf ${TMPDIR}
22.2.2.3 运行用作 K3s 后端的 NATS #
我们需要在节点上通过 ssh
进行连接,并使用指向 nats
的
--datastore-endpoint
标志运行 K3s。
以下命令将 K3s 作为前台进程启动,因此您可以轻松地通过日志来查看是否出现了任何问题。为了不阻碍当前终端,可以在该命令的前面添加
&
标志,以将其作为后台进程启动。
k3s server --datastore-endpoint=nats://
为了将使用 NATS 后端的 K3s 服务器永久保留在您的 slemicro
VM
上,可以运行以下脚本,以创建包含所需配置的 systemd
服务。
export INSTALL_K3S_SKIP_START=false
export INSTALL_K3S_SKIP_DOWNLOAD=true
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
--datastore-endpoint=nats://" sh -
22.2.2.4 查错 #
可以在节点上运行以下命令来校验流中的所有操作是否正常进行:
nats str report -a
nats str view -a
23 SLE Micro 上的 NVIDIA GPU #
23.1 简介 #
本指南将演示如何通过预构建的开源驱动程序在 SLE Micro 5.5 上实现主机级别的 NVIDIA GPU 支持。这些驱动程序将植入到操作系统中,而不是由 NVIDIA 的 GPU Operator 动态加载。对于想要将部署所需的所有项目预先植入映像,并且不需要动态选择驱动程序版本(即,由用户通过 Kubernetes 选择驱动程序版本)的客户而言,此配置非常理想。本指南首先介绍如何将其他组件部署到已预先部署的系统,然后使用一个章节介绍如何通过 Edge Image Builder 将此配置嵌入到初始部署中。如果您不想了解基础知识并想要手动完成设置,请直接跳到该章节。
必须指出的是,这些驱动程序的支持工作由 SUSE 和 NVIDIA 在密切合作的前提下提供,而驱动程序由 SUSE 构建并作为软件包储存库的一部分交付。但是,如果您在使用驱动程序期间在这两方面有任何疑虑或问题,请咨询您的 SUSE 或 NVIDIA 客户经理以获得进一步的帮助。如果您打算使用 NVIDIA AI Enterprise (NVAIE),请确保使用 NVAIE 认证的 GPU,这可能需要使用专有的 NVIDIA 驱动程序。如果您不确定,请咨询您的 NVIDIA 代表。
本指南不会介绍有关 NVIDIA GPU Operator 集成的更多信息。虽然其中不会介绍如何为
Kubernetes 集成 NVIDIA GPU Operator,但您仍然可以按照本指南中的大部分步骤来设置底层操作系统,并通过 NVIDIA GPU
Operator Helm chart 中的 driver.enabled=false
标志来让 GPU
Operator 使用预安装的驱动程序,在这种情况下,GPU Operator
会直接选择主机上安装的驱动程序。NVIDIA 在此处提供了更详细的说明。SUSE
最近还发布了一份技术参考文档
(TRD),其中介绍了如何使用 GPU Operator 和 NVIDIA 专有的驱动程序,您可以根据用例的要求参考此文档。
23.2 先决条件 #
如果您要学习本指南,事先需要做好以下准备:
至少一台装有 SLE Micro 5.5 的主机,可以是物理主机,也可以是虚拟主机。
您的主机已附加到某个订阅,只有这样,才能访问软件包 — 可在此处进行评估。
已安装兼容的 NVIDIA GPU(或完全直通到运行 SLE Micro 的虚拟机)。
root 用户访问权限 — 本章中的说明假设您是 root 用户,而不是通过
sudo
提升了的特权。
23.3 手动安装 #
本节介绍如何直接将 NVIDIA 驱动程序安装到 SLE Micro 操作系统上,因为 NVIDIA 开放驱动程序现在包含在核心 SLE Micro 软件包储存库中,因此,只需安装所需的 RPM 软件包就能安装这些驱动程序。无需编译或下载可执行软件包。下面介绍如何部署支持最新 GPU 的第六代 (G06) 驱动程序(有关更多信息,请参见此处),请选择适合您系统中的 NVIDIA GPU 的驱动程序代系。对于新式 GPU,“G06”驱动程序是最常见的选择。
在开始之前,必须知道的是,除了 SUSE 作为 SLE Micro 一部分交付的 NVIDIA 开放驱动程序之外,您可能还需要将其他 NVIDIA
组件用于设置。这些组件可能包括 OpenGL 库、CUDA 工具包、命令行实用程序(例如
nvidia-smi
)和容器集成组件(例如
nvidia-container-toolkit
)。其中许多组件不是由 SUSE 交付,因为它们是专有的
NVIDIA 软件,或者我们代替 NVIDIA
交付这些软件毫无意义。因此在说明中,我们将配置其他一些用于访问所述组件的储存库,并讲解一些示例来介绍这些工具的用法,以得到一个功能完备的系统。必须能够区分
SUSE 储存库和 NVIDIA 储存库,因为 NVIDIA 提供的软件包版本与 SUSE 构建的版本有时不匹配。这种情况通常发生在 SUSE
推出新的开放驱动程序版本时,需要经过几天时间,NVIDIA 储存库中才会提供匹配的同等软件包。
我们建议您采取以下措施来确保所选驱动程序版本与您的 GPU 兼容并符合现有的任何 CUDA 要求:
查看 CUDA 发行说明
检查您要部署的驱动程序版本是否在 NVIDIA SLE15-SP5 储存库中有匹配的版本,并确保支持组件有可用的同等软件包版本
要查找 NVIDIA 开放驱动程序版本,请在目标计算机上运行 zypper se -s
nvidia-open-driver
,或者在 SLE
Micro 5.5 for x86_64 的 SUSE Customer Center 中搜索“nvidia-open-driver”。
在此处,您会看到四个可用版本,其中 545.29.06 是最新版本:
在确认 NVIDIA 储存库中提供了同等版本后,便可以在主机操作系统上安装软件包了。为此,需要打开
transactional-update
会话,它会创建底层操作系统的新读/写快照,以便我们可以对不可变平台进行更改(有关
transactional-update
的更多说明,请参见此处):
transactional-update shell
在进入 transactional-update
外壳后,从 NVIDIA
添加其他软件包储存库。这样就可以提取其他实用程序,例如 nvidia-smi
:
zypper ar https://download.nvidia.com/suse/sle15sp5/ nvidia-sle15sp5-main zypper --gpg-auto-import-keys refresh
然后,可以安装驱动程序,并安装 nvidia-compute-utils
来获取其他实用程序。如果您不需要这些实用程序,可以忽略其安装,但为了稍后进行测试,最好现在就安装它们:
zypper install -y --auto-agree-with-licenses nvidia-open-driver-G06-signed-kmp nvidia-compute-utils-G06
如果安装失败,可能表明所选驱动程序版本与 NVIDIA
在其储存库中提供的版本之间存在依赖关系不匹配情况。请参见上一节来校验您的版本是否匹配。尝试安装不同的驱动程序版本。例如,如果 NVIDIA
储存库中有较低的版本,您可以尝试在 install 命令中指定
nvidia-open-driver-G06-signed-kmp=545.29.06
,以指定一致的版本。
接下来,如果您未使用支持的 GPU(请记住,可在此处找到列表),可以通过启用模块级别的支持来查看驱动程序是否有效,但每个用户的情况有所不同 - 如果您使用的是支持的 GPU,请跳过此步骤:
sed -i '/NVreg_OpenRmEnableUnsupportedGpus/s/^#//g' /etc/modprobe.d/50-nvidia-default.conf
安装这些软件包后,请退出 transactional-update
会话:
exit
在继续之前,请确保已退出 transactional-update
会话。
安装驱动程序后,接下来请重引导。由于 SLE Micro 是不可变的操作系统,因此它需要重引导至您在上一步骤中创建的新快照。驱动程序只会安装到此新快照中,因此如果不重引导至此新快照(会自动重引导),就无法加载驱动程序。准备就绪后,发出 reboot 命令:
reboot
系统成功重引导后,请重新登录并使用 nvidia-smi
工具校验驱动程序是否已成功加载,以及它是否可以访问和枚举您的 GPU:
nvidia-smi
此命令应显示如下所示的输出,请注意,以下示例中显示了两个 GPU:
Wed Feb 28 12:31:06 2024 +---------------------------------------------------------------------------------------+ | NVIDIA-SMI 545.29.06 Driver Version: 545.29.06 CUDA Version: 12.3 | |-----------------------------------------+----------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+======================+======================| | 0 NVIDIA A100-PCIE-40GB Off | 00000000:17:00.0 Off | 0 | | N/A 29C P0 35W / 250W | 4MiB / 40960MiB | 0% Default | | | | Disabled | +-----------------------------------------+----------------------+----------------------+ | 1 NVIDIA A100-PCIE-40GB Off | 00000000:CA:00.0 Off | 0 | | N/A 30C P0 33W / 250W | 4MiB / 40960MiB | 0% Default | | | | Disabled | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| | No running processes found | +---------------------------------------------------------------------------------------+
在 SLE Micro 系统上安装和校验 NVIDIA 驱动程序的过程到此结束。
23.4 进一步验证手动安装 #
在此阶段,我们只能确认的是,在主机级别,可以访问 NVIDIA
设备,并且驱动程序可以成功加载。但是,如果我们想要确保设备正常运行,可以通过一项简单测试来验证 GPU
是否可以从用户空间应用程序接收指令,最好是通过容器和 CUDA 库接收,因为实际工作负载通常使用这种方法。为此,我们可以通过安装
nvidia-container-toolkit
(NVIDIA
Container Toolkit) 来进一步修改主机操作系统。首先,打开另一个
transactional-update
外壳,请注意,在上一步骤中我们可能是通过单个事务执行了此操作,后面的章节将介绍如何完全自动地执行此操作:
transactional-update shell
接下来,从 NVIDIA Container Toolkit 储存库安装
nvidia-container-toolkit
软件包:
下面的
nvidia-container-toolkit.repo
包含稳定储存库 (nvidia-container-toolkit
) 和实验性储存库 (nvidia-container-toolkit-experimental
)。对于生产用途,建议使用稳定储存库。默认会禁用实验性储存库。
zypper ar https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo zypper --gpg-auto-import-keys install -y nvidia-container-toolkit
准备就绪后,可以退出 transactional-update
外壳:
exit
... 然后将计算机重引导至新快照:
reboot
如前所述,需确保已退出 transactional-update
外壳并重引导计算机,使更改生效。
重引导计算机后,可以校验系统是否可以使用 NVIDIA Container Toolkit 成功枚举设备。输出应该非常详细,包含 INFO 和 WARN 讯息,但不包含 ERROR 讯息:
nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
这会确保计算机上启动的任何容器都可以采用已发现的 NVIDIA GPU 设备。准备就绪后,可以运行基于 podman 的容器。通过
podman
执行此操作可以方便地从容器内部验证对 NVIDIA 设备的访问,稍后还可以自信地对
Kubernetes 执行同样的操作。根据 SLE
BCI,为 podman
授予对上一条命令处理过的带标签 NVIDIA 设备的访问权限,然后直接运行
Bash 命令:
podman run --rm --device nvidia.com/gpu=all --security-opt=label=disable -it registry.suse.com/bci/bci-base:latest bash
现在,您将从临时 podman
容器内部执行命令。该容器无权访问您的底层系统,并且是临时性的,因此我们在此处执行的所有操作都不会保存,并且您无法破坏底层主机上的任何设置。由于我们现在处于容器中,因此可以安装所需的
CUDA 库。请再次对照此页面检查驱动程序的
CUDA 版本是否正确,不过,先前 nvidia-smi
命令的输出应该也会显示所需的 CUDA
版本。以下示例将安装 CUDA 12.3 并提取许多示例、演示和开发包,以便您可以全面验证 GPU:
zypper ar http://developer.download.nvidia.com/compute/cuda/repos/sles15/x86_64/ cuda-sle15-sp5 zypper in -y cuda-libraries-devel-12-3 cuda-minimal-build-12-3 cuda-demo-suite-12-3
成功安装后,请不要退出容器。我们将运行 deviceQuery
CUDA 示例,它会全面验证通过 CUDA
以及从容器本身内部进行 GPU 访问的情况:
/usr/local/cuda-12/extras/demo_suite/deviceQuery
如果成功,您应会看到如下所示的输出,请注意命令结束后返回的 Result = PASS
讯息,并注意在以下输出中,系统正确识别了两个 GPU,而您的环境中可能只有一个 GPU:
/usr/local/cuda-12/extras/demo_suite/deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 2 CUDA Capable device(s) Device 0: "NVIDIA A100-PCIE-40GB" CUDA Driver Version / Runtime Version 12.2 / 12.1 CUDA Capability Major/Minor version number: 8.0 Total amount of global memory: 40339 MBytes (42298834944 bytes) (108) Multiprocessors, ( 64) CUDA Cores/MP: 6912 CUDA Cores GPU Max Clock rate: 1410 MHz (1.41 GHz) Memory Clock rate: 1215 Mhz Memory Bus Width: 5120-bit L2 Cache Size: 41943040 bytes Maximum Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072, 65536), 3D=(16384, 16384, 16384) Maximum Layered 1D Texture Size, (num) layers 1D=(32768), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(32768, 32768), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 2048 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 3 copy engine(s) Run time limit on kernels: No Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Enabled Device supports Unified Addressing (UVA): Yes Device supports Compute Preemption: Yes Supports Cooperative Kernel Launch: Yes Supports MultiDevice Co-op Kernel Launch: Yes Device PCI Domain ID / Bus ID / location ID: 0 / 23 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > Device 1: <snip to reduce output for multiple devices> < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > > Peer access from NVIDIA A100-PCIE-40GB (GPU0) -> NVIDIA A100-PCIE-40GB (GPU1) : Yes > Peer access from NVIDIA A100-PCIE-40GB (GPU1) -> NVIDIA A100-PCIE-40GB (GPU0) : Yes deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 12.3, CUDA Runtime Version = 12.3, NumDevs = 2, Device0 = NVIDIA A100-PCIE-40GB, Device1 = NVIDIA A100-PCIE-40GB Result = PASS
在此处,您可以继续运行任何其他 CUDA 工作负载 — 使用编译器以及 CUDA 生态系统的任何其他方面来运行进一步的测试。完成后,可以退出容器,请注意您在容器中安装的任何内容都是临时性的(因此会丢失!),并且底层操作系统不会受到影响:
exit
23.5 使用 Kubernetes 实现 #
确认已在 SLE Micro 上安装并使用 NVIDIA 开放驱动程序后,我们来了解如何在同一台计算机上配置 Kubernetes。本指南不会指导您部署
Kubernetes,但假设您已安装 K3s 或 RKE2,并且已相应地配置
kubeconfig,以便能够以超级用户的身份执行标准 kubectl
命令。假设您的节点构成了单节点群集,不过,对多节点群集可以使用类似的核心步骤。首先,请确保可以正常进行
kubectl
访问:
kubectl get nodes
此命令应会显示如下所示的输出:
NAME STATUS ROLES AGE VERSION node0001 Ready control-plane,etcd,master 13d v1.28.9+rke2r1
您会发现,k3s/rke2 安装已检测到主机上的 NVIDIA Container Toolkit,并已将 NVIDIA 运行时集成自动配置到
containerd
(k3s/rke2 使用的容器运行时接口)中。这一点可以通过检查 containerd
config.toml
文件来确认:
tail -n8 /var/lib/rancher/rke2/agent/etc/containerd/config.toml
此命令必须显示如下所示的内容。同等的 K3s 位置是
/var/lib/rancher/k3s/agent/etc/containerd/config.toml
:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes."nvidia"] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes."nvidia".options] BinaryName = "/usr/bin/nvidia-container-runtime"
如果未显示这些项,则可能表示检测失败。原因可能是计算机或 Kubernetes 服务未重启动。如果需要,请如前所述手动添加这些项。
接下来,我们需要将作为附加 Kubernetes 运行时的 NVIDIA RuntimeClass
配置为默认设置,以确保需要访问 GPU 的任何用户 Pod 请求都可以按照 containerd
配置中的配置,使用 NVIDIA Container Toolkit 通过
nvidia-container-runtime
进行这种访问:
kubectl apply -f - <<EOF apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: nvidia handler: nvidia EOF
下一步是配置 NVIDIA Device Plugin,该插件会将 Kubernetes 配置为利用 NVIDIA GPU 作为群集中可用的资源,并与 NVIDIA Container Toolkit 配合工作。此工具最初会检测底层主机上的所有功能,包括 GPU、驱动程序和其他功能(例如 GL),然后允许您请求 GPU 资源并将其用作应用程序的一部分。
首先,需要添加并更新 NVIDIA Device Plugin 的 Helm 储存库:
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin helm repo update
现在可以安装 NVIDIA Device Plugin:
helm upgrade -i nvdp nvdp/nvidia-device-plugin --namespace nvidia-device-plugin --create-namespace --version 0.14.5 --set runtimeClassName=nvidia
几分钟后,您会看到一个新的 Pod 正在运行,它将在可用节点上完成检测,并根据检测到的 GPU 数量来标记节点:
kubectl get pods -n nvidia-device-plugin NAME READY STATUS RESTARTS AGE nvdp-nvidia-device-plugin-jp697 1/1 Running 2 (12h ago) 6d3h kubectl get node node0001 -o json | jq .status.capacity { "cpu": "128", "ephemeral-storage": "466889732Ki", "hugepages-1Gi": "0", "hugepages-2Mi": "0", "memory": "32545636Ki", "nvidia.com/gpu": "1", <---- "pods": "110" }
现在,可以创建一个 NVIDIA Pod 来尝试使用此 GPU。我们来尝试在 CUDA 基准容器上执行此操作:
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: nbody-gpu-benchmark namespace: default spec: restartPolicy: OnFailure runtimeClassName: nvidia containers: - name: cuda-container image: nvcr.io/nvidia/k8s/cuda-sample:nbody args: ["nbody", "-gpu", "-benchmark"] resources: limits: nvidia.com/gpu: 1 env: - name: NVIDIA_VISIBLE_DEVICES value: all - name: NVIDIA_DRIVER_CAPABILITIES value: all EOF
如果一切顺利,您可以在日志中看到基准测试信息:
kubectl logs nbody-gpu-benchmark Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance. -fullscreen (run n-body simulation in fullscreen mode) -fp64 (use double precision floating point values for simulation) -hostmem (stores simulation data in host memory) -benchmark (run benchmark to measure performance) -numbodies=<N> (number of bodies (>= 1) to run in simulation) -device=<d> (where d=0,1,2.... for the CUDA device to use) -numdevices=<i> (where i=(number of CUDA devices > 0) to use for simulation) -compare (compares simulation results running once on the default GPU and once on the CPU) -cpu (run n-body simulation on the CPU) -tipsy=<file.bin> (load a tipsy model file for simulation) NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled. > Windowed mode > Simulation data stored in video memory > Single precision floating point simulation > 1 Devices used for simulation GPU Device 0: "Turing" with compute capability 7.5 > Compute 7.5 CUDA device: [Tesla T4] 40960 bodies, total time for 10 iterations: 101.677 ms = 165.005 billion interactions per second = 3300.103 single-precision GFLOP/s at 20 flops per interaction
最后,如果您的应用程序需要 OpenGL,您可以在主机级别安装所需的 NVIDIA OpenGL 库,然后 NVIDIA Device Plugin 和 NVIDIA Container Toolkit 可将这些库提供给容器。为此,请如下所示安装软件包:
transactional-update pkg install nvidia-gl-G06
需要重引导才能将此软件包提供给应用程序。NVIDIA Device Plugin 会通过 NVIDIA Container Toolkit 自动重新检测此软件包。
23.6 通过 Edge Image Builder 将所有组件融合到一起 #
现在您已展示了您的应用程序和 GPU 在 SLE Micro 上的完整功能,接下来可以使用第 9 章 “Edge Image Builder”通过可部署/可使用的 ISO 或 RAW 磁盘映像将它们作为一个整体来提供。本指南不会介绍如何使用 Edge Image Builder,但它提供了构建此类映像所需的配置。下面提供了映像定义的示例以及所需的 Kubernetes 配置文件,以确保可以现成地部署所有必要的组件。下面是该示例的 Edge Image Builder 目录结构:
. ├── base-images │ └── SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso ├── eib-config-iso.yaml ├── kubernetes │ ├── config │ │ └── server.yaml │ ├── helm │ │ └── values │ │ └── nvidia-device-plugin.yaml │ └── manifests │ └── nvidia-runtime-class.yaml └── rpms └── gpg-keys └── nvidia-container-toolkit.key
我们来浏览这些文件。首先,这是一个运行 K3s 的单节点群集的示例映像定义,它还会部署实用程序和 OpenGL 软件包
(eib-config-iso.yaml
):
apiVersion: 1.0
image:
arch: x86_64
imageType: iso
baseImage: SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso
outputImageName: deployimage.iso
operatingSystem:
time:
timezone: Europe/London
ntp:
pools:
- 2.suse.pool.ntp.org
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: $6$XcQN1xkuQKjWEtQG$WbhV80rbveDLJDz1c93K5Ga9JDjt3mF.ZUnhYtsS7uE52FR8mmT8Cnii/JPeFk9jzQO6eapESYZesZHO9EslD1
packages:
packageList:
- nvidia-open-driver-G06-signed-kmp-default
- nvidia-compute-utils-G06
- nvidia-gl-G06
- nvidia-container-toolkit
additionalRepos:
- url: https://download.nvidia.com/suse/sle15sp5/
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
sccRegistrationCode: <snip>
kubernetes:
version: v1.28.9+k3s1
helm:
charts:
- name: nvidia-device-plugin
version: v0.14.5
installationNamespace: kube-system
targetNamespace: nvidia-device-plugin
createNamespace: true
valuesFile: nvidia-device-plugin.yaml
repositoryName: nvidia
repositories:
- name: nvidia
url: https://nvidia.github.io/k8s-device-plugin
这只是一个示例。您可能需要根据自己的要求和期望对其进行自定义。此外,如果使用 SLE Micro,则您需要提供自己的
sccRegistrationCode
来解析软件包依赖项并提取 NVIDIA 驱动程序。
除此之外,还需要添加其他组件,供 Kubernetes 在引导时加载。首先需要为 EIB 目录创建
kubernetes
目录,其中包含配置、Helm chart 值和任何其他所需清单的子目录:
mkdir -p kubernetes/config kubernetes/helm/values kubernetes/manifests
现在我们来通过选择 CNI(如果未选择,则默认为 Cilium)并启用 SELinux 来设置(可选的)Kubernetes 配置:
cat << EOF > kubernetes/config/server.yaml cni: cilium selinux: true EOF
现在确保在 Kubernetes 群集上创建 NVIDIA RuntimeClass:
cat << EOF > kubernetes/manifests/nvidia-runtime-class.yaml apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: nvidia handler: nvidia EOF
我们将使用内置的 Helm 控制器通过 Kubernetes 本身来部署 NVIDIA Device Plugin。我们需要在 chart 的 values 文件中提供运行时类:
cat << EOF > kubernetes/helm/values/nvidia-device-plugin.yaml runtimeClassName: nvidia EOF
在继续之前,我们需要抓取 NVIDIA Container Toolkit RPM 公共密钥:
mkdir -p rpms/gpg-keys curl -o rpms/gpg-keys/nvidia-container-toolkit.key https://nvidia.github.io/libnvidia-container/gpgkey
系统会自动隔离所有必要的项目,包括 Kubernetes 二进制文件、容器映像、Helm
chart(以及所有引用的映像),这意味着在部署时,系统默认不需要互联网连接。现在您只需从 SUSE 下载页面抓取 SLE
Micro ISO(并将其放入 base-images
目录),然后可以调用 Edge Image Builder
工具来生成 ISO。为完成本示例,使用了以下命令来构建映像:
podman run --rm --privileged -it -v /path/to/eib-files/:/eib \ registry.suse.com/edge/edge-image-builder:1.0.2 \ build --definition-file eib-config-iso.yaml
有关更多说明,请参见 Edge Image Builder 的文档。
23.7 解决问题 #
23.7.1 nvidia-smi 找不到 GPU #
使用 dmesg
检查内核讯息。如果讯息指出无法分配
NvKMSKapDevice
,请运用“GPU 不受支持”解决方法:
sed -i '/NVreg_OpenRmEnableUnsupportedGpus/s/^#//g' /etc/modprobe.d/50-nvidia-default.conf
注意:如果您在上述步骤中更改了内核模块配置,则需要重新加载或重引导内核模块才能使更改生效。
第 V 部分 Day 2 操作 #
本章介绍管理员如何在管理群集和下游群集上处理不同的“Day 2”操作任务。
24 管理群集 #
本章介绍如何在管理群集
上执行各种 Day 2
操作。
24.1 RKE2 升级 #
为了确保能够实现灾难恢复,我们建议备份 RKE2
群集数据。有关如何执行此操作的信息,请查看此页面。rke2
二进制文件的默认位置为 /opt/rke2/bin
。
可以使用 RKE2 安装脚本升级 RKE2 版本,如下所示:
curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=vX.Y.Z+rke2rN sh -
安装后请记得重启动 rke2
进程:
# For server nodes:
systemctl restart rke2-server
# For agent nodes:
systemctl restart rke2-agent
为了避免任何不可预见的升级问题,请遵循以下节点升级顺序:
服务器节点 - 应每次升级一个节点。
代理节点 - 应在完成所有服务器节点升级之后进行升级。可以同时升级。
有关更多信息,请参见 RKE2 升级文档。
24.2 操作系统升级 #
本节假设您已将系统注册到 https://scc.suse.com。
SUSE 定期发布新的 SLE Micro
软件包更新。SLE Micro 使用
transactional-upgrade
来检索更新的软件包版本。
transactional-upgrade
提供应用程序和库来以事务方式更新 Linux
操作系统,也就是说,更新将在后台执行,同时系统可以照常继续运行。只有在重引导系统后,更新才会生效。有关更多信息,请参见
transactional-update
GitHub 页面。
要更新系统中的所有软件包,请执行::
transactional-update
由于重引导节点会导致它有一段时间不可用,如果您运行的是多节点群集,可以先封锁并清空节点,然后再重引导。
要封锁节点,请执行::
kubectl cordon <node>
这会导致将该节点移出默认调度机制,以确保不会错误地将任何 Pod 分配到该节点。
要清空节点,请执行::
kubectl drain <node>
这可以确保将该节点上的所有工作负载转移到其他可用节点。
根据您在节点上运行的工作负载,可能还需要在命令中提供其他标志(例如
--delete-emptydir-data
、--ignore-daemonsets
)。
重引导节点:
sudo reboot
成功重引导后,该节点上的软件包将会更新。唯一剩下的操作就是使用 uncordon 命令将该节点放回到默认调度机制。
解封节点::
kubectl uncordon <node>
如果您要撤销更新,请使用以下 transactional-update
命令执行上述步骤:
transactional-update rollback last
24.3 Helm 升级 #
本节假设您已在系统上安装 helm
。有关 helm
安装说明,请查看此页面。
本节介绍如何升级通过 EIB 部署的(第 24.3.1 节 “通过 EIB 部署的 Helm chart”)和不是通过 EIB 部署的(第 24.3.2 节 “不是通过 EIB 部署的 Helm chart”)Helm chart。
24.3.1 通过 EIB 部署的 Helm chart #
EIB 使用 RKE2 的清单自动部署功能来部署其映像定义文件(第 3.3 节 “创建映像定义文件”)中定义的 Helm chart。
要升级以这种方式部署的 chart,需要升级 EIB 在初始化器
节点上的
/var/lib/rancher/rke2/server/manifests
目录下创建的 chart 清单文件。
为了确保能够实现灾难恢复,我们建议您始终备份 chart 清单文件,并按照 chart 提供的任何灾难恢复相关文档进行操作。
要升级 chart 清单文件,请执行以下步骤:
找到
初始化器
节点对于
多节点群集
- 在 EIB 映像定义文件中,应该已经为某个节点指定了initializer: true
属性。如果未指定此属性,则初始化器节点将是节点列表中的第一个服务器节点。对于
单节点群集
- 初始化器是当前正在运行的节点。
通过 SSH 连接到
初始化器
节点:ssh root@<node_ip>
提取 Helm chart:
对于托管在 Helm chart 储存库中的 Helm chart:
helm repo add <chart_repo_name> <chart_repo_urls> helm pull <chart_repo_name>/<chart_name> # Alternatively if you want to pull a specific verison helm pull <chart_repo_name>/<chart_name> --version=X.Y.Z
对于基于 OCI 的 Helm chart:
helm pull oci://<chart_oci_url> # Alternatively if you want to pull a specific verison helm pull oci://<chart_oci_url> --version=X.Y.Z
将提取的
.tgz
存档编码,以便可以将其传递给HelmChart
CR 配置:base64 -w 0 <chart_name>-X.Y.Z.tgz > <chart_name>-X.Y.Z.txt
为要编辑的 chart 清单文件创建副本:
cp /var/lib/rancher/rke2/server/manifests/<chart_name>.yaml ./<chart_name>.yaml
更改
bar.yaml
文件的chartContent
和version
配置:sed -i -e "s|chartContent:.*|chartContent: $(<chart-name-X.Y.Z.txt)|" -e "s|version:.*|version: X.Y.Z|" <chart_name>.yaml
注意如果需要对 chart 进行任何其他升级更改(例如添加新的自定义 chart 值),则需要手动编辑 chart 清单文件。
替换原始 chart 清单文件:
cp <chart_name>.yaml /var/lib/rancher/rke2/server/manifests/
以上命令将触发 Helm chart 升级。升级将由 helm-controller 处理。
要跟踪 Helm chart 的升级,需要查看 helm-controller
为 chart 升级创建的 Pod
的日志。有关详细信息,请参见“示例”(第 24.3.1.1 节 “示例”)一节。
24.3.1.1 示例 #
本节中的示例假设您已找到并连接到初始化器
节点。
本节提供有关如何升级以下 Helm chart 的示例:
Rancher(第 24.3.1.1.1 节 “Rancher 升级”)Helm chart
Metal3(第 24.3.1.1.2 节 “Metal3 升级”)Helm chart
24.3.1.1.1 Rancher 升级 #
为了确保能够实现灾难恢复,我们建议进行 Rancher 备份。有关如何执行此操作的信息,请查看此页面。
此示例说明如何将 Rancher 升级到 2.8.4
版本。
添加
Rancher Prime
Helm 储存库:helm repo add rancher-prime https://charts.rancher.com/server-charts/prime
提取最新的
Rancher Prime
Helm chart 版本:helm pull rancher-prime/rancher --version=2.8.4
将
.tgz
存档编码,以便可以将其传递给HelmChart
CR 配置:base64 -w 0 rancher-2.8.4.tgz > rancher-2.8.4-encoded.txt
为要编辑的
rancher.yaml
文件创建副本:cp /var/lib/rancher/rke2/server/manifests/rancher.yaml ./rancher.yaml
更改
rancher.yaml
文件的chartContent
和version
配置:sed -i -e "s|chartContent:.*|chartContent: $(<rancher-2.8.4-encoded.txt)|" -e "s|version:.*|version: 2.8.4|" rancher.yaml
注意如果需要对 chart 进行任何其他升级更改(例如添加新的自定义 chart 值),则需要手动编辑
rancher.yaml
文件。替换原始
rancher.yaml
文件:cp rancher.yaml /var/lib/rancher/rke2/server/manifests/
要校验是否做出了更新,请执行以下操作:
列出
default
名称空间中的 Pod:kubectl get pods -n default # Example output NAME READY STATUS RESTARTS AGE helm-install-cert-manager-7v7nm 0/1 Completed 0 88m helm-install-rancher-p99k5 0/1 Completed 0 3m21s
查看
helm-install-rancher-*
Pod 的日志:kubectl logs <helm_install_rancher_pod> -n default # Example kubectl logs helm-install-rancher-p99k5 -n default
校验
Rancher
Pod 是否正在运行:kubectl get pods -n cattle-system # Example output NAME READY STATUS RESTARTS AGE helm-operation-mccvd 0/2 Completed 0 3m52s helm-operation-np8kn 0/2 Completed 0 106s helm-operation-q8lf7 0/2 Completed 0 2m53s rancher-648d4fbc6c-qxfpj 1/1 Running 0 5m27s rancher-648d4fbc6c-trdnf 1/1 Running 0 9m57s rancher-648d4fbc6c-wvhbf 1/1 Running 0 9m57s rancher-webhook-649dcc48b4-zqjs7 1/1 Running 0 100s
校验
Rancher
版本是否已升级:kubectl get settings.management.cattle.io server-version # Example output NAME VALUE server-version v2.8.4
24.3.1.1.2 Metal3 升级 #
此示例说明如何将 Metal3 升级到 0.7.1
版本。
提取最新的
Metal3
Helm chart 版本:helm pull oci://registry.suse.com/edge/metal3-chart --version 0.7.1
将
.tgz
存档编码,以便可以将其传递给HelmChart
CR 配置:base64 -w 0 metal3-chart-0.7.1.tgz > metal3-chart-0.7.1-encoded.txt
为要编辑的
Metal3
清单文件创建副本:cp /var/lib/rancher/rke2/server/manifests/metal3.yaml ./metal3.yaml
更改
Metal3
清单文件的chartContent
和version
配置:sed -i -e "s|chartContent:.*|chartContent: $(<metal3-chart-0.7.1-encoded.txt)|" -e "s|version:.*|version: 0.7.1|" metal3.yaml
注意如果需要对 chart 进行任何其他升级更改(例如添加新的自定义 chart 值),则需要手动编辑
metal3.yaml
文件。替换原始
Metal3
清单文件:cp metal3.yaml /var/lib/rancher/rke2/server/manifests/
要校验是否做出了更新,请执行以下操作:
列出
default
名称空间中的 Pod:kubectl get pods -n default # Example output NAME READY STATUS RESTARTS AGE helm-install-metal3-7p7bl 0/1 Completed 0 27s
查看
helm-install-rancher-*
Pod 的日志:kubectl logs <helm_install_rancher_pod> -n default # Example kubectl logs helm-install-metal3-7p7bl -n default
校验
Metal3
Pod 是否正在运行:kubectl get pods -n metal3-system # Example output NAME READY STATUS RESTARTS AGE baremetal-operator-controller-manager-785f99c884-9z87p 2/2 Running 2 (25m ago) 36m metal3-metal3-ironic-96fb66cdd-lkss2 4/4 Running 0 3m54s metal3-metal3-mariadb-55fd44b648-q6zhk 1/1 Running 0 36m
校验
HelmChart
资源版本是否已升级:kubectl get helmchart metal3 -n default # Example output NAME JOB CHART TARGETNAMESPACE VERSION REPO HELMVERSION BOOTSTRAP metal3 helm-install-metal3 metal3-system 0.7.1
24.3.2 不是通过 EIB 部署的 Helm chart #
获取当前正在运行的 Helm chart
.yaml
文件的值,并根据需要对其进行任何更改:helm get values <chart_name> -n <chart_namespace> -o yaml > <chart_name>-values.yaml
更新 Helm chart:
# For charts using a chart repository helm upgrade <chart_name> <chart_repo_name>/<chart_name> \ --namespace <chart_namespace> \ -f <chart_name>-values.yaml \ --version=X.Y.Z # For OCI based charts helm upgrade <chart_name> oci://<oci_registry_url>/<chart_name> \ --namespace <chart_namespace> \ -f <chart_name>-values.yaml \ --version=X.Y.Z
校验 chart 是否已升级。根据具体的 chart,可能需要校验不同的资源。有关 chart 升级示例,请参见“示例”(第 24.3.2.1 节 “示例”)一节。
24.3.2.1 示例 #
本节提供有关如何升级以下 Helm chart 的示例:
Rancher(第 24.3.2.1.1 节 “Rancher”)Helm chart
Metal3(第 24.3.2.1.2 节 “Metal3”)Helm chart
24.3.2.1.1 Rancher #
为了确保能够实现灾难恢复,我们建议进行 Rancher 备份。有关如何执行此操作的信息,请查看此页面。
此示例说明如何将 Rancher 升级到 2.8.4
版本。
获取当前 Rancher 版本的值,并将其列显到
rancher-values.yaml
文件中:helm get values rancher -n cattle-system -o yaml > rancher-values.yaml
更新 Helm chart:
helm upgrade rancher rancher-prime/rancher \ --namespace cattle-system \ -f rancher-values.yaml \ --version=2.8.4
校验
Rancher
版本是否已升级:kubectl get settings.management.cattle.io server-version # Example output NAME VALUE server-version v2.8.4
有关 Rancher Helm chart 升级的详细信息,请查看此页面。
24.3.2.1.2 Metal3 #
此示例说明如何将 Metal3 升级到 0.7.1
版本。
获取当前 Rancher 版本的值,并将其列显到
rancher-values.yaml
文件中:helm get values metal3 -n metal3-system -o yaml > metal3-values.yaml
更新 Helm chart:
helm upgrade metal3 oci://registry.suse.com/edge/metal3-chart \ --namespace metal3-system \ -f metal3-values.yaml \ --version=0.7.1
校验
Metal3
Pod 是否正在运行:kubectl get pods -n metal3-system # Example output NAME READY STATUS RESTARTS AGE baremetal-operator-controller-manager-785f99c884-fvsx4 2/2 Running 0 12m metal3-metal3-ironic-96fb66cdd-j9mgf 4/4 Running 0 2m41s metal3-metal3-mariadb-55fd44b648-7fmvk 1/1 Running 0 12m
校验
Metal3
Helm 版本是否已更改:helm ls -n metal3-system # Expected output NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION metal3 metal3-system 2 2024-06-17 12:43:06.774802846 +0000 UTC deployed metal3-0.7.1 1.16.0
25 下游群集 #
本章介绍如何使用管理群集
对下游群集的不同组件执行各种 Day 2
操作。
25.1 简介 #
本节旨在充当 Day 2
操作文档的起点,在其中可以找到以下信息。
用于在多个下游群集中实现
Day 2
操作的默认组件(第 25.1.1 节 “组件”)。确定要为特定用例使用哪些
Day 2
资源(第 25.1.2 节 “确定您的用例”)。Day 2
操作的建议工作流程顺序(第 25.1.3 节 “Day 2 工作流程”)。
25.1.1 组件 #
下面提供了默认组件的说明,应在管理群集
或下游群集
上设置这些组件,以便可以成功执行
Day 2
操作。
25.1.1.1 Rancher #
如果您要在用例中使用 Fleet(第 6 章 “Fleet”)但不使用 Rancher,则完全可以跳过 Rancher 组件的设置。
Rancher 负责管理您的下游群集
。应将其部署在您的管理群集
上。
有关详细信息,请参见第 4 章 “Rancher”。
25.1.1.2 Fleet #
Fleet 负责多群集资源部署。
通常由 Rancher
组件提供。对于不使用 Rancher
的用例,可将
Fleet 部署为独立组件。
有关将 Fleet 安装为独立组件的详细信息,请参见 Fleet 的安装细节。
有关 Fleet 组件的详细信息,请参见第 6 章 “Fleet”。
本文档主要依赖于 Fleet
,更具体地说,依赖于使用 GitRepo
和捆绑包
资源(有关详细信息,请参见第 25.1.2 节 “确定您的用例”)来通过 GitOps 自动部署与 Day
2
操作相关的资源。
对于需要使用第三方 GitOps 工具的用例,请参见:
对于
操作系统软件包更新
- 第 25.3.4.3 节 “SUC 计划部署 - 第三方 GitOps 工作流程”对于
Kubernetes 发行版升级
- 第 25.4.4.3 节 “SUC 计划部署 - 第三方 GitOps 工作流程”对于
Helm chart 升级
- 从第 33.1 节 “摘要”页面检索所需 Edge 版本支持的 chart 版本,并在第三方 GitOps 工具中填充 chart 版本和 URL
25.1.1.3 系统升级控制器 (SUC) #
系统升级控制器 (SUC)
负责根据通过自定义资源(称为计划
)提供的配置数据在指定节点上执行任务。应将其放置在每个需要执行某种
Day 2
操作的下游群集
上。
有关 SUC 的详细信息,请参见上游储存库。
有关如何在下游群集上部署 SUC 的信息,请先确定您的用例(第 25.1.2 节 “确定您的用例”),然后参见第 25.2.1.1 节 “使用 GitRepo 资源进行 SUC 部署”或第 25.2.1.2 节 “使用捆绑包资源进行 SUC 部署”来了解 SUC 部署信息。
25.1.2 确定您的用例 #
如前所述,与 Day 2
操作相关的资源将通过 Fleet 的
GitRepo
和捆绑包
资源传播到下游群集。
下面提供了有关这些资源的作用,以及应在哪些用例中使用它们来执行 Day 2
操作的详细信息。
25.1.2.1 GitRepo #
GitRepo
是一种 Fleet(第 6 章 “Fleet”)资源,它代表一个 Git 储存库,Fleet
可从中创建捆绑包
。每个捆绑包
是基于
GitRepo
资源中定义的配置路径创建的。有关详细信息,请参见 GitRepo 文档。
就 Day 2
操作而言,GitRepo
资源通常用于在利用
Fleet GitOps 方法的非隔离环境中部署 SUC
或 SUC
计划
。
或者,如果您通过本地 git 服务器镜像储存库设置,则
GitRepo
资源也可用于在隔离环境中部署
SUC
或 SUC 计划
。
25.1.2.2 捆绑包 #
捆绑包
包含了要在目标群集上部署的原始
Kubernetes 资源。通常它们是基于 GitRepo
资源创建的,但在某些用例中也可以手动部署。有关详细信息,请参见捆绑包文档。
就 Day 2
操作而言,捆绑包
资源通常用于在不使用某种形式的本地 GitOps
过程(例如本地 git 服务器)的隔离环境中部署 SUC
或 SUC
计划
。
或者,如果您的用例不允许使用 GitOps 工作流程(例如需使用 Git 储存库),则捆绑包资源也可用于在非隔离环境中部署 SUC
或 SUC
计划
。
25.1.3 Day 2 工作流程 #
下面是在将下游群集升级到特定 Edge 版本时应遵循的 Day 2
工作流程。
操作系统软件包更新(第 25.3 节 “操作系统软件包更新”)
Kubernetes 版本升级(第 25.4 节 “Kubernetes 版本升级”)
Helm chart 升级(第 25.5 节 “Helm chart 升级”)
25.2 系统升级控制器部署指南 #
系统升级控制器 (SUC) 负责根据自定义资源(称为计划)中定义的配置在指定节点上部署资源。有关详细信息,请参见上游文档。
本节只会重点介绍如何部署系统升级控制器
。应根据以下文档部署计划资源:
操作系统软件包更新(第 25.3 节 “操作系统软件包更新”)
Kubernetes 版本升级(第 25.4 节 “Kubernetes 版本升级”)
Helm chart 升级(第 25.5 节 “Helm chart 升级”)
25.2.1 部署 #
本节假设您要使用 Fleet(第 6 章 “Fleet”)来编排 SUC 部署。使用第三方 GitOps 工作流程的用户应参见第 25.2.1.3 节 “使用第三方 GitOps 工作流程时部署系统升级控制器”来了解需要在其工作流程中设置哪些资源。
要确定所要使用的资源,请参见第 25.1.2 节 “确定您的用例”。
25.2.1.1 使用 GitRepo 资源进行 SUC 部署 #
本节介绍如何创建 GitRepo
资源,用于将成功完成 SUC 部署所需的 SUC 计划
传送到目标下游群集。
Edge 团队会在每个 suse-edge/fleet-examples
版本中的
gitrepos/day2/system-upgrade-controller-gitrepo.yaml
下,为
SUC 维护一个随时可用的 GitRepo
资源。
如果您使用 suse-edge/fleet-examples
储存库,请确保使用带有专用版本标记的资源。
可通过以下方式之一创建 GitRepo
:
通过 Rancher UI(第 25.2.1.1.1 节 “GitRepo 部署 - Rancher UI”)(如果
Rancher
可用)通过将资源手动部署(第 25.2.1.1.2 节 “GitRepo 创建 - 手动”)到
管理群集
创建 GitRepo 后,Fleet
将负责拾取资源,并将 SUC 资源部署到所有目标群集。有关如何跟踪部署过程的信息,请参见第 25.2.2.1 节 “监控 SUC 部署”。
25.2.1.1.1 GitRepo 部署 - Rancher UI #
在左上角,选择 ☰ → Continuous Delivery(持续交付)
转到 Git 储存库 → 添加储存库
如果使用 suse-edge/fleet-examples
储存库,请执行以下步骤:
Watch(监视)→ Revision(修订版)- 为要使用的
suse-edge/fleet-examples
储存库选择版本标记,例如release-3.0.1
。在路径下,添加版本标记中显示的系统升级控制器路径 -
fleets/day2/system-upgrade-controller
选择下一步转到目标配置部分
请仅选择您要为其部署
系统升级控制器
的群集。如果您对配置感到满意,请单击创建
或者,如果您决定使用自己的储存库来托管这些文件,则需要提供上述储存库数据。
25.2.1.1.2 GitRepo 创建 - 手动 #
选择您要从中部署 SUC
GitRepo
的所需 Edge 版本标记(在下文中用${REVISION}
表示)。提取 GitRepo 资源:
curl -o system-upgrade-controller-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/{REVISION}/gitrepos/day2/system-upgrade-controller-gitrepo.yaml
编辑 GitRepo 配置,在
spec.targets
下指定所需的目标列表。默认情况下,suse-edge/fleet-examples
中的GitRepo
资源不会映射到任何下游群集。为了匹配所有群集,请将默认的
GitRepo
目标更改为:spec: targets: - clusterSelector: {}
或者,如果您要更细致地选择群集,请参见映射到下游群集
将 GitRepo 资源应用于
管理群集
:kubectl apply -f system-upgrade-controller-gitrepo.yaml
查看
fleet-default
名称空间下创建的 GitRepo 资源:kubectl get gitrepo system-upgrade-controller -n fleet-default # Example output NAME REPO COMMIT BUNDLEDEPLOYMENTS-READY STATUS system-upgrade-controller https://github.com/suse-edge/fleet-examples.git release-3.0.1 0/0
25.2.1.2 使用捆绑包资源进行 SUC 部署 #
本节介绍如何创建捆绑包
资源,用于将成功完成 SUC 部署所需的 SUC 计划
传送到目标下游群集。
Edge 团队会在每个 suse-edge/fleet-examples
版本中的
bundles/day2/system-upgrade-controller/controller-bundle.yaml
下,为 SUC 维护随时可用的捆绑包
资源。
如果您使用 suse-edge/fleet-examples
储存库,请确保使用带有专用版本标记的资源。
可通过以下方式之一创建捆绑包
:
通过 Rancher UI(第 25.2.1.2.1 节 “捆绑包创建 - Rancher UI”)(如果
Rancher
可用)通过将资源手动部署(第 25.2.1.2.2 节 “捆绑包创建 - 手动”)到
管理群集
创建捆绑包后,Fleet
将负责拾取资源,并将 SUC 资源部署到所有目标群集。有关如何跟踪部署过程的信息,请参见第 25.2.2.1 节 “监控 SUC 部署”。
25.2.1.2.1 捆绑包创建 - Rancher UI #
在左上角,选择 ☰ → Continuous Delivery(持续交付)
转到高级 > 捆绑包
选择从 YAML 创建
此处可通过以下方式之一创建捆绑包:
通过手动将文件内容复制到从 YAML 创建页面。可从以下 URL 检索文件内容 - https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/bundles/day2/system-upgrade-controller/controller-bundle.yaml。其中
${REVISION}
是您需要的 Edge 版本标记(例如release-3.0.1
)。通过将
suse-edge/fleet-examples
储存库克隆到所需的版本标记中,并在从 YAML 创建页面中选择从文件读取选项。然后导航到bundles/day2/system-upgrade-controller
目录并选择controller-bundle.yaml
。这会在从 YAML 创建页面中自动填充捆绑包内容。
更改
捆绑包
的目标群集:为了匹配所有下游群集,请将默认的捆绑包
.spec.targets
更改为:spec: targets: - clusterSelector: {}
有关更精细的下游群集映射,请参见映射到下游群集。
创建
25.2.1.2.2 捆绑包创建 - 手动 #
选择您要从中部署 SUC
捆绑包
的所需 Edge 版本标记(在下文中用${REVISION}
表示)。提取捆绑包资源:
curl -o controller-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/bundles/day2/system-upgrade-controller/controller-bundle.yaml
编辑
捆绑包
目标配置,在spec.targets
下提供所需的目标列表。默认情况下,suse-edge/fleet-examples
中的捆绑包
资源不会映射到任何下游群集。为了匹配所有群集,请将默认的
捆绑包
目标更改为:spec: targets: - clusterSelector: {}
或者,如果您要更细致地选择群集,请参见映射到下游群集
将捆绑包资源应用于
管理群集
:kubectl apply -f controller-bundle.yaml
查看
fleet-default
名称空间下创建的捆绑包资源:kubectl get bundles system-upgrade-controller -n fleet-default # Example output NAME BUNDLEDEPLOYMENTS-READY STATUS system-upgrade-controller 0/0
25.2.1.3 使用第三方 GitOps 工作流程时部署系统升级控制器 #
要使用第三方 GitOps
工具部署系统升级控制器
,根据具体使用的工具,您可能需要获取系统升级控制器
Helm chart 和/或 Kubernetes 资源的信息。
选择您要从中使用 SUC 的特定 Edge 版本。
从该页面中,可以在
fleets/day2/system-upgrade-controller/fleet.ymal
文件的
helm
配置部分下找到 SUC Helm
chart 数据。
可以在 SUC 捆绑包
配置中的
.spec.resources.content
下找到 SUC Kubernetes 资源。该捆绑包的位置为
bundles/day2/system-upgrade-controller/controller-bundle.yaml
。
使用上面提到的资源来填充第三方 GitOps 工作流程所需的数据,以部署 SUC。
25.2.2 使用 Rancher 监控 SUC 资源 #
本节介绍如何使用 Rancher UI 监控 SUC 部署生命周期以及任何已部署的 SUC 计划。
25.2.2.1 监控 SUC 部署 #
要检查特定群集的 SUC Pod 日志,请执行以下操作:
25.2.2.2 监控 SUC 计划 #
SUC 计划 Pod 会保持活动状态 15 分钟。此期限过后,创建它们的相应作业会将其去除。要访问 SUC 计划 Pod 日志,应该为群集启用日志记录。有关如何在 Rancher 中执行此操作的信息,请参见 Rancher 与日志记录服务的集成。
要检查特定 SUC 计划的 Pod 日志,请执行以下操作:
在左上角,选择 ☰ → <您的群集名称>
选择工作负载 → Pod
在名称空间下拉菜单中选择
cattle-system
名称空间在 Pod 过滤栏中输入 SUC 计划 Pod 的名称。该名称采用以下模板格式:
apply-<计划名称>-on-<节点名称>
图 25.1︰ Kubernetes 升级计划 Pod 示例 #请注意,在图 1 中,有一个 Pod 处于已完成状态,另有一个 Pod 处于未知状态。这是预料之中的情况,其原因是在节点上执行了 Kubernetes 版本升级。
图 25.2︰ 操作系统软件包更新计划 Pod 示例 #图 25.3︰ HA 群集上 EIB 部署的 Helm chart 的升级计划 Pod 示例 #选择您要查看其日志的 Pod,然后导航到 ⋮ → 查看日志
25.3 操作系统软件包更新 #
25.3.1 组件 #
本节介绍操作系统软件包更新
过程在默认 Day 2
组件(第 25.1.1 节 “组件”)之上使用的自定义组件。
25.3.1.1 edge-update.service #
负责执行操作系统软件包更新
的 Systemd 服务。使用 transactional-update
命令执行发行版升级
(dup
)。
如果您要使用常规升级方法,请在每个节点上的
/etc/edge/
下创建一个 edge-update.conf
文件。在此文件中添加 UPDATE_METHOD=up
变量。
此组件通过 SUC 计划交付,该计划应位于需要进行操作系统软件包更新的每个下游群集上。
25.3.2 要求 #
一般:
已在 SCC 中注册的计算机 - 所有下游群集节点都应已注册到
https://scc.suse.com/
。只有这样,edge-update.service
才能成功连接到所需的操作系统 RPM 储存库。确保 SUC 计划容忍度与节点容忍度相匹配 - 如果您的 Kubernetes 群集节点具有自定义污点,请确保在 SUC 计划中为这些污点添加容忍度。默认情况下,SUC 计划仅包含控制平面节点的容忍度。默认容忍度包括:
CriticalAddonsOnly=true:NoExecute
node-role.kubernetes.io/control-plane:NoSchedule
node-role.kubernetes.io/etcd:NoExecute
注意其他任何容忍度必须添加到每个计划的
.spec.tolerations
部分下。与操作系统软件包更新相关的 SUC 计划可以在 suse-edge/fleet-examples 储存库中的fleets/day2/system-upgrade-controller-plans/os-pkg-update
下找到。请确保使用有效储存库版本标记中的计划。为控制平面 SUC 计划定义自定义容忍度的示例如下:
apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: os-pkg-plan-control-plane spec: ... tolerations: # default tolerations - key: "CriticalAddonsOnly" operator: "Equal" value: "true" effect: "NoExecute" - key: "node-role.kubernetes.io/control-plane" operator: "Equal" effect: "NoSchedule" - key: "node-role.kubernetes.io/etcd" operator: "Equal" effect: "NoExecute" # custom toleration - key: "foo" operator: "Equal" value: "bar" effect: "NoSchedule" ...
隔离:
镜像 SUSE RPM 储存库 - 操作系统 RPM 储存库应在本地镜像,以便
edge-update.service
可以访问它们。可以使用 RMT 实现此目的。
25.3.3 更新过程 #
本节假设您将使用 Fleet(第 6 章 “Fleet”)部署操作系统软件包更新
SUC 计划。如果您打算使用其他方法部署 SUC
计划,请参见第 25.3.4.3 节 “SUC 计划部署 - 第三方 GitOps 工作流程”。
操作系统软件包更新过程
主要围绕着将 SUC
计划部署到下游群集来进行。然后,这些计划将包含有关如何以及在哪些节点上部署
edge-update.service
systemd.service 的信息。有关 SUC 计划结构的信息,请参见上游文档。
操作系统软件包更新
SUC 计划通过以下方式交付:
通过
GitRepo
资源 - 第 25.3.4.1 节 “SUC 计划部署 - GitRepo 资源”通过
捆绑包
资源 - 第 25.3.4.2 节 “SUC 计划部署 - 捆绑包资源”
要确定使用哪个资源,请参见第 25.1.2 节 “确定您的用例”。
有关更新过程中会发生哪些情况的完整概述,请参见第 25.3.3.1 节 “概述”一节。
25.3.3.1 概述 #
本节旨在介绍操作系统软件包更新过程从头到尾的完整工作流程。
操作系统软件包更新步骤:
用户可以根据用例,确定是要使用 GitRepo 还是捆绑包资源将
操作系统软件包更新 SUC 计划
部署到所需的下游群集。有关如何将 GitRepo/捆绑包映射到特定的一组下游群集的信息,请参见映射到下游群集。如果您不确定是要使用 GitRepo 还是捆绑包资源进行 SUC 计划部署,请参见第 25.1.2 节 “确定您的用例”。
有关 GitRepo/捆绑包配置选项,请参见第 25.3.4.1 节 “SUC 计划部署 - GitRepo 资源”或第 25.3.4.2 节 “SUC 计划部署 - 捆绑包资源”。
用户将配置的 GitRepo/捆绑包资源部署到其
管理群集
中的fleet-default
名称空间。此操作可以手动完成,也可以通过 Rancher UI(如果可用)完成。Fleet(第 6 章 “Fleet”)持续监控
fleet-default
名称空间,并立即检测新部署的 GitRepo/捆绑包资源。有关 Fleet 监控哪些名称空间的详细信息,请参见 Fleet 的名称空间文档。如果用户已部署 GitRepo 资源,
Fleet
将协调 GitRepo,并根据其路径和 fleet.yaml 配置,在fleet-default
名称空间中部署捆绑包资源。有关详细信息,请参见 Fleet 的 GitRepo 内容文档。然后,
Fleet
继续将此捆绑包中的Kubernetes 资源
部署到所有目标下游群集
。在操作系统软件包更新
的上下文中,Fleet 将部署捆绑包中的以下资源:os-pkg-plan-agent
SUC 计划 - 告知 SUC 如何在群集代理节点上执行软件包更新。如果群集仅由控制平面节点组成,则不做解释。os-pkg-plan-control-plane
SUC 计划 - 告知 SUC 如何在群集控制平面节点上执行软件包更新。os-pkg-update
密钥 - 在每个 SUC 计划中引用;附带一个update.sh
脚本,该脚本负责创建执行实际软件包更新的edge-update.service
sustemd.service。注意上述资源将部署在每个下游群集的
cattle-system
名称空间中。
在下游群集上,SUC 将拾取新部署的 SUC 计划,并在与 SUC 计划中定义的节点选择器匹配的每个节点上部署更新 Pod。有关如何监控 SUC 计划 Pod 的信息,请参见第 25.2.2.2 节 “监控 SUC 计划”。
更新 Pod(部署在每个节点上)挂载
os-pkg-update
密钥并执行密钥附带的update.sh
脚本。update.sh
继续执行以下操作:创建
edge-update.service
- 创建的服务属于 oneshot 类型,采用以下工作流程:通过执行以下命令更新节点操作系统上的所有软件包版本:
transactional-update cleanup dup
成功执行
transactional-update
后,将安排系统重引导,使软件包版本更新生效注意成功执行
transactional-update
后,将安排系统重引导并等待 1 分钟。
启动
edge-update.service
并等待启动完成清理
edge-update.service
- 在 systemd.service 完成其工作后,会将其从系统中去除,以确保将来不会发生意外的执行/重引导。
系统重引导后,操作系统软件包更新过程即告完成。重引导后,所有操作系统软件包版本应会更新到可用操作系统 RPM 储存库中显示的相应最新版本。
25.3.4 操作系统软件包更新 - SUC 计划部署 #
本节介绍如何使用 Fleet 的 GitRepo 和捆绑包资源来编排 SUC 计划相关的操作系统软件包更新的部署。
25.3.4.1 SUC 计划部署 - GitRepo 资源 #
可通过以下方式之一部署 GitRepo
资源,该资源中附带了所需的操作系统软件包更新
SUC
计划:
通过
Rancher UI
部署 - 第 25.3.4.1.1 节 “GitRepo 创建 - Rancher UI”(如果Rancher
可用)。手动将相应资源部署(第 25.3.4.1.2 节 “GitRepo 创建 - 手动”)到
管理群集
。
部署后,要监控目标群集节点的操作系统软件包更新过程,请参见第 25.2.2.2 节 “监控 SUC 计划”文档。
25.3.4.1.1 GitRepo 创建 - Rancher UI #
在左上角,选择 ☰ → Continuous Delivery(持续交付)
转到 Git 储存库 → 添加储存库
如果使用 suse-edge/fleet-examples
储存库,请执行以下步骤:
监视 → 修订版 - 为要使用的
suse-edge/fleet-examples
储存库选择版本标记在路径下,添加您要使用的操作系统软件包更新 Fleet 的路径 -
fleets/day2/system-upgrade-controller-plans/os-pkg-update
选择下一步转到目标配置部分。请仅选择您要升级其节点软件包的群集
创建
或者,如果您决定使用自己的储存库来托管这些文件,则需要提供上述储存库数据。
25.3.4.1.2 GitRepo 创建 - 手动 #
选择您要从中应用操作系统 SUC 更新计划的所需 Edge 版本标记(在下文中用
${REVISION}
表示)。提取 GitRepo 资源:
curl -o os-pkg-update-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/gitrepos/day2/os-pkg-update-gitrepo.yaml
编辑 GitRepo 配置,在
spec.targets
下指定所需的目标列表。默认情况下,suse-edge/fleet-examples
中的GitRepo
资源不会映射到任何下游群集。为了匹配所有群集,请将默认的
GitRepo
目标更改为:spec: targets: - clusterSelector: {}
或者,如果您要更细致地选择群集,请参见映射到下游群集
将 GitRepo 资源应用于
管理群集
:kubectl apply -f os-pkg-update-gitrepo.yaml
查看
fleet-default
名称空间下创建的 GitRepo 资源:kubectl get gitrepo os-pkg-update -n fleet-default # Example output NAME REPO COMMIT BUNDLEDEPLOYMENTS-READY STATUS os-pkg-update https://github.com/suse-edge/fleet-examples.git release-3.0.1 0/0
25.3.4.2 SUC 计划部署 - 捆绑包资源 #
可通过以下方式之一部署捆绑包资源,该资源中附带了所需的操作系统软件包更新
SUC 计划:
通过
Rancher UI
部署 - 第 25.3.4.2.1 节 “捆绑包创建 - Rancher UI”(如果Rancher
可用)。手动将相应资源部署(第 25.3.4.2.2 节 “捆绑包创建 - 手动”)到
管理群集
。
部署后,要监控目标群集节点的操作系统软件包更新过程,请参见第 25.2.2.2 节 “监控 SUC 计划”文档。
25.3.4.2.1 捆绑包创建 - Rancher UI #
在左上角,单击 ☰ → Continuous Delivery(持续交付)
转到高级 > 捆绑包
选择从 YAML 创建
此处可通过以下方式之一创建捆绑包:
通过手动将捆绑包内容复制到从 YAML 创建页面。可以从 https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/bundles/day2/system-upgrade-controller-plans/os-pkg-update/pkg-update-bundle.yaml 检索内容,其中
${REVISION}
是您使用的 Edge 版本通过将 suse-edge/fleet-examples 储存库克隆到所需的版本标记中,并在从 YAML 创建页面中选择从文件读取选项。然后导航到
bundles/day2/system-upgrade-controller-plans/os-pkg-update
目录并选择pkg-update-bundle.yaml
。这会在从 YAML 创建页面中自动填充捆绑包内容。
更改
捆绑包
的目标群集:为了匹配所有下游群集,请将默认的捆绑包
.spec.targets
更改为:spec: targets: - clusterSelector: {}
有关更精细的下游群集映射,请参见映射到下游群集。
选择创建
25.3.4.2.2 捆绑包创建 - 手动 #
选择您要从中应用操作系统软件包更新 SUC 计划的所需 Edge 版本标记(在下文中用
${REVISION}
表示)。提取捆绑包资源:
curl -o pkg-update-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/bundles/day2/system-upgrade-controller-plans/os-pkg-update/pkg-update-bundle.yaml
编辑
捆绑包
目标配置,在spec.targets
下提供所需的目标列表。默认情况下,suse-edge/fleet-examples
中的捆绑包
资源不会映射到任何下游群集。为了匹配所有群集,请将默认的
捆绑包
目标更改为:spec: targets: - clusterSelector: {}
或者,如果您要更细致地选择群集,请参见映射到下游群集
将捆绑包资源应用于
管理群集
:kubectl apply -f pkg-update-bundle.yaml
查看
fleet-default
名称空间下创建的捆绑包资源:kubectl get bundles os-pkg-update -n fleet-default # Example output NAME BUNDLEDEPLOYMENTS-READY STATUS os-pkg-update 0/0
25.3.4.3 SUC 计划部署 - 第三方 GitOps 工作流程 #
在某些用例中,用户可能希望将操作系统软件包更新 SUC 计划合并到他们自己的第三方
GitOps 工作流程(例如 Flux
)中。
要获取所需的操作系统软件包更新资源,首先请确定您要使用的 suse-edge/fleet-examples 储存库的 Edge 版本标记。
然后,便可以在
fleets/day2/system-upgrade-controller-plans/os-pkg-update
中查找资源,其中:
plan-control-plane.yaml
- 控制平面节点的系统升级控制器
计划资源plan-agent.yaml
- 代理节点的系统升级控制器
计划资源secret.yaml
- 密钥,其中附带了用于创建edge-update.service
systemd.service 的脚本
这些计划
资源由系统升级控制器
解释,应部署在您要升级的每个下游群集上。有关如何部署系统升级控制器
的信息,请参见第 25.2.1.3 节 “使用第三方 GitOps 工作流程时部署系统升级控制器”。
为了更好地了解如何使用 GitOps 工作流程来部署操作系统软件包更新的 SUC
计划,建议查看有关使用 Fleet
进行更新的过程概述(第 25.3.3.1 节 “概述”)。
25.4 Kubernetes 版本升级 #
本节介绍不是通过 Rancher(第 4 章 “Rancher”)实例创建的下游群集的 Kubernetes 升级过程。有关如何对通过
Rancher
创建的群集进行 Kubernetes 版本升级的信息,请参见升级和回滚
Kubernetes。
25.4.1 组件 #
本节介绍 Kubernetes 升级
过程在默认 Day 2
组件(第 25.1.1 节 “组件”)之上使用的自定义组件。
25.4.1.1 rke2-upgrade #
负责升级特定节点的 RKE2 版本的映像。
此组件由 SUC 根据 SUC 计划创建的 Pod 交付。该计划应位于需要进行 RKE2 升级的每个下游群集上。
有关 rke2-upgrade
映像如何执行升级的详细信息,请参见上游文档。
25.4.1.2 k3s-upgrade #
负责升级特定节点的 K3s 版本的映像。
此组件由 SUC 根据 SUC 计划创建的 Pod 交付。该计划应位于需要进行 K3s 升级的每个下游群集上。
有关 k3s-upgrade
映像如何执行升级的详细信息,请参见上游文档。
25.4.2 要求 #
备份您的 Kubernetes 发行版:
对于导入的 RKE2 群集,请参见 RKE2 备份和恢复文档。
对于导入的 K3s 群集,请参见 K3s 备份和恢复文档。
确保 SUC 计划容忍度与节点容忍度相匹配 - 如果您的 Kubernetes 群集节点具有自定义污点,请确保在 SUC 计划中为这些污点添加容忍度。默认情况下,SUC 计划仅包含控制平面节点的容忍度。默认容忍度包括:
CriticalAddonsOnly=true:NoExecute
node-role.kubernetes.io/control-plane:NoSchedule
node-role.kubernetes.io/etcd:NoExecute
注意其他任何容忍度必须添加到每个计划的
.spec.tolerations
部分下。与 Kubernetes 版本升级相关的 SUC 计划可以在 suse-edge/fleet-examples 储存库中的以下位置找到:对于 RKE2 -
fleets/day2/system-upgrade-controller-plans/rke2-upgrade
对于 K3s -
fleets/day2/system-upgrade-controller-plans/k3s-upgrade
请确保使用有效储存库版本标记中的计划。
为 RKE2 控制平面 SUC 计划定义自定义容忍度的示例如下:
apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: rke2-plan-control-plane spec: ... tolerations: # default tolerations - key: "CriticalAddonsOnly" operator: "Equal" value: "true" effect: "NoExecute" - key: "node-role.kubernetes.io/control-plane" operator: "Equal" effect: "NoSchedule" - key: "node-role.kubernetes.io/etcd" operator: "Equal" effect: "NoExecute" # custom toleration - key: "foo" operator: "Equal" value: "bar" effect: "NoSchedule" ...
25.4.3 升级过程 #
本节假设您将使用 Fleet(第 6 章 “Fleet”)部署 SUC 计划。如果您打算使用其他方法部署 SUC 计划,请参见第 25.4.4.3 节 “SUC 计划部署 - 第三方 GitOps 工作流程”。
Kubernetes 版本升级过程
主要围绕着将 SUC
计划部署到下游群集来进行。这些计划包含的信息会告知 SUC
要在哪些节点上创建运行 rke2/k3s-upgrade
映像的 Pod。有关 SUC 计划结构的信息,请参见上游文档。
Kubernetes 升级
计划通过以下方式交付:
通过
GitRepo
资源 - 第 25.4.4.1 节 “SUC 计划部署 - GitRepo 资源”通过
捆绑包
资源 - 第 25.4.4.2 节 “SUC 计划部署 - 捆绑包资源”
要确定使用哪个资源,请参见第 25.1.2 节 “确定您的用例”。
有关更新过程中会发生哪些情况的完整概述,请参见第 25.4.3.1 节 “概述”一节。
25.4.3.1 概述 #
本节旨在介绍 Kubernetes 版本升级过程从头到尾的完整工作流程。
Kubernetes 版本升级步骤:
用户可以根据用例,确定是要使用 GitRepo 还是捆绑包资源将
Kubernetes 升级 SUC 计划
部署到所需的下游群集。有关如何将 GitRepo/捆绑包映射到特定的一组下游群集的信息,请参见映射到下游群集。如果您不确定是要使用 GitRepo 还是捆绑包资源进行 SUC 计划部署,请参见第 25.1.2 节 “确定您的用例”。
有关 GitRepo/捆绑包配置选项,请参见第 25.4.4.1 节 “SUC 计划部署 - GitRepo 资源”或第 25.4.4.2 节 “SUC 计划部署 - 捆绑包资源”。
用户将配置的 GitRepo/捆绑包资源部署到其
管理群集
中的fleet-default
名称空间。此操作可以手动完成,也可以通过 Rancher UI(如果可用)完成。Fleet(第 6 章 “Fleet”)持续监控
fleet-default
名称空间,并立即检测新部署的 GitRepo/捆绑包资源。有关 Fleet 监控哪些名称空间的详细信息,请参见 Fleet 的名称空间文档。如果用户已部署 GitRepo 资源,
Fleet
将协调 GitRepo,并根据其路径和 fleet.yaml 配置,在fleet-default
名称空间中部署捆绑包资源。有关详细信息,请参见 Fleet 的 GitRepo 内容文档。然后,
Fleet
继续将此捆绑包中的Kubernetes 资源
部署到所有目标下游群集
。在Kubernetes 版本升级
的上下文中,Fleet 将部署捆绑包中的以下资源(具体取决于 Kubernetes 发行版):rke2-plan-agent
/k3s-plan-agent
- 告知 SUC 如何在群集代理节点上执行 Kubernetes 升级。如果群集仅由控制平面节点组成,则不做解释。rke2-plan-control-plane
/k3s-plan-control-plane
- 告知 SUC 如何在群集控制平面节点上执行 Kubernetes 升级。注意上述 SUC 计划将部署在每个下游群集的
cattle-system
名称空间中。
在下游群集上,SUC 将拾取新部署的 SUC 计划,并在与 SUC 计划中定义的节点选择器匹配的每个节点上部署更新 Pod。有关如何监控 SUC 计划 Pod 的信息,请参见第 25.2.2.2 节 “监控 SUC 计划”。
根据您部署的 SUC 计划,更新 Pod 将运行 rke2-upgrade 或 k3s-upgrade 映像,并在每个群集节点上执行以下工作流程:
封锁群集节点 - 为了确保在升级此节点时不会意外调度任何 Pod,我们将此节点标记为
不可调度
。将节点操作系统上安装的
rke2/k3s
二进制文件替换为 Pod 当前正在运行的rke2-upgrade/k3s-upgrade
映像附带的二进制文件。终止节点操作系统上正在运行的
rke2/k3s
进程 - 这会指示监督程序使用新版本自动重启动rke2/k3s
进程。解封群集节点 - 成功完成 Kubernetes 发行版升级后,将节点重新标记为
可调度
。注意有关
rke2-upgrade
和k3s-upgrade
映像工作原理的更多信息,请参见 rke2-upgrade 和 k3s-upgrade 上游项目。
执行上述步骤后,每个群集节点的 Kubernetes 版本应会升级到所需的 Edge 兼容版本。
25.4.4 Kubernetes 版本升级 - SUC 计划部署 #
25.4.4.1 SUC 计划部署 - GitRepo 资源 #
可通过以下方式之一部署 GitRepo 资源,该资源中附带了所需的
Kubernetes 升级
SUC 计划:
通过
Rancher UI
部署 - 第 25.4.4.1.1 节 “GitRepo 创建 - Rancher UI”(如果Rancher
可用)。手动将相应资源部署(第 25.4.4.1.2 节 “GitRepo 创建 - 手动”)到
管理群集
。
部署后,要监控目标群集节点的 Kubernetes 升级过程,请参见第 25.2.2.2 节 “监控 SUC 计划”文档。
25.4.4.1.1 GitRepo 创建 - Rancher UI #
在左上角,选择 ☰ → Continuous Delivery(持续交付)
转到 Git 储存库 → 添加储存库
如果使用 suse-edge/fleet-examples
储存库,请执行以下步骤:
监视 → 修订版 - 为要使用的
suse-edge/fleet-examples
储存库选择版本标记在路径下,添加版本标记中显示的 Kubernetes 发行版升级 Fleet 路径:
对于 RKE2 -
fleets/day2/system-upgrade-controller-plans/rke2-upgrade
对于 K3s -
fleets/day2/system-upgrade-controller-plans/k3s-upgrade
选择下一步转到目标配置部分。请仅选择您要升级其中的所需 Kubernetes 发行版的群集
创建
或者,如果您决定使用自己的储存库来托管这些文件,则需要提供上述储存库数据。
25.4.4.1.2 GitRepo 创建 - 手动 #
选择您要从中应用 Kubernetes SUC 升级计划的所需 Edge 版本标记(在下文中用
${REVISION}
表示)。提取 GitRepo 资源:
对于 RKE2 群集:
curl -o rke2-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/gitrepos/day2/rke2-upgrade-gitrepo.yaml
对于 K3s 群集:
curl -o k3s-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/gitrepos/day2/k3s-upgrade-gitrepo.yaml
编辑 GitRepo 配置,在
spec.targets
下指定所需的目标列表。默认情况下,suse-edge/fleet-examples
中的GitRepo
资源不会映射到任何下游群集。为了匹配所有群集,请将默认的
GitRepo
目标更改为:spec: targets: - clusterSelector: {}
或者,如果您要更细致地选择群集,请参见映射到下游群集
将 GitRepo 资源应用于
管理群集
:# RKE2 kubectl apply -f rke2-upgrade-gitrepo.yaml # K3s kubectl apply -f k3s-upgrade-gitrepo.yaml
查看
fleet-default
名称空间下创建的 GitRepo 资源:# RKE2 kubectl get gitrepo rke2-upgrade -n fleet-default # K3s kubectl get gitrepo k3s-upgrade -n fleet-default # Example output NAME REPO COMMIT BUNDLEDEPLOYMENTS-READY STATUS k3s-upgrade https://github.com/suse-edge/fleet-examples.git release-3.0.1 0/0 rke2-upgrade https://github.com/suse-edge/fleet-examples.git release-3.0.1 0/0
25.4.4.2 SUC 计划部署 - 捆绑包资源 #
可通过以下方式之一部署捆绑包资源,该资源中附带了所需的
Kubernetes 升级
SUC 计划:
通过
Rancher UI
部署 - 第 25.4.4.2.1 节 “捆绑包创建 - Rancher UI”(如果Rancher
可用)。手动将相应资源部署(第 25.4.4.2.2 节 “捆绑包创建 - 手动”)到
管理群集
。
部署后,要监控目标群集节点的 Kubernetes 升级过程,请参见第 25.2.2.2 节 “监控 SUC 计划”文档。
25.4.4.2.1 捆绑包创建 - Rancher UI #
在左上角,单击 ☰ → Continuous Delivery(持续交付)
转到高级 > 捆绑包
选择从 YAML 创建
此处可通过以下方式之一创建捆绑包:
通过手动将捆绑包内容复制到从 YAML 创建页面。可以检索内容:
通过将 suse-edge/fleet-examples 储存库克隆到所需的版本标记中,并在从 YAML 创建页面中选择从文件读取选项。然后导航到所需的捆绑包(对于 RKE2,为
/bundles/day2/system-upgrade-controller-plans/rke2-upgrade/plan-bundle.yaml
;对于 K3s,为/bundles/day2/system-upgrade-controller-plans/k3s-upgrade/plan-bundle.yaml
)。这会在从 YAML 创建页面中自动填充捆绑包内容
更改
捆绑包
的目标群集:为了匹配所有下游群集,请将默认的捆绑包
.spec.targets
更改为:spec: targets: - clusterSelector: {}
有关更精细的下游群集映射,请参见映射到下游群集。
创建
25.4.4.2.2 捆绑包创建 - 手动 #
选择您要从中应用 Kubernetes SUC 升级计划的所需 Edge 版本标记(在下文中用
${REVISION}
表示)。提取捆绑包资源:
对于 RKE2 群集:
curl -o rke2-plan-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/bundles/day2/system-upgrade-controller-plans/rke2-upgrade/plan-bundle.yaml
对于 K3s 群集:
curl -o k3s-plan-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/${REVISION}/bundles/day2/system-upgrade-controller-plans/k3s-upgrade/plan-bundle.yaml
编辑
捆绑包
目标配置,在spec.targets
下提供所需的目标列表。默认情况下,suse-edge/fleet-examples
中的捆绑包
资源不会映射到任何下游群集。为了匹配所有群集,请将默认的
捆绑包
目标更改为:spec: targets: - clusterSelector: {}
或者,如果您要更细致地选择群集,请参见映射到下游群集
将捆绑包资源应用于
管理群集
:# For RKE2 kubectl apply -f rke2-plan-bundle.yaml # For K3s kubectl apply -f k3s-plan-bundle.yaml
查看
fleet-default
名称空间下创建的捆绑包资源:# For RKE2 kubectl get bundles rke2-upgrade -n fleet-default # For K3s kubectl get bundles k3s-upgrade -n fleet-default # Example output NAME BUNDLEDEPLOYMENTS-READY STATUS k3s-upgrade 0/0 rke2-upgrade 0/0
25.4.4.3 SUC 计划部署 - 第三方 GitOps 工作流程 #
在某些用例中,用户可能希望将 Kubernetes 升级资源合并到他们自己的第三方 GitOps 工作流程(例如
Flux
)中。
要获取所需的升级资源,首先请确定您要使用的 suse-edge/fleet-examples 储存库的 Edge 版本标记。
然后,便可以在以下位置查找资源:
对于 RKE2 群集升级:
对于
控制平面
节点 -fleets/day2/system-upgrade-controller-plans/rke2-upgrade/plan-control-plane.yaml
对于
代理
节点 -fleets/day2/system-upgrade-controller-plans/rke2-upgrade/plan-agent.yaml
对于 K3s 群集升级:
对于
控制平面
节点 -fleets/day2/system-upgrade-controller-plans/k3s-upgrade/plan-control-plane.yaml
对于
代理
节点 -fleets/day2/system-upgrade-controller-plans/k3s-upgrade/plan-agent.yaml
这些计划
资源由系统升级控制器
解释,应部署在您要升级的每个下游群集上。有关如何部署系统升级控制器
的信息,请参见第 25.2.1.3 节 “使用第三方 GitOps 工作流程时部署系统升级控制器”。
为了更好地了解如何使用 GitOps 工作流程来部署 Kubernetes 版本升级的 SUC
计划,建议查看有关使用 Fleet
进行更新的过程概述(第 25.4.3.1 节 “概述”)。
25.5 Helm chart 升级 #
以下章节重点介绍如何使用 Fleet
功能实现 Helm chart 更新。
采用第三方 GitOps 工作流程的用户应从
fleets/day2/chart-templates/<chart-name>
中的
fleet.yaml
文件获取所需 Helm chart 的配置。请确保从有效的“Day 2”Edge 版本中检索
chart 数据。
25.5.1 组件 #
除了默认的 Day 2
组件(第 25.1.1 节 “组件”)之外,此操作不需要其他自定义组件。
25.5.2 为隔离环境做好准备 #
25.5.2.1 确保您有权访问 Helm chart 的升级 fleet.yaml
文件 #
将所需的资源托管在管理群集
可访问的本地 git 服务器上。
25.5.2.2 找到 Edge 发行版本的所需资产 #
转到 Day 2 版本页面,找到您要将 chart 升级到的 Edge 3.X.Y 版本,然后单击资产。
从该版本的资产部分下载以下文件,对 SUSE 支持的 Helm chart 进行隔离式升级时需要这些文件:
版本文件
说明
edge-save-images.sh
此脚本提取
edge-release-images.txt
文件中的映像并将其保存到“.tar.gz”存档中,然后您可以在隔离环境中使用该存档。edge-save-oci-artefacts.sh
此脚本提取
edge-release-helm-oci-artefacts.txt
文件中的 SUSE OCI chart 项目,并为包含所有其他 chart OCI 存档的目录创建“.tar.gz”存档。edge-load-images.sh
此脚本加载
edge-save-images.sh
生成的“.tar.gz”存档中的映像,重新标记这些映像并将其推送到专用注册表中。edge-load-oci-artefacts.sh
此脚本获取包含“.tgz”SUSE OCI chart 的目录,并将所有 OCI chart 加载到专用注册表中。该目录是从
edge-save-oci-artefacts.sh
脚本生成的“.tar.gz”存档中检索的。edge-release-helm-oci-artefacts.txt
此文件包含 SUSE Edge 版本 Helm chart 的 OCI 项目列表。
edge-release-images.txt
此文件包含 Edge 版本 Helm chart 所需的映像列表。
25.5.2.3 创建 SUSE Edge 版本映像存档 #
在可以访问互联网的计算机上:
将
edge-save-images.sh
设为可执行文件:chmod +x edge-save-images.sh
使用
edge-save-images.sh
脚本创建 Docker 可导入的“.tar.gz”存档:./edge-save-images.sh --source-registry registry.suse.com
这会创建一个随时可加载的
edge-images.tar.gz
(除非指定了-i|--images
选项)存档,其中包含所需的映像。将此存档复制到隔离的计算机
scp edge-images.tar.gz <user>@<machine_ip>:/path
25.5.2.4 创建 SUSE Edge Helm chart OCI 映像存档 #
在可以访问互联网的计算机上:
将
edge-save-oci-artefacts.sh
设为可执行文件:chmod +x edge-save-oci-artefacts.sh
使用
edge-save-oci-artefacts.sh
脚本创建包含所有 SUSE Edge Helm chart OCI 映像的“.tar.gz”存档:./edge-save-oci-artefacts.sh --source-registry registry.suse.com
这会创建一个包含所有 SUSE Edge Helm chart OCI 映像的
oci-artefacts.tar.gz
存档将此存档复制到隔离的计算机
scp oci-artefacts.tar.gz <user>@<machine_ip>:/path
25.5.2.5 将 SUSE Edge 版本映像加载到隔离的计算机上 #
在隔离的计算机上:
登录到专用注册表(如果需要):
podman login <REGISTRY.YOURDOMAIN.COM:PORT>
将
edge-load-images.sh
设为可执行文件:chmod +x edge-load-images.sh
使用
edge-load-images.sh
从复制的edge-images.tar.gz
存档中加载映像,重新标记这些映像并将其推送到专用注册表中:./edge-load-images.sh --source-registry registry.suse.com --registry <REGISTRY.YOURDOMAIN.COM:PORT> --images edge-images.tar.gz
25.5.2.6 将 SUSE Edge Helm chart OCI 映像加载到隔离的计算机上 #
在隔离的计算机上:
登录到专用注册表(如果需要):
podman login <REGISTRY.YOURDOMAIN.COM:PORT>
将
edge-load-oci-artefacts.sh
设为可执行文件:chmod +x edge-load-oci-artefacts.sh
解压缩复制的
oci-artefacts.tar.gz
存档:tar -xvf oci-artefacts.tar.gz
这会使用命名模板
edge-release-oci-tgz-<date>
生成一个目录将此目录传递给
edge-load-oci-artefacts.sh
脚本,以将 SUSE Edge Helm chart OCI 映像加载到专用注册表中:注意此脚本假设您的环境中已预装了
Helm
CLI。有关 Helm 安装说明,请参见安装 Helm。./edge-load-oci-artefacts.sh --archive-directory edge-release-oci-tgz-<date> --registry <REGISTRY.YOURDOMAIN.COM:PORT> --source-registry registry.suse.com
25.5.2.7 为 Kubernetes 发行版创建指向专用注册表的注册表镜像 #
对于 RKE2,请参见 Containerd 注册表配置
对于 K3s,请参见嵌入式注册表镜像
25.5.3 升级过程 #
以下升级过程利用 Rancher 的 Fleet(第 6 章 “Fleet”)功能。使用第三方 GitOps 工作流程的用户应根据第 33.1 节 “摘要”中所述检索每个 Edge 版本支持的 chart 版本,并将这些支持的版本填充到其第三方 GitOps 工作流程中。
本节重点介绍以下用例的 Helm 升级过程:
我有一个新群集,想要部署和管理 SUSE Helm chart(第 25.5.3.1 节 “我有一个新群集,想要部署和管理 SUSE Helm chart”)
我想升级 Fleet 管理的 Helm chart(第 25.5.3.2 节 “我想升级 Fleet 管理的 Helm chart”)
我想升级 EIB 创建的 Helm chart(第 25.5.3.3 节 “我想升级 EIB 创建的 Helm chart”)
手动部署的 Helm chart 无法可靠升级。我们建议使用第 25.5.3.1 节 “我有一个新群集,想要部署和管理 SUSE Helm chart”方法重新部署这些 Helm chart。
25.5.3.1 我有一个新群集,想要部署和管理 SUSE Helm chart #
适用于想要通过 Fleet 管理其 Helm chart 生命周期的用户。
25.5.3.1.1 准备 Fleet 资源 #
从您要使用的 Edge 版本标记中获取 Chart 的 Fleet 资源
从选定的 Edge 版本标记修订版导航到 Helm chart Fleet 目录 -
fleets/day2/chart-templates/<chart>
将该 chart Fleet 目录复制到用于 GitOps 工作流程的 Git 储存库
(可选)如果 Helm chart 需要对其值进行配置,请编辑复制的目录中
fleet.yaml
文件内的.helm.values
配置(可选)在某些用例中,您可能需要向 chart 的 Fleet 目录添加其他资源,使该目录能够更好地适应您的环境。有关如何增强 Fleet 目录的信息,请参见 Git 储存库内容
longhorn
Helm chart 的示例如下:
用户 Git 储存库结构:
<user_repository_root> └── longhorn └── fleet.yaml
填充了用户
longhorn
数据的fleet.yaml
内容:defaultNamespace: longhorn-system helm: releaseName: "longhorn" chart: "longhorn" repo: "https://charts.longhorn.io" version: "1.6.1" takeOwnership: true # custom chart value overrides values: # Example for user provided custom values content defaultSettings: deletingConfirmationFlag: true # https://fleet.rancher.io/bundle-diffs diff: comparePatches: - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: engineimages.longhorn.io operations: - {"op":"remove", "path":"/status/conditions"} - {"op":"remove", "path":"/status/storedVersions"} - {"op":"remove", "path":"/status/acceptedNames"} - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: nodes.longhorn.io operations: - {"op":"remove", "path":"/status/conditions"} - {"op":"remove", "path":"/status/storedVersions"} - {"op":"remove", "path":"/status/acceptedNames"} - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: volumes.longhorn.io operations: - {"op":"remove", "path":"/status/conditions"} - {"op":"remove", "path":"/status/storedVersions"} - {"op":"remove", "path":"/status/acceptedNames"}
注意上面只是一些示例值,用于演示基于
longhorn
chart 创建的自定义配置。不应将它们视为longhorn
chart 的部署指南。
25.5.3.1.2 创建 GitRepo #
在储存库中填充 chart 的 Fleet 资源后,必须创建 GitRepo 资源。此资源将包含有关如何访问 chart 的 Fleet 资源以及需要将这些资源应用于哪些群集的信息。
可以通过 Rancher UI 或者通过将资源手动部署到管理群集
来创建
GitRepo
资源。
有关如何手动创建和部署 GitRepo 资源的信息,请参见创建部署。
要通过 Rancher UI 创建
GitRepo
资源,请参见在
Rancher UI 中访问 Fleet。
用于手动部署的 longhorn GitRepo
资源示例:
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
name: longhorn-git-repo
namespace: fleet-default
spec:
# If using a tag
# revision: <user_repository_tag>
#
# If using a branch
# branch: <user_repository_branch>
paths:
# As seen in the 'Prepare your Fleet resources' example
- longhorn
repo: <user_repository_url>
targets:
# Match all clusters
- clusterSelector: {}
25.5.3.1.3 管理部署的 Helm chart #
通过 Fleet 部署后,要进行 Helm chart 升级,请参见第 25.5.3.2 节 “我想升级 Fleet 管理的 Helm chart”。
25.5.3.2 我想升级 Fleet 管理的 Helm chart #
确定需要将 chart 升级到哪个版本,以便它与 Edge 3.X.Y 版本兼容。可以在第 33.1 节 “摘要”中查看每个 Edge 版本的 Helm chart 版本。
在 Fleet 监控的 Git 储存库中,根据第 33.1 节 “摘要”中所述使用正确的 chart 版本和储存库编辑 Helm chart 的
fleet.yaml
文件。提交更改并将其推送到储存库后,会触发所需 Helm chart 的升级
25.5.3.3 我想升级 EIB 创建的 Helm chart #
本节假设您已预先部署了系统升级控制器 (SUC),如果您尚未部署,或者不确定为何需要 SUC,请参见默认的 Day 2 组件(第 25.1.1 节 “组件”)列表。
EIB 利用 rke2/k3s
的自动部署清单功能来部署 Helm chart。它在初始化器节点的
/var/lib/rancher/<rke2/k3s>/server/manifests
位置创建
HelmChart
资源定义清单,然后让 rke2/k3s
拾取该清单并将其自动部署到群集中。
从 Day 2
的角度看,这意味着对 Helm chart 的任何升级都需要通过编辑特定 chart的
HelmChart
清单文件来进行。为了对多个群集自动完成此过程,本节使用了 SUC 计划。
有关信息,请参见以下资源:
Helm chart 升级工作流程的一般概述(第 25.5.3.3.1 节 “概述”)。
成功完成 Helm chart 升级所要执行的升级步骤(第 25.5.3.3.2 节 “升级步骤”)。
展示使用所述方法进行 Longhorn chart 升级的示例(第 25.5.3.3.3 节 “示例”)。
如何使用其他 GitOps 工具完成升级过程(第 25.5.3.3.4 节 “使用第三方 GitOps 工具进行 Helm chart 升级”)。
25.5.3.3.1 概述 #
本节旨在概述用户升级一个或多个 Helm chart 所要执行的工作流程。有关完成 Helm chart 升级所要执行的步骤的详细说明,请参见第 25.5.3.3.2 节 “升级步骤”。
该工作流程的第一个步骤是用户提取其 chart 要升级到的新 Helm chart 存档。
然后对存档进行编码,并将其作为配置传递到位于相关 SUC 计划的 Fleet 目录下的
eib-chart-upgrade-user-data.yaml
文件中。“升级步骤”(第 25.5.3.3.2 节 “升级步骤”)一节会进一步解释此过程。然后,用户继续配置并部署
GitRepo
资源,用于将全部所需的资源(SUC 计划、密钥等)传送到下游群集。该资源部署在
管理群集
上的fleet-default
名称空间下。
Fleet(第 6 章 “Fleet”)检测部署的资源,并将配置的所有资源部署到指定的下游群集。部署的资源包括:
eib-chart-upgrade
SUC 计划,SUC 将使用它在每个节点上创建升级 Pod。eib-chart-upgrade-script
密钥,其中附带升级脚本
,升级 Pod 将使用该脚本来升级初始化器节点上的HelmChart
清单。eib-chart-upgrade-user-data
密钥,其中附带 chart 数据,升级脚本
将使用这些数据来了解需要升级哪些 chart 清单。
部署
eib-chart-upgrade
SUC 计划后,SUC 将拾取该计划并创建一个用于部署升级 Pod 的作业。部署后,升级 Pod 将挂载
eib-chart-upgrade-script
和eib-chart-upgrade-user-data
密钥,并执行eib-chart-upgrade-script
密钥附带的升级脚本
。升级脚本
执行以下操作:确定运行脚本的 Pod 是否已部署在
初始化器
节点上。初始化器
节点是托管HelmChart
清单的节点。对于单节点群集,它是单个控制平面节点。对于 HA 群集,它是您在 EIB 中创建群集时标记为初始化器
的节点。如果您未指定initializer
属性,则节点
列表中的第一个节点将标记为初始化器
。有关详细信息,请参见 EIB 的上游文档。注意如果
升级脚本
在非初始化器节点上运行,则它会立即完成执行,而不会执行下面的步骤。备份要编辑的清单,以确保能够实现灾难恢复。
注意默认情况下,清单的备份存储在
/tmp/eib-helm-chart-upgrade-<date>
目录下。如果您要使用自定义位置,可以将MANIFEST_BACKUP_DIR
环境变量传递给 Helm chart 升级 SUC 计划(计划中的示例)。编辑
HelmChart
清单。从此版本开始,已更改以下属性以触发 chart 升级:chartContent
属性的内容已替换为eib-chart-upgrade-user-data
密钥中提供的经过编码的存档。version
属性的值已替换为eib-chart-upgrade-user-data
密钥中提供的版本。
25.5.3.3.2 升级步骤 #
确定您要从中复制 Helm chart 升级逻辑的 Edge 版本标记。
将
fleets/day2/system-upgrade-controller-plans/eib-chart-upgrade
Fleet 目录复制到将由 Fleet 用来执行 GitOps 的储存库。提取您要升级到的 Helm chart 存档:
helm pull [chart URL | repo/chartname] # Alternatively if you want to pull a specific version: # helm pull [chart URL | repo/chartname] --version 0.0.0
对提取的 chart 存档进行编码:
# Encode the archive and disable line wrapping base64 -w 0 <chart-archive>.tgz
配置您在步骤 2 中复制的
eib-chart-upgrade
Fleet 目录下的eib-chart-upgrade-user-data.yaml
密钥:该密钥附带一个名为
chart_upgrade_data.txt
的文件。此文件包含 chart 升级数据,升级脚本
将使用这些数据来了解哪些 chart 需要升级。该文件要求以每个 chart 项一行的形式指定配置项,其格式如下:“<name>|<version>|<base64_encoded_archive>”:name
- Helm chart 的名称,如 EIB 定义文件的kubernetes.helm.charts.name[]
属性中所示。version
- 应包含 Helm chart 的新版本。在升级期间,此值用于替换HelmChart
清单的旧version
值。base64_encoded_archive
- 在此处传递base64 -w 0 <chart-archive>.tgz
的输出。在升级期间,此值用于替换HelmChart
清单的旧chartContent
值。注意在开始添加数据之前,应从该文件中去除 <name>|<version>|<base64_encoded_archive> 行。它是一个示例行,用于说明在何处以及如何配置 chart 数据。
配置一个
GitRepo
资源用于传送 chart 升级fleet
。有关GitRepo
的详细信息,请参见 GitRepo 资源。通过 Rancher UI 配置
GitRepo
:在左上角,选择 ☰ → Continuous Delivery(持续交付)
转到 Git 储存库 → 添加储存库
在此处将您的储存库数据和路径传递给 chart
升级 fleet
选择下一步,并指定您要对其中已配置的 chart 进行升级的目标群集
创建
如果无法对您的设置使用
Rancher
,可以在管理群集
上手动配置GitRepo
:在以下模板中填充您的数据:
apiVersion: fleet.cattle.io/v1alpha1 kind: GitRepo metadata: name: CHANGE_ME namespace: fleet-default spec: # if running from a tag # revision: CHANGE_ME # if running from a branch # branch: CHANGE_ME paths: # path to your chart upgrade fleet relative to your repository - CHANGE_ME # your repository URL repo: CHANGE_ME targets: # Select target clusters - clusterSelector: CHANGE_ME # To match all clusters: # - clusterSelector: {}
有关如何设置和部署
GitRepo
资源的详细信息,请参见 GitRepo 资源和创建 GitRepo 资源。有关如何在更精细的级别匹配目标群集的信息,请参见映射到下游群集。
将配置的
GitRepo
资源部署到管理群集
的fleet-default
名称空间。
执行这些步骤后,应该可以成功创建 GitRepo
资源。然后,Fleet
将拾取该资源,并创建捆绑包。此捆绑包将包含 GitRepo
在其 Fleet 目录下配置的原始 Kubernetes 资源。
然后,Fleet 会将捆绑包中的所有 Kubernetes 资源部署到指定的下游群集。其中一个资源是触发 chart 升级的 SUC 计划。有关要部署的资源的完整列表以及升级过程的工作流程,请参见“概述”(第 25.5.3.3.1 节 “概述”)一节。
要跟踪升级过程本身,请参见“监控 SUC 计划”(第 25.2.2.2 节 “监控 SUC 计划”)一节。
25.5.3.3.3 示例 #
下面一节将为第 25.5.3.3.2 节 “升级步骤”一节提供真实示例。
我通过 EIB 部署了以下两个群集:
longhorn-single-k3s
- 单节点 K3s 群集longhorn-ha-rke2
- HA RKE2 群集
这两个群集都运行 Longhorn,并已使用以下映像定义片段通过 EIB 进行部署:
kubernetes:
# HA RKE2 cluster specific snippet
# nodes:
# - hostname: cp1rke2.example.com
# initializer: true
# type: server
# - hostname: cp2rke2.example.com
# type: server
# - hostname: cp3rke2.example.com
# type: server
# - hostname: agent1rke2.example.com
# type: agent
# - hostname: agent2rke2.example.com
# type: agent
# version depending on the distribution
version: v1.28.9+k3s1/v1.28.9+rke2r1
helm:
charts:
- name: longhorn
repositoryName: longhorn
targetNamespace: longhorn-system
createNamespace: true
version: 1.5.5
repositories:
- name: longhorn
url: https://charts.longhorn.io
...
这种部署的问题在于,longhorn-single-k3s
和
longhorn-ha-rke2
当前运行的 Longhorn 版本与任何 Edge 版本都不兼容。
我们需要将这两个群集上的 chart 升级到 Edge 支持的 Longhorn 版本。
为此,我们需要执行以下步骤:
确定我们要从中获取升级逻辑的 Edge 版本标记。例如,此示例将使用
release-3.0.1
版本标记,它支持的 Longhorn 版本为1.6.1
。克隆
release-3.0.1
版本标记,并将fleets/day2/system-upgrade-controller-plans/eib-chart-upgrade
目录复制到我们自己的储存库。为简单起见,本节将根据
suse-edge/fleet-examples
储存库的某个分支介绍操作步骤,因此目录结构是相同的,但您可以将eib-chart-upgrade
Fleet 目录放入您的储存库中的任何位置。目录结构示例:
. ... |-- fleets | `-- day2 | `-- system-upgrade-controller-plans | `-- eib-chart-upgrade | |-- eib-chart-upgrade-script.yaml | |-- eib-chart-upgrade-user-data.yaml | |-- fleet.yaml | `-- plan.yaml ...
添加 Longhorn chart 储存库:
helm repo add longhorn https://charts.longhorn.io
提取 Longhorn chart 版本
1.6.1
:helm pull longhorn/longhorn --version 1.6.1
这会将 Longhorn 作为名为
longhorn-1.6.1.tgz
的存档来提取。对 Longhorn 存档进行编码:
base64 -w 0 longhorn-1.6.1.tgz
这会输出该存档的采用 base64 编码的单行字符串。
现在我们已准备好全部所需的数据,可以配置
eib-chart-upgrade-user-data.yaml
文件。文件配置应如下所示:apiVersion: v1 kind: Secret metadata: name: eib-chart-upgrade-user-data type: Opaque stringData: # <name>|<version>|<base64_encoded_archive> chart_upgrade_data.txt: | longhorn|1.6.1|H4sIFAAAAAAA/ykAK2FIUjBjSE02THk5NWIzV...
longhorn
是 EIB 定义文件中所示的 chart 名称1.6.1
是要将 LonghornHelmChart
清单的version
属性升级到的版本H4sIFAAAAAAA/ykAK2FIUjBjSE02THk5NWIzV...
是经过编码的 Longhorn1.6.1
存档的片段。此处添加了片段是为了方便阅读。您始终应在此处提供完整的采用 base64 编码的存档字符串。注意此示例显示了单个 chart 的升级配置,如果您的用例需要升级多个群集上的多个 chart,您可以追加其他 chart 数据,如下所示:
apiVersion: v1 kind: Secret metadata: name: eib-chart-upgrade-user-data type: Opaque stringData: # <name>|<version>|<base64_encoded_archive> chart_upgrade_data.txt: | chartA|0.0.0|<chartA_base64_archive> chartB|0.0.0|<chartB_base64_archive> chartC|0.0.0|<chartC_base64_archive> ...
我们还确定不要在
/tmp
中保留清单备份,因此在plan.yaml
文件中添加了以下配置:apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: eib-chart-upgrade spec: ... upgrade: ... # For when you want to backup your chart # manifest data under a specific directory # envs: - name: MANIFEST_BACKUP_DIR value: "/root"
这可以确保将清单备份保存在
/root
目录而不是/tmp
中。完成全部所需的配置后,剩下的操作就是创建
GitRepo
资源。此示例通过Rancher UI
创建GitRepo
资源。根据“升级步骤”(第 25.5.3.3.2 节 “升级步骤”)中所述的步骤,我们已经:
将
GitRepo
命名为“longhorn-upgrade”。将 URL 传递给要使用的储存库 - https://github.com/suse-edge/fleet-examples.git
传递储存库的分支 -“doc-example”
传递储存库中显示的
eib-chart-upgrade
Fleet 目录路径 -fleets/day2/system-upgrade-controller-plans/eib-chart-upgrade
选择目标群集并创建资源
图 25.9︰ 成功部署 SUC 和 Longhorn GitRepo #
现在我们需要监控群集上的升级过程:
按照“监控 SUC 计划”(第 25.2.2.2 节 “监控 SUC 计划”)一节中的指导,检查升级 Pod 的状态。
升级 Pod 成功完成后,我们还需要等待 Helm 控制器创建 Pod 并监控这些 Pod。这些 Pod 将根据升级 Pod 对
HelmChart
清单文件所做的文件更改执行实际升级。
确保一切成功完成后,我们需要校验版本是否已更改:
此结果确认 Longhorn
Helm chart 已成功升级,本示例到此结束。
如果出于某种原因,我们想要还原到 Longhorn 的前一 chart 版本,可以在初始化器节点上的
/root/longhorn.yaml
中找到旧版 Longhorn 清单。这是肯定的,因为我们已在 SUC
计划中指定了 MANIFEST_BACKUP_DIR
。
25.5.3.3.4 使用第三方 GitOps 工具进行 Helm chart 升级 #
在某些用例中,用户可能希望将此升级过程与除 Fleet 以外的 GitOps 工作流程(例如 Flux
)配合使用。
要获取与 EIB 所部署的 Helm chart 升级相关的资源,需要首先确定您要使用的 suse-edge/fleet-examples 储存库的 Edge 版本标记。
然后,便可以在
fleets/day2/system-upgrade-controller-plans/eib-chart-upgrade
中查找资源,其中:
plan.yaml
- 与升级过程相关的系统升级控制器计划。eib-chart-upgrade-script.yaml
- 密钥,其中包含负责编辑和升级HelmChart
清单文件的升级脚本
。eib-chart-upgrade-user-data.yaml
- 密钥,其中包含升级脚本
使用的文件;用户需事先在其中填充相关的 chart 升级数据。
这些计划
资源由系统升级控制器
解释,应部署在包含需要升级的 chart
的每个下游群集上。有关如何部署系统升级控制器
的信息,请参见第 25.2.1.3 节 “使用第三方 GitOps 工作流程时部署系统升级控制器”。
为了更好地了解如何使用 GitOps 工作流程来为升级过程部署 SUC
计划,建议查看有关使用 Fleet
进行升级的过程概述(第 25.5.3.3.1 节 “概述”)。
第 VI 部分 产品文档 #
在这里查找 ATIP 文档
- 26 SUSE 自适应电信基础架构平台 (ATIP)
SUSE 自适应电信基础架构平台 (
ATIP
) 是针对电信行业进行优化的边缘计算平台,可帮助电信公司实现创新并加速其网络的现代化改造。- 27 概念和体系结构
SUSE ATIP 是旨在用于托管从核心到边缘规模的现代云原生电信应用程序的平台。
- 28 要求和假设
ATIP 节点的硬件要求基于以下组件:
- 29 设置管理群集
管理群集是用于管理运行时堆栈的置备和生命周期的 ATIP 组成部分。从技术角度讲,管理群集包含以下组件:
- 30 电信功能配置
本章将阐释部署了 ATIP 的群集上特定于电信的功能配置。
- 31 全自动定向网络置备
定向网络置备是用于自动置备下游群集的功能。如果您有许多下游群集需要置备并希望自动完成该过程,此功能将非常有用。
- 32 生命周期操作
本章介绍已部署的 ATIP 群集的生命周期管理操作。
26 SUSE 自适应电信基础架构平台 (ATIP) #
SUSE 自适应电信基础架构平台 (ATIP
)
是针对电信行业进行优化的边缘计算平台,可帮助电信公司实现创新并加速其网络的现代化改造。
ATIP 是一个完整的电信云堆栈,用于托管 5G 分组核心和云 RAN 等云原生网络功能 (CNF)。
对电信规模的复杂边缘堆栈配置实现自动化零接触式部署和生命周期管理。
使用特定于电信公司的配置和工作负载持续保证电信级硬件的质量。
由专用于边缘的组件构成,因此占用空间更小,并且性能功耗比更高。
通过与供应商无关的 API 和完全开源性来维持灵活的平台策略。
27 概念和体系结构 #
SUSE ATIP 是旨在用于托管从核心到边缘规模的现代云原生电信应用程序的平台。
本页介绍 ATIP 中使用的体系结构和组件。了解这些知识将有助于部署和使用 ATIP。
27.1 ATIP 体系结构 #
下图显示了 ATIP 的概要体系结构:
27.2 组件 #
有两个不同的区块 - 管理堆栈和运行时堆栈:
管理堆栈:ATIP 的这一组成部分用于管理运行时堆栈的置备和生命周期。管理堆栈包括以下组件:
使用 Rancher 在公有云和私有云环境中进行多群集管理(第 4 章 “Rancher”)
使用 Metal3(第 8 章 “Metal3”)、MetalLB(第 17 章 “MetalLB”)和
CAPI
(群集 API)基础架构提供程序来提供裸机支持全面的租户隔离和
IDP
(身份提供程序)集成第三方集成和扩展大型商城
不区分供应商的 API 和丰富的提供商生态系统
控制 SLE Micro 事务更新
GitOps 引擎,可以结合使用 Git 储存库和 Fleet(第 6 章 “Fleet”)来管理群集的生命周期
运行时堆栈:ATIP 的这一组成部分用于运行工作负载。
包含 K3s(第 13 章 “K3s”)和 RKE2(第 14 章 “RKE2”)等安全轻量级发行版的 Kubernetes(
RKE2
已针对政府用途和受监管行业进行强化、认证和优化)。NeuVector(第 16 章 “NeuVector”),可用于实现映像漏洞扫描、深度包检测和群集内自动流量控制等安全功能。
包含 Longhorn(第 15 章 “Longhorn”)的块存储,让您可以方便地使用云原生存储解决方案。
包含 SLE Micro(第 7 章 “SLE Micro”)的优化操作系统,可以启用安全、轻量且不可变(事务文件系统)的操作系统来运行容器。SLE Micro 适用于
aarch64
和x86_64
体系结构,还支持用于电信和边缘用例的实时内核
。
27.3 部署流程示例 #
下面是工作流程的简要示例,可帮助您了解管理组件与运行时组件之间的关系。
定向网络置备是可用于部署预配置了所有组件,并可以在无需人工干预的情况下运行工作负载的新下游群集的工作流程。
27.3.1 示例 1:部署装有所有组件的新管理群集 #
使用 Edge Image Builder(第 9 章 “Edge Image Builder”)创建包含管理堆栈的新
ISO
映像。然后,可以使用此 ISO
映像在 VM
或裸机上安装新管理群集。
有关如何部署新管理群集的详细信息,请参见 ATIP 管理群集指南(第 29 章 “设置管理群集”)。
有关如何使用 Edge Image Builder 的详细信息,请参见 Edge Image Builder 指南(第 3 章 “使用 Edge Image Builder 配置独立群集”)。
27.3.2 示例 2:使用电信配置文件部署单节点下游群集,使其能够运行电信工作负载 #
启动并运行管理群集后,我们可以使用该群集通过定向网络置备工作流程,来部署启用并配置了所有电信功能的单节点下游群集。
下图显示了部署该群集的概要工作流程:
有关如何部署下游群集的详细信息,请参见 ATIP 自动置备指南(第 31 章 “全自动定向网络置备”)。
有关电信功能的详细信息,请参见 ATIP 电信功能指南(第 30 章 “电信功能配置”)。
27.3.3 示例 3:使用 MetalLB 作为负载平衡器部署高可用性下游群集 #
启动并运行管理群集后,我们可以使用该群集通过定向网络置备工作流程,来部署使用 MetalLB
作为负载平衡器的高可用性下游群集。
下图显示了部署该群集的概要工作流程:
有关如何部署下游群集的详细信息,请参见 ATIP 自动置备指南(第 31 章 “全自动定向网络置备”)。
有关 MetalLB
的详细信息,请参见第 17 章 “MetalLB”。
28 要求和假设 #
28.1 硬件 #
ATIP 节点的硬件要求基于以下组件:
管理群集:管理群集包含
SLE Micro
、RKE2
、Rancher Prime
、Metal3
等组件,用于管理多个下游群集。服务器的硬件要求可能根据所要管理的下游群集数量而有所不同。服务器(
VM
或裸机
)的最低要求如下:RAM:至少 8 GB(建议至少提供 16 GB)
CPU:至少 2 个(建议至少提供 4 个 CPU)
下游群集:下游群集是部署在 ATIP 节点上的群集,用于运行电信工作负载。需要满足特定的要求才能启用
SR-IOV
、CPU 性能优化
等某些电信功能。SR-IOV:要以直通模式将 VF(虚拟功能)挂接到 CNF/VNF,NIC 必须支持 SR-IOV,并且必须在 BIOS 中启用 VT-d/AMD-Vi。
CPU 处理器:要运行特定的电信工作负载,应该适配 CPU 处理器型号,以启用此参考表格(第 30 章 “电信功能配置”)中所述的大多数功能。
使用虚拟媒体进行安装所要满足的固件要求:
服务器硬件 | BMC 型号 | 管理 |
Dell 硬件 | 第 15 代 | iDRAC9 |
Supermicro 硬件 | 01.00.25 | Supermicro SMC - redfish |
HPE 硬件 | 1.50 | iLO6 |
28.2 网络 #
下图显示了电信环境的典型网络体系结构作为参考:
网络体系结构基于以下组件:
管理网络:此网络用于管理 ATIP 节点。它用于带外管理。通常,此网络还会连接到独立的管理交换机,但可以通过 VLAN 连接到同一服务交换机以隔离流量。
控制平面网络:此网络用于 ATIP 节点与其上运行的服务之间的通讯。此网络还用于 ATIP 节点与外部服务(例如
DHCP
或DNS
服务器)之间的通讯。在某些情况下,对于联网环境,交换机/路由器可以通过互联网处理流量。其他网络:在某些情况下,ATIP 节点可以连接到其他网络以满足特定的客户目的。
要使用定向网络置备工作流程,管理群集必须与下游群集服务器基板管理控制器 (BMC) 建立网络连接,以便可以自动准备和置备主机。
28.3 服务(DHCP、DNS 等) #
可能需要一些外部服务(例如 DHCP
、DNS
等),具体取决于部署环境的类型:
联网环境:在这种情况下,ATIP 节点将连接到互联网(通过路由 L3 协议),外部服务将由客户提供。
离线/隔离环境:在这种情况下,ATIP 节点未建立互联网 IP 连接,因此需要通过其他服务在本地镜像 ATIP 定向网络置备工作流程所需的内容。
文件服务器:文件服务器用于在执行定向网络置备工作流程期间存储 ATIP 节点上置备的 ISO 映像。
metal3
Helm chart 可以部署媒体服务器来存储 ISO 映像 — 请查看下面一节(注意),但也可以使用现有的本地 Web 服务器。
28.4 禁用 rebootmgr #
rebootmgr
是当系统中存在未完成的更新时用于配置重引导策略的服务。对于电信工作负载,必须禁用或正确配置
rebootmgr
服务,以避免在系统安排了更新时重引导节点,从而避免对节点上运行的服务造成任何影响。
有关 rebootmgr
的详细信息,请参见 rebootmgr GitHub 储存库。
运行以下命令来校验使用的策略:
cat /etc/rebootmgr.conf [rebootmgr] window-start=03:30 window-duration=1h30m strategy=best-effort lock-group=default
可以运行以下命令来禁用 rebootmgr:
sed -i 's/strategy=best-effort/strategy=off/g' /etc/rebootmgr.conf
也可以使用 rebootmgrctl
命令:
rebootmgrctl strategy off
可以使用定向网络置备工作流程来自动执行此项设置 rebootmgr
策略的配置。有关详细信息,请查看 ATIP
自动置备文档(第 31 章 “全自动定向网络置备”)。
29 设置管理群集 #
29.1 简介 #
管理群集是用于管理运行时堆栈的置备和生命周期的 ATIP 组成部分。从技术角度讲,管理群集包含以下组件:
SUSE Linux Enterprise Micro
(操作系统)。可以根据用例自定义某些配置,例如网络、存储、用户和内核参数。RKE2
(Kubernetes 群集)。可以根据用例将其配置为使用特定的 CNI 插件,例如Multus
、Cilium
等。Rancher
(管理平台),用于管理群集的生命周期。Metal3
,该组件用于管理裸机节点的生命周期。CAPI
,该组件用于管理 Kubernetes 群集(下游群集)的生命周期。在 ATIP 中,RKE2 CAPI 提供程序
也用于管理 RKE2 群集(下游群集)的生命周期。
通过上述所有组件,管理群集可以管理下游群集的生命周期,并使用声明性方法来管理基础架构和应用程序。
有关 SUSE Linux Enterprise Micro
的详细信息,请参见:SLE Micro(第 7 章 “SLE Micro”)
有关 RKE2
的详细信息,请参见:RKE2(第 14 章 “RKE2”)
有关 Rancher
的详细信息,请参见:Rancher(第 4 章 “Rancher”)
有关 Metal3
的详细信息,请参见:Metal3(第 8 章 “Metal3”)
29.2 设置管理群集的步骤 #
需要执行以下步骤来设置管理群集(使用单个节点):
使用声明性方法设置管理群集需要执行三个主要步骤:
为联网环境准备映像(第 29.3 节 “为联网环境准备映像”):第一步是准备包含所有必要配置的清单和文件,以便在联网环境中使用。
联网环境的目录结构(第 29.3.1 节 “目录结构”):此步骤创建一个目录结构,供 Edge Image Builder 用来存储配置文件和映像本身。
管理群集定义文件(第 29.3.2 节 “管理群集定义文件”):
mgmt-cluster.yaml
文件是管理群集的主定义文件。其中包含有关所要创建的映像的以下信息:映像信息:与要使用基础映像创建的映像相关的信息。
操作系统:要在映像中使用的操作系统配置。
Kubernetes:要在群集中使用的 Helm chart 和储存库、Kubernetes 版本、网络配置以及节点。
Custom 文件夹(第 29.3.3 节 “Custom 文件夹”):
custom
文件夹包含的配置文件和脚本供 Edge Image Builder 用来部署功能完备的管理群集。Files 文件夹:包含管理群集要使用的配置文件。
Scripts 文件夹:包含管理群集要使用的脚本。
Kubernetes 文件夹(第 29.3.4 节 “Kubernetes 文件夹”):
kubernetes
文件夹包含管理群集要使用的配置文件。Manifests 文件夹:包含管理群集要使用的清单。
Helm 文件夹:包含管理群集要使用的 Helm chart。
Config 文件夹:包含管理群集要使用的配置文件。
Network 文件夹(第 29.3.5 节 “Network 文件夹”):
network
文件夹包含管理群集节点要使用的网络配置文件。
为隔离环境准备映像(第 29.4 节 “为隔离环境准备映像”):此步骤用于显示差异,以准备好要在隔离方案中使用的清单和文件。
隔离环境的目录结构(第 29.4.1 节 “隔离环境的目录结构”):必须修改目录结构,以包含用于在隔离环境中运行管理群集的资源。
定义文件中的修改(第 29.4.2 节 “定义文件中的修改”):必须修改
mgmt-cluster.yaml
文件,以包含embeddedArtifactRegistry
部分,并将images
字段设置为要包含在 EIB 输出映像中的所有容器映像。custom 文件夹中的修改(第 29.4.3 节 “custom 文件夹中的修改”):必须修改
custom
文件夹,以包含用于在隔离环境中运行管理群集的资源。注册脚本:使用隔离环境时,必须去除
custom/scripts/99-register.sh
脚本。隔离资源:必须在
custom/files
文件夹中包含custom/files/airgap-resources.tar.gz
文件,该文件包含用于在隔离环境中运行管理群集的所有资源。脚本:必须修改
custom/scripts/99-mgmt-setup.sh
脚本,以提取airgap-resources.tar.gz
文件并将其复制到最终位置。必须修改custom/files/metal3.sh
脚本,以使用airgap-resources.tar.gz
文件中包含的本地资源,而不是从互联网下载资源。
创建映像(第 29.5 节 “映像创建”):此步骤使用 Edge Image Builder 工具创建映像(适用于联网方案和隔离方案)。在系统上运行 Edge Image Builder 工具之前请先检查先决条件(第 9 章 “Edge Image Builder”)。
置备管理群集(第 29.6 节 “置备管理群集”):此步骤使用上一步骤中创建的映像来置备管理群集(适用于联网方案和隔离方案)。可以使用便携式计算机、服务器、VM 或任何其他带有 USB 端口的 x86_64 系统来执行此步骤。
有关 Edge Image Builder 的详细信息,请参见 Edge Image Builder(第 9 章 “Edge Image Builder”)和 Edge Image Builder 快速入门(第 3 章 “使用 Edge Image Builder 配置独立群集”)。
29.3 为联网环境准备映像 #
使用 Edge Image Builder 为管理群集创建映像时可以自定义许多配置,但本文档只会介绍设置管理群集所需的最低限度配置。Edge Image Builder 通常从容器内部运行,因此,如果您目前无法运行容器,则首先需要安装 Podman 或 Rancher Desktop 之类的容器运行时。本指南假设您已经安装了可用的容器运行时。
此外,作为部署高可用性管理群集的先决条件,您需要在网络中预留三个 IP:- apiVIP
(表示 API VIP
地址,用于访问 Kubernetes API 服务器)。- ingressVIP
(表示入口 VIP 地址,由
Rancher UI 等组件使用)。- metal3VIP
(表示 Metal3 VIP 地址)。
29.3.1 目录结构 #
运行 EIB 时,将从主机挂载一个目录,因此首先需要创建一个目录结构,供 EIB 用来存储配置文件和映像本身。此目录采用以下结构:
eib ├── mgmt-cluster.yaml ├── network │ └── mgmt-cluster-node1.yaml ├── kubernetes │ ├── manifests │ │ ├── rke2-ingress-config.yaml │ │ ├── neuvector-namespace.yaml │ │ ├── ingress-l2-adv.yaml │ │ └── ingress-ippool.yaml │ ├── helm │ │ └── values │ │ ├── rancher.yaml │ │ ├── neuvector.yaml │ │ ├── metal3.yaml │ │ └── certmanager.yaml │ └── config │ └── server.yaml ├── custom │ ├── scripts │ │ ├── 99-register.sh │ │ ├── 99-mgmt-setup.sh │ │ └── 99-alias.sh │ └── files │ ├── rancher.sh │ ├── mgmt-stack-setup.service │ ├── metal3.sh │ └── basic-setup.sh └── base-images
必须从 SUSE Customer Center 或
SUSE 下载页面下载
SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso
映像,并且必须将它放在 base-images
文件夹中。
应检查该映像的 SHA256 校验和,确保它未遭篡改。可以在映像所下载到的位置找到校验和。
可以在 SUSE Edge GitHub 储存库中的“telco-examples”文件夹下找到目录结构的示例。
29.3.2 管理群集定义文件 #
mgmt-cluster.yaml
文件是管理群集的主定义文件。其中包含以下信息:
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso
outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: ${ROOT_PASSWORD}
packages:
packageList:
- git
- jq
sccRegistrationCode: ${SCC_REGISTRATION_CODE}
kubernetes:
version: ${KUBERNETES_VERSION}
helm:
charts:
- name: cert-manager
repositoryName: jetstack
version: 1.14.2
targetNamespace: cert-manager
valuesFile: certmanager.yaml
createNamespace: true
installationNamespace: kube-system
- name: longhorn-crd
version: 103.3.0+up1.6.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: longhorn
version: 103.3.0+up1.6.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: metal3-chart
version: 0.7.1
repositoryName: suse-edge-charts
targetNamespace: metal3-system
createNamespace: true
installationNamespace: kube-system
valuesFile: metal3.yaml
- name: neuvector-crd
version: 103.0.3+up2.7.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: neuvector
version: 103.0.3+up2.7.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: rancher
version: 2.8.4
repositoryName: rancher-prime
targetNamespace: cattle-system
createNamespace: true
installationNamespace: kube-system
valuesFile: rancher.yaml
repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: rancher-charts
url: https://charts.rancher.io/
- name: suse-edge-charts
url: oci://registry.suse.com/edge
- name: rancher-prime
url: https://charts.rancher.com/server-charts/prime
network:
apiHost: ${API_HOST}
apiVIP: ${API_VIP}
nodes:
- hostname: mgmt-cluster-node1
initializer: true
type: server
# - hostname: mgmt-cluster-node2
# initializer: true
# type: server
# - hostname: mgmt-cluster-node3
# initializer: true
# type: server
为了解释 mgmt-cluster.yaml
定义文件中的字段和值,我们将此文件划分成了以下几个部分。
映像部分(定义文件):
image:
imageType: iso
arch: x86_64
baseImage: SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso
outputImageName: eib-mgmt-cluster-image.iso
其中 baseImage
是从 SUSE Customer Center 或 SUSE
下载页面下载的原始映像。outputImageName
是将用于置备管理群集的新映像的名称。
操作系统部分(定义文件):
operatingSystem:
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: ${ROOT_PASSWORD}
packages:
packageList:
- jq
sccRegistrationCode: ${SCC_REGISTRATION_CODE}
其中 installDevice
是用于安装操作系统的设备,username
和 encryptedPassword
是用于访问系统的身份凭证,packageList
是要安装的软件包列表(在安装过程中,需要在内部使用
jq
),sccRegistrationCode
是在构建时用于获取软件包和依赖项的注册码,可从 SUSE Customer Center 获取。可以如下所示使用
openssl
命令生成加密的口令:
openssl passwd -6 MyPassword!123
此命令输出如下所示的内容:
$6$UrXB1sAGs46DOiSq$HSwi9GFJLCorm0J53nF2Sq8YEoyINhHcObHzX2R8h13mswUIsMwzx4eUzn/rRx0QPV4JIb0eWCoNrxGiKH4R31
Kubernetes 部分(定义文件):
kubernetes:
version: ${KUBERNETES_VERSION}
helm:
charts:
- name: cert-manager
repositoryName: jetstack
version: 1.14.2
targetNamespace: cert-manager
valuesFile: certmanager.yaml
createNamespace: true
installationNamespace: kube-system
- name: longhorn-crd
version: 103.3.0+up1.6.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: longhorn
version: 103.3.0+up1.6.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: metal3-chart
version: 0.7.1
repositoryName: suse-edge-charts
targetNamespace: metal3-system
createNamespace: true
installationNamespace: kube-system
valuesFile: metal3.yaml
- name: neuvector-crd
version: 103.0.3+up2.7.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: neuvector
version: 103.0.3+up2.7.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: rancher
version: 2.8.4
repositoryName: rancher-prime
targetNamespace: cattle-system
createNamespace: true
installationNamespace: kube-system
valuesFile: rancher.yaml
repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: rancher-charts
url: https://charts.rancher.io/
- name: suse-edge-charts
url: oci://registry.suse.com/edge
- name: rancher-prime
url: https://charts.rancher.com/server-charts/prime
network:
apiHost: ${API_HOST}
apiVIP: ${API_VIP}
nodes:
- hostname: mgmt-cluster1
initializer: true
type: server
# - hostname: mgmt-cluster2
# type: server
# - hostname: mgmt-cluster3
# type: server
其中 version
是要安装的 Kubernetes 版本。在本例中,我们将使用 RKE2
群集,因此版本必须低于 1.29(例如 v1.28.9+rke2r1
),以便与
Rancher
兼容。
helm
部分包含要安装的 Helm chart 列表、要使用的储存库,以及所有 chart 和储存库的版本配置。
network
部分包含 RKE2
组件要使用网络配置,例如
apiHost
和
apiVIP
。apiVIP
应是网络中未使用的 IP 地址,并且不属于
DHCP 池(如果使用 DHCP)。此外,如果我们在多节点群集中使用 apiVIP
,apiVIP 将用于访问
Kubernetes API 服务器。apiHost
是 RKE2
组件要使用的 apiVIP
的名称解析。
nodes
部分包含要在群集中使用的节点列表。nodes
部分包含要在群集中使用的节点列表。此示例使用的是单节点群集,但可以通过在列表中添加更多节点(通过取消注释相应的行),将其扩展为多节点群集。
节点的名称在群集中必须唯一,列表中第一个节点的 initializer
字段必须设置为
true
。节点的名称必须与 network
部分中定义的主机名相同,并且与
network
部分中的文件名直接匹配。
29.3.3 Custom 文件夹 #
custom
文件夹包含以下子文件夹:
... ├── custom │ ├── scripts │ │ ├── 99-register.sh │ │ ├── 99-mgmt-setup.sh │ │ └── 99-alias.sh │ └── files │ ├── rancher.sh │ ├── mgmt-stack-setup.service │ ├── metal3.sh │ └── basic-setup.sh ...
custom/files
文件夹包含管理群集要使用的配置文件。custom/scripts
文件夹包含管理群集要使用的脚本。
custom/files
文件夹包含以下文件:
basic-setup.sh
:包含有关要使用的Metal3
版本的配置参数,以及Rancher
和MetalLB
基本参数。请仅在您要更改所要使用的组件或名称空间的版本时才修改此文件。#!/bin/bash # Pre-requisites. Cluster already running export KUBECTL="/var/lib/rancher/rke2/bin/kubectl" export KUBECONFIG="/etc/rancher/rke2/rke2.yaml" ################## # METAL3 DETAILS # ################## export METAL3_CHART_TARGETNAMESPACE="metal3-system" export METAL3_CLUSTERCTLVERSION="1.6.2" export METAL3_CAPICOREVERSION="1.6.2" export METAL3_CAPIMETAL3VERSION="1.6.0" export METAL3_CAPIRKE2VERSION="0.2.6" export METAL3_CAPIPROVIDER="rke2" export METAL3_CAPISYSTEMNAMESPACE="capi-system" export METAL3_RKE2BOOTSTRAPNAMESPACE="rke2-bootstrap-system" export METAL3_CAPM3NAMESPACE="capm3-system" export METAL3_RKE2CONTROLPLANENAMESPACE="rke2-control-plane-system" export METAL3_CAPI_IMAGES="registry.suse.com/edge" # Or registry.opensuse.org/isv/suse/edge/clusterapi/containerfile/suse for the upstream ones ########### # METALLB # ########### export METALLBNAMESPACE="metallb-system" ########### # RANCHER # ########### export RANCHER_CHART_TARGETNAMESPACE="cattle-system" export RANCHER_FINALPASSWORD="adminadminadmin" die(){ echo ${1} 1>&2 exit ${2} }
metal3.sh
:包含要使用的Metal3
组件的配置(无需修改)。在将来的版本中将替换此脚本,以改用Rancher Turtles
来简化配置。#!/bin/bash set -euo pipefail BASEDIR="$(dirname "$0")" source ${BASEDIR}/basic-setup.sh METAL3LOCKNAMESPACE="default" METAL3LOCKCMNAME="metal3-lock" trap 'catch $? $LINENO' EXIT catch() { if [ "$1" != "0" ]; then echo "Error $1 occurred on $2" ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} fi } # Get or create the lock to run all those steps just in a single node # As the first node is created WAY before the others, this should be enough # TODO: Investigate if leases is better if [ $(${KUBECTL} get cm -n ${METAL3LOCKNAMESPACE} ${METAL3LOCKCMNAME} -o name | wc -l) -lt 1 ]; then ${KUBECTL} create configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} --from-literal foo=bar else exit 0 fi # Wait for metal3 while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CHART_TARGETNAMESPACE} -l app.kubernetes.io/name=metal3-ironic -o name) --timeout=10s; do sleep 2 ; done # Get the ironic IP IRONICIP=$(${KUBECTL} get cm -n ${METAL3_CHART_TARGETNAMESPACE} ironic-bmo -o jsonpath='{.data.IRONIC_IP}') # If LoadBalancer, use metallb, else it is NodePort if [ $(${KUBECTL} get svc -n ${METAL3_CHART_TARGETNAMESPACE} metal3-metal3-ironic -o jsonpath='{.spec.type}') == "LoadBalancer" ]; then # Wait for metallb while ! ${KUBECTL} wait --for condition=ready -n ${METALLBNAMESPACE} $(${KUBECTL} get pods -n ${METALLBNAMESPACE} -l app.kubernetes.io/component=controller -o name) --timeout=10s; do sleep 2 ; done # Do not create the ippool if already created ${KUBECTL} get ipaddresspool -n ${METALLBNAMESPACE} ironic-ip-pool -o name || cat <<-EOF | ${KUBECTL} apply -f - apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ironic-ip-pool namespace: ${METALLBNAMESPACE} spec: addresses: - ${IRONICIP}/32 serviceAllocation: priority: 100 serviceSelectors: - matchExpressions: - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]} EOF # Same for L2 Advs ${KUBECTL} get L2Advertisement -n ${METALLBNAMESPACE} ironic-ip-pool-l2-adv -o name || cat <<-EOF | ${KUBECTL} apply -f - apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: ironic-ip-pool-l2-adv namespace: ${METALLBNAMESPACE} spec: ipAddressPools: - ironic-ip-pool EOF fi # If clusterctl is not installed, install it if ! command -v clusterctl > /dev/null 2>&1; then LINUXARCH=$(uname -m) case $(uname -m) in "x86_64") export GOARCH="amd64" ;; "aarch64") export GOARCH="arm64" ;; "*") echo "Arch not found, asumming amd64" export GOARCH="amd64" ;; esac # Clusterctl bin # Maybe just use the binary from hauler if available curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v${METAL3_CLUSTERCTLVERSION}/clusterctl-linux-${GOARCH} -o /usr/local/bin/clusterctl chmod +x /usr/local/bin/clusterctl fi # If rancher is deployed if [ $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name | wc -l) -ge 1 ]; then cat <<-EOF | ${KUBECTL} apply -f - apiVersion: management.cattle.io/v3 kind: Feature metadata: name: embedded-cluster-api spec: value: false EOF # Disable Rancher webhooks for CAPI ${KUBECTL} delete mutatingwebhookconfiguration.admissionregistration.k8s.io mutating-webhook-configuration ${KUBECTL} delete validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration ${KUBECTL} wait --for=delete namespace/cattle-provisioning-capi-system --timeout=300s fi # Deploy CAPI if [ $(${KUBECTL} get pods -n ${METAL3_CAPISYSTEMNAMESPACE} -o name | wc -l) -lt 1 ]; then # https://github.com/rancher-sandbox/cluster-api-provider-rke2#setting-up-clusterctl mkdir -p ~/.cluster-api cat <<-EOF > ~/.cluster-api/clusterctl.yaml images: all: repository: ${METAL3_CAPI_IMAGES} EOF # Try this command 3 times just in case, stolen from https://stackoverflow.com/a/33354419 if ! (r=3; while ! clusterctl init \ --core "cluster-api:v${METAL3_CAPICOREVERSION}"\ --infrastructure "metal3:v${METAL3_CAPIMETAL3VERSION}"\ --bootstrap "${METAL3_CAPIPROVIDER}:v${METAL3_CAPIRKE2VERSION}"\ --control-plane "${METAL3_CAPIPROVIDER}:v${METAL3_CAPIRKE2VERSION}" ; do ((--r))||exit echo "Something went wrong, let's wait 10 seconds and retry" sleep 10;done) ; then echo "clusterctl failed" exit 1 fi # Wait for capi-controller-manager while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CAPISYSTEMNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CAPISYSTEMNAMESPACE} -l cluster.x-k8s.io/provider=cluster-api -o name) --timeout=10s; do sleep 2 ; done # Wait for capm3-controller-manager, there are two pods, the ipam and the capm3 one, just wait for the first one while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CAPM3NAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CAPM3NAMESPACE} -l cluster.x-k8s.io/provider=infrastructure-metal3 -o name | head -n1 ) --timeout=10s; do sleep 2 ; done # Wait for rke2-bootstrap-controller-manager while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_RKE2BOOTSTRAPNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_RKE2BOOTSTRAPNAMESPACE} -l cluster.x-k8s.io/provider=bootstrap-rke2 -o name) --timeout=10s; do sleep 2 ; done # Wait for rke2-control-plane-controller-manager while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_RKE2CONTROLPLANENAMESPACE} $(${KUBECTL} get pods -n ${METAL3_RKE2CONTROLPLANENAMESPACE} -l cluster.x-k8s.io/provider=control-plane-rke2 -o name) --timeout=10s; do sleep 2 ; done fi # Clean up the lock cm ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
rancher.sh
:包含要使用的Rancher
组件的配置(无需修改)。#!/bin/bash set -euo pipefail BASEDIR="$(dirname "$0")" source ${BASEDIR}/basic-setup.sh RANCHERLOCKNAMESPACE="default" RANCHERLOCKCMNAME="rancher-lock" if [ -z "${RANCHER_FINALPASSWORD}" ]; then # If there is no final password, then finish the setup right away exit 0 fi trap 'catch $? $LINENO' EXIT catch() { if [ "$1" != "0" ]; then echo "Error $1 occurred on $2" ${KUBECTL} delete configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE} fi } # Get or create the lock to run all those steps just in a single node # As the first node is created WAY before the others, this should be enough # TODO: Investigate if leases is better if [ $(${KUBECTL} get cm -n ${RANCHERLOCKNAMESPACE} ${RANCHERLOCKCMNAME} -o name | wc -l) -lt 1 ]; then ${KUBECTL} create configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE} --from-literal foo=bar else exit 0 fi # Wait for rancher to be deployed while ! ${KUBECTL} wait --for condition=ready -n ${RANCHER_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name) --timeout=10s; do sleep 2 ; done until ${KUBECTL} get ingress -n ${RANCHER_CHART_TARGETNAMESPACE} rancher > /dev/null 2>&1; do sleep 10; done RANCHERBOOTSTRAPPASSWORD=$(${KUBECTL} get secret -n ${RANCHER_CHART_TARGETNAMESPACE} bootstrap-secret -o jsonpath='{.data.bootstrapPassword}' | base64 -d) RANCHERHOSTNAME=$(${KUBECTL} get ingress -n ${RANCHER_CHART_TARGETNAMESPACE} rancher -o jsonpath='{.spec.rules[0].host}') # Skip the whole process if things have been set already if [ -z $(${KUBECTL} get settings.management.cattle.io first-login -ojsonpath='{.value}') ]; then # Add the protocol RANCHERHOSTNAME="https://${RANCHERHOSTNAME}" TOKEN="" while [ -z "${TOKEN}" ]; do # Get token sleep 2 TOKEN=$(curl -sk -X POST ${RANCHERHOSTNAME}/v3-public/localProviders/local?action=login -H 'content-type: application/json' -d "{\"username\":\"admin\",\"password\":\"${RANCHERBOOTSTRAPPASSWORD}\"}" | jq -r .token) done # Set password curl -sk ${RANCHERHOSTNAME}/v3/users?action=changepassword -H 'content-type: application/json' -H "Authorization: Bearer $TOKEN" -d "{\"currentPassword\":\"${RANCHERBOOTSTRAPPASSWORD}\",\"newPassword\":\"${RANCHER_FINALPASSWORD}\"}" # Create a temporary API token (ttl=60 minutes) APITOKEN=$(curl -sk ${RANCHERHOSTNAME}/v3/token -H 'content-type: application/json' -H "Authorization: Bearer ${TOKEN}" -d '{"type":"token","description":"automation","ttl":3600000}' | jq -r .token) curl -sk ${RANCHERHOSTNAME}/v3/settings/server-url -H 'content-type: application/json' -H "Authorization: Bearer ${APITOKEN}" -X PUT -d "{\"name\":\"server-url\",\"value\":\"${RANCHERHOSTNAME}\"}" curl -sk ${RANCHERHOSTNAME}/v3/settings/telemetry-opt -X PUT -H 'content-type: application/json' -H 'accept: application/json' -H "Authorization: Bearer ${APITOKEN}" -d '{"value":"out"}' fi # Clean up the lock cm ${KUBECTL} delete configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE}
mgmt-stack-setup.service
:包含用于创建 systemd 服务,以便在首次引导期间运行脚本的配置(无需修改)。[Unit] Description=Setup Management stack components Wants=network-online.target # It requires rke2 or k3s running, but it will not fail if those services are not present After=network.target network-online.target rke2-server.service k3s.service # At least, the basic-setup.sh one needs to be present ConditionPathExists=/opt/mgmt/bin/basic-setup.sh [Service] User=root Type=forking # Metal3 can take A LOT to download the IPA image TimeoutStartSec=1800 ExecStartPre=/bin/sh -c "echo 'Setting up Management components...'" # Scripts are executed in StartPre because Start can only run a single on ExecStartPre=/opt/mgmt/bin/rancher.sh ExecStartPre=/opt/mgmt/bin/metal3.sh ExecStart=/bin/sh -c "echo 'Finished setting up Management components'" RemainAfterExit=yes KillMode=process # Disable & delete everything ExecStartPost=rm -f /opt/mgmt/bin/rancher.sh ExecStartPost=rm -f /opt/mgmt/bin/metal3.sh ExecStartPost=rm -f /opt/mgmt/bin/basic-setup.sh ExecStartPost=/bin/sh -c "systemctl disable mgmt-stack-setup.service" ExecStartPost=rm -f /etc/systemd/system/mgmt-stack-setup.service [Install] WantedBy=multi-user.target
custom/scripts
文件夹包含以下文件:
99-alias.sh
脚本:包含管理群集在首次引导时用来加载 kubeconfig 文件的别名(无需修改)。#!/bin/bash echo "alias k=kubectl" >> /etc/profile.local echo "alias kubectl=/var/lib/rancher/rke2/bin/kubectl" >> /etc/profile.local echo "export KUBECONFIG=/etc/rancher/rke2/rke2.yaml" >> /etc/profile.local
99-mgmt-setup.sh
脚本:包含首次引导期间用于复制脚本的配置(无需修改)。#!/bin/bash # Copy the scripts from combustion to the final location mkdir -p /opt/mgmt/bin/ for script in basic-setup.sh rancher.sh metal3.sh; do cp ${script} /opt/mgmt/bin/ done # Copy the systemd unit file and enable it at boot cp mgmt-stack-setup.service /etc/systemd/system/mgmt-stack-setup.service systemctl enable mgmt-stack-setup.service
99-register.sh
脚本:包含用于通过 SCC 注册码注册系统的配置。必须正确设置${SCC_ACCOUNT_EMAIL}
和${SCC_REGISTRATION_CODE}
才能使用您的帐户注册系统。#!/bin/bash set -euo pipefail # Registration https://www.suse.com/support/kb/doc/?id=000018564 if ! which SUSEConnect > /dev/null 2>&1; then zypper --non-interactive install suseconnect-ng fi SUSEConnect --email "${SCC_ACCOUNT_EMAIL}" --url "https://scc.suse.com" --regcode "${SCC_REGISTRATION_CODE}"
29.3.4 Kubernetes 文件夹 #
kubernetes
文件夹包含以下子文件夹:
... ├── kubernetes │ ├── manifests │ │ ├── rke2-ingress-config.yaml │ │ ├── neuvector-namespace.yaml │ │ ├── ingress-l2-adv.yaml │ │ └── ingress-ippool.yaml │ ├── helm │ │ └── values │ │ ├── rancher.yaml │ │ ├── neuvector.yaml │ │ ├── metal3.yaml │ │ └── certmanager.yaml │ └── config │ └── server.yaml ...
kubernetes/config
文件夹包含以下文件:
server.yaml
:默认安装的CNI
插件是Cilium
,因此不需要创建此文件夹和文件。如果您需要自定义CNI
插件,可以使用kubernetes/config
文件夹中的server.yaml
文件。该文件包含以下信息:cni: - multus - cilium
这是一个可选文件,用于定义某些 Kubernetes 自定义设置,例如要使用的 CNI 插件,或官方文档中所述的许多选项。
kubernetes/manifests
文件夹包含以下文件:
rke2-ingress-config.yaml
:包含用于为管理群集创建入口
服务的配置(无需修改)。apiVersion: helm.cattle.io/v1 kind: HelmChartConfig metadata: name: rke2-ingress-nginx namespace: kube-system spec: valuesContent: |- controller: config: use-forwarded-headers: "true" enable-real-ip: "true" publishService: enabled: true service: enabled: true type: LoadBalancer externalTrafficPolicy: Local
neuvector-namespace.yaml
:包含用于创建NeuVector
名称空间的配置(无需修改)。apiVersion: v1 kind: Namespace metadata: labels: pod-security.kubernetes.io/enforce: privileged name: neuvector
ingress-l2-adv.yaml
:包含用于为MetalLB
组件创建L2Advertisement
的配置(无需修改)。apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: ingress-l2-adv namespace: metallb-system spec: ipAddressPools: - ingress-ippool
ingress-ippool.yaml
:包含用于为rke2-ingress-nginx
组件创建IPAddressPool
的配置。必须正确设置${INGRESS_VIP}
,以定义预留给rke2-ingress-nginx
组件使用的 IP 地址。apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ingress-ippool namespace: metallb-system spec: addresses: - ${INGRESS_VIP}/32 serviceAllocation: priority: 100 serviceSelectors: - matchExpressions: - {key: app.kubernetes.io/name, operator: In, values: [rke2-ingress-nginx]}
kubernetes/helm/values
文件夹包含以下文件:
rancher.yaml
:包含用于创建Rancher
组件的配置。必须正确设置${INGRESS_VIP}
,以定义Rancher
组件要使用的 IP 地址。用于访问Rancher
组件的 URL 为https://rancher-${INGRESS_VIP}.sslip.io
。hostname: rancher-${INGRESS_VIP}.sslip.io bootstrapPassword: "foobar" replicas: 1 global.cattle.psp.enabled: "false"
neuvector.yaml
:包含用于创建NeuVector
组件的配置(无需修改)。controller: replicas: 1 ranchersso: enabled: true manager: enabled: false cve: scanner: enabled: false replicas: 1 k3s: enabled: true crdwebhook: enabled: false
metal3.yaml
:包含用于创建Metal3
组件的配置。必须正确设置${METAL3_VIP}
,以定义Metal3
组件要使用的 IP 地址。global: ironicIP: ${METAL3_VIP} enable_vmedia_tls: false additionalTrustedCAs: false metal3-ironic: global: predictableNicNames: "true" persistence: ironic: size: "5Gi"
媒体服务器是 Metal3 中包含的可选功能(默认处于禁用状态)。要使用该 Metal3 功能,需要在前面所述的清单中配置该功能。要使用 Metal3 媒体服务器,请指定以下变量:
在 global 部分,将
enable_metal3_media_server
设置为true
以启用媒体服务器功能。包含有关媒体服务器的以下配置,其中 ${MEDIA_VOLUME_PATH} 是媒体卷在媒体中的路径(例如
/home/metal3/bmh-image-cache
)metal3-media: mediaVolume: hostPath: ${MEDIA_VOLUME_PATH}
可以使用外部媒体服务器来存储映像,如果您要将该服务器与 TLS 配合使用,则需要修改以下配置:
将前面所述
metal3.yaml
文件中的additionalTrustedCAs
设置为true
,以启用来自外部媒体服务器的附加可信 CA。在
kubernetes/manifests/metal3-cacert-secret.yaml
文件夹中包含以下密钥配置,以存储外部媒体服务器的 CA 证书。apiVersion: v1 kind: Namespace metadata: name: metal3-system --- apiVersion: v1 kind: Secret metadata: name: tls-ca-additional namespace: metal3-system type: Opaque data: ca-additional.crt: {{ additional_ca_cert | b64encode }}
additional_ca_cert
是外部媒体服务器的 base64 编码 CA
证书。可使用以下命令对证书进行编码并手动生成密钥:
kubectl -n meta3-system create secret generic tls-ca-additional --from-file=ca-additional.crt=./ca-additional.crt
certmanager.yaml
:包含用于创建Cert-Manager
组件的配置(无需修改)。installCRDs: "true"
29.3.5 Network 文件夹 #
network
文件夹中的文件数与管理群集中的节点数一样多。在本例中,我们只有一个节点,因此只有一个文件,其名为
mgmt-cluster-node1.yaml
。该文件的名称必须与
mgmt-cluster.yaml
定义文件的上述 network/node 部分中定义的主机名相匹配。
如果您需要自定义网络配置,例如要使用特定的静态 IP 地址(无 DHCP 的方案),可以使用 network
文件夹中的 mgmt-cluster-node1.yaml
文件。该文件包含以下信息:
${MGMT_GATEWAY}
:网关 IP 地址。${MGMT_DNS}
:DNS 服务器 IP 地址。${MGMT_MAC}
:网络接口的 MAC 地址。${MGMT_NODE_IP}
:管理群集的 IP 地址。
routes:
config:
- destination: 0.0.0.0/0
metric: 100
next-hop-address: ${MGMT_GATEWAY}
next-hop-interface: eth0
table-id: 254
dns-resolver:
config:
server:
- ${MGMT_DNS}
- 8.8.8.8
interfaces:
- name: eth0
type: ethernet
state: up
mac-address: ${MGMT_MAC}
ipv4:
address:
- ip: ${MGMT_NODE_IP}
prefix-length: 24
dhcp: false
enabled: true
ipv6:
enabled: false
如果您要使用 DHCP 获取 IP 地址,可使用以下配置(必须使用 ${MGMT_MAC}
变量正确设置
MAC
地址):
## This is an example of a dhcp network configuration for a management cluster
## interfaces:
- name: eth0
type: ethernet
state: up
mac-address: ${MGMT_MAC}
ipv4:
dhcp: true
enabled: true
ipv6:
enabled: false
根据管理群集中的节点数,您可以创建更多文件(例如
mgmt-cluster-node2.yaml
、mgmt-cluster-node3.yaml
等)来配置其余节点。routes
部分用于定义管理群集的路由表。
29.4 为隔离环境准备映像 #
本节介绍如何为隔离环境准备映像,其中只说明了与前面几节内容存在的差别。为隔离环境准备映像需要对上一节(为联网环境准备映像(第 29.3 节 “为联网环境准备映像”))的内容进行以下更改:
必须修改
mgmt-cluster.yaml
文件,以包含embeddedArtifactRegistry
部分,并将images
字段设置为要包含在 EIB 输出映像中的所有容器映像。使用隔离环境时,必须去除
custom/scripts/99-register.sh
脚本。必须在
custom/files
文件夹中包含custom/files/airgap-resources.tar.gz
文件,该文件包含用于在隔离环境中运行管理群集的所有资源。必须修改
custom/scripts/99-mgmt-setup.sh
脚本,以提取airgap-resources.tar.gz
文件并将其复制到最终位置。必须修改
custom/files/metal3.sh
脚本,以使用airgap-resources.tar.gz
文件中包含的本地资源,而不是从互联网下载资源。
29.4.1 隔离环境的目录结构 #
除了下面所述的差别之外,隔离环境与联网环境的目录结构在其他方面相同:
eib |-- base-images | |-- SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso |-- custom | |-- files | | |-- airgap-resources.tar.gz | | |-- basic-setup.sh | | |-- metal3.sh | | |-- mgmt-stack-setup.service | | |-- rancher.sh | |-- scripts | |-- 99-alias.sh | |-- 99-mgmt-setup.sh |-- kubernetes | |-- config | | |-- server.yaml | |-- helm | | |-- values | | |-- certmanager.yaml | | |-- metal3.yaml | | |-- neuvector.yaml | | |-- rancher.yaml | |-- manifests | |-- neuvector-namespace.yaml |-- mgmt-cluster.yaml |-- network |-- mgmt-cluster-network.yaml
在启动设置过程之前,必须从 SUSE Customer
Center 或 SUSE 下载页面下载
SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso
映像,并且必须将它放在 base-images
文件夹中。
应检查该映像的 SHA256 校验和,确保它未遭篡改。可以在映像所下载到的位置找到校验和。
可以在 SUSE Edge GitHub 储存库中的“telco-examples”文件夹下找到目录结构的示例。
29.4.2 定义文件中的修改 #
必须修改 mgmt-cluster.yaml
文件,以包含
embeddedArtifactRegistry
部分,并将 images
字段设置为要包含在 EIB 输出映像中的所有容器映像。images
字段必须包含要放入输出映像中的所有容器映像的列表。下面是包含 embeddedArtifactRegistry
部分的 mgmt-cluster.yaml
文件示例:
apiVersion: 1.0
image:
imageType: iso
arch: x86_64
baseImage: SLE-Micro.x86_64-5.5.0-Default-SelfInstall-GM2.install.iso
outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: ${ROOT_PASSWORD}
packages:
packageList:
- jq
sccRegistrationCode: ${SCC_REGISTRATION_CODE}
kubernetes:
version: ${KUBERNETES_VERSION}
helm:
charts:
- name: cert-manager
repositoryName: jetstack
version: 1.14.2
targetNamespace: cert-manager
valuesFile: certmanager.yaml
createNamespace: true
installationNamespace: kube-system
- name: longhorn-crd
version: 103.3.0+up1.6.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: longhorn
version: 103.3.0+up1.6.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: metal3-chart
version: 0.7.1
repositoryName: suse-edge-charts
targetNamespace: metal3-system
createNamespace: true
installationNamespace: kube-system
valuesFile: metal3.yaml
- name: neuvector-crd
version: 103.0.3+up2.7.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: neuvector
version: 103.0.3+up2.7.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: rancher
version: 2.8.4
repositoryName: rancher-prime
targetNamespace: cattle-system
createNamespace: true
installationNamespace: kube-system
valuesFile: rancher.yaml
repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: rancher-charts
url: https://charts.rancher.io/
- name: suse-edge-charts
url: oci://registry.suse.com/edge
- name: rancher-prime
url: https://charts.rancher.com/server-charts/prime
network:
apiHost: ${API_HOST}
apiVIP: ${API_VIP}
nodes:
- hostname: mgmt-cluster-node1
initializer: true
type: server
# - hostname: mgmt-cluster-node2
# initializer: true
# type: server
# - hostname: mgmt-cluster-node3
# initializer: true
# type: server
embeddedArtifactRegistry:
images:
- name: registry.rancher.com/rancher/backup-restore-operator:v4.0.2
- name: registry.rancher.com/rancher/calico-cni:v3.27.0-rancher1
- name: registry.rancher.com/rancher/cis-operator:v1.0.13
- name: registry.rancher.com/rancher/coreos-kube-state-metrics:v1.9.7
- name: registry.rancher.com/rancher/coreos-prometheus-config-reloader:v0.38.1
- name: registry.rancher.com/rancher/coreos-prometheus-operator:v0.38.1
- name: registry.rancher.com/rancher/flannel-cni:v0.3.0-rancher9
- name: registry.rancher.com/rancher/fleet-agent:v0.9.4
- name: registry.rancher.com/rancher/fleet:v0.9.4
- name: registry.rancher.com/rancher/gitjob:v0.9.7
- name: registry.rancher.com/rancher/grafana-grafana:7.1.5
- name: registry.rancher.com/rancher/hardened-addon-resizer:1.8.20-build20240410
- name: registry.rancher.com/rancher/hardened-calico:v3.27.3-build20240423
- name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.8.10-build20240124
- name: registry.rancher.com/rancher/hardened-cni-plugins:v1.4.1-build20240325
- name: registry.rancher.com/rancher/hardened-coredns:v1.11.1-build20240305
- name: registry.rancher.com/rancher/hardened-dns-node-cache:1.22.28-build20240125
- name: registry.rancher.com/rancher/hardened-etcd:v3.5.9-k3s1-build20240418
- name: registry.rancher.com/rancher/hardened-flannel:v0.25.1-build20240423
- name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.7.1-build20240401
- name: registry.rancher.com/rancher/hardened-kubernetes:v1.28.9-rke2r1-build20240416
- name: registry.rancher.com/rancher/hardened-multus-cni:v4.0.2-build20240208
- name: registry.rancher.com/rancher/hardened-node-feature-discovery:v0.14.1-build20230926
- name: registry.rancher.com/rancher/hardened-whereabouts:v0.6.3-build20240208
- name: registry.rancher.com/rancher/helm-project-operator:v0.2.1
- name: registry.rancher.com/rancher/istio-kubectl:1.5.10
- name: registry.rancher.com/rancher/jimmidyson-configmap-reload:v0.3.0
- name: registry.rancher.com/rancher/k3s-upgrade:v1.28.9-k3s1
- name: registry.rancher.com/rancher/klipper-helm:v0.8.3-build20240228
- name: registry.rancher.com/rancher/klipper-lb:v0.4.7
- name: registry.rancher.com/rancher/kube-api-auth:v0.2.1
- name: registry.rancher.com/rancher/kubectl:v1.28.7
- name: registry.rancher.com/rancher/library-nginx:1.19.2-alpine
- name: registry.rancher.com/rancher/local-path-provisioner:v0.0.26
- name: registry.rancher.com/rancher/machine:v0.15.0-rancher112
- name: registry.rancher.com/rancher/mirrored-cluster-api-controller:v1.4.4
- name: registry.rancher.com/rancher/nginx-ingress-controller:nginx-1.9.6-rancher1
- name: registry.rancher.com/rancher/pause:3.6
- name: registry.rancher.com/rancher/prom-alertmanager:v0.21.0
- name: registry.rancher.com/rancher/prom-node-exporter:v1.0.1
- name: registry.rancher.com/rancher/prom-prometheus:v2.18.2
- name: registry.rancher.com/rancher/prometheus-auth:v0.2.2
- name: registry.rancher.com/rancher/prometheus-federator:v0.3.4
- name: registry.rancher.com/rancher/pushprox-client:v0.1.0-rancher2-client
- name: registry.rancher.com/rancher/pushprox-proxy:v0.1.0-rancher2-proxy
- name: registry.rancher.com/rancher/rancher-agent:v2.8.4
- name: registry.rancher.com/rancher/rancher-csp-adapter:v3.0.1
- name: registry.rancher.com/rancher/rancher-webhook:v0.4.5
- name: registry.rancher.com/rancher/rancher:v2.8.4
- name: registry.rancher.com/rancher/rke-tools:v0.1.96
- name: registry.rancher.com/rancher/rke2-cloud-provider:v1.29.3-build20240412
- name: registry.rancher.com/rancher/rke2-runtime:v1.28.9-rke2r1
- name: registry.rancher.com/rancher/rke2-upgrade:v1.28.9-rke2r1
- name: registry.rancher.com/rancher/security-scan:v0.2.15
- name: registry.rancher.com/rancher/shell:v0.1.24
- name: registry.rancher.com/rancher/system-agent-installer-k3s:v1.28.9-k3s1
- name: registry.rancher.com/rancher/system-agent-installer-rke2:v1.28.9-rke2r1
- name: registry.rancher.com/rancher/system-agent:v0.3.6-suc
- name: registry.rancher.com/rancher/system-upgrade-controller:v0.13.1
- name: registry.rancher.com/rancher/ui-plugin-catalog:1.3.0
- name: registry.rancher.com/rancher/ui-plugin-operator:v0.1.1
- name: registry.rancher.com/rancher/webhook-receiver:v0.2.5
- name: registry.rancher.com/rancher/kubectl:v1.20.2
- name: registry.rancher.com/rancher/mirrored-longhornio-csi-attacher:v4.4.2
- name: registry.rancher.com/rancher/mirrored-longhornio-csi-provisioner:v3.6.2
- name: registry.rancher.com/rancher/mirrored-longhornio-csi-resizer:v1.9.2
- name: registry.rancher.com/rancher/mirrored-longhornio-csi-snapshotter:v6.3.2
- name: registry.rancher.com/rancher/mirrored-longhornio-csi-node-driver-registrar:v2.9.2
- name: registry.rancher.com/rancher/mirrored-longhornio-livenessprobe:v2.12.0
- name: registry.rancher.com/rancher/mirrored-longhornio-backing-image-manager:v1.6.1
- name: registry.rancher.com/rancher/mirrored-longhornio-longhorn-engine:v1.6.1
- name: registry.rancher.com/rancher/mirrored-longhornio-longhorn-instance-manager:v1.6.1
- name: registry.rancher.com/rancher/mirrored-longhornio-longhorn-manager:v1.6.1
- name: registry.rancher.com/rancher/mirrored-longhornio-longhorn-share-manager:v1.6.1
- name: registry.rancher.com/rancher/mirrored-longhornio-longhorn-ui:v1.6.1
- name: registry.rancher.com/rancher/mirrored-longhornio-support-bundle-kit:v0.0.36
- name: registry.suse.com/edge/cluster-api-provider-rke2-bootstrap:v0.2.6
- name: registry.suse.com/edge/cluster-api-provider-rke2-controlplane:v0.2.6
- name: registry.suse.com/edge/cluster-api-controller:v1.6.2
- name: registry.suse.com/edge/cluster-api-provider-metal3:v1.6.0
- name: registry.suse.com/edge/ip-address-manager:v1.6.0
29.4.3 custom 文件夹中的修改 #
使用隔离环境时,必须去除
custom/scripts/99-register.sh
脚本。如目录结构中所示,99-register.sh
脚本并未包含在custom/scripts
文件夹中。必须修改
custom/scripts/99-mgmt-setup.sh
脚本,以提取airgap-resources.tar.gz
文件并将其复制到最终位置。下面是经过修改的、用于提取和复制airgap-resources.tar.gz
文件的99-mgmt-setup.sh
脚本示例:#!/bin/bash # Copy the scripts from combustion to the final location mkdir -p /opt/mgmt/bin/ for script in basic-setup.sh rancher.sh metal3.sh; do cp ${script} /opt/mgmt/bin/ done # Copy the systemd unit file and enable it at boot cp mgmt-stack-setup.service /etc/systemd/system/mgmt-stack-setup.service systemctl enable mgmt-stack-setup.service # Extract the airgap resources tar zxf airgap-resources.tar.gz # Copy the clusterctl binary to the final location cp airgap-resources/clusterctl /opt/mgmt/bin/ && chmod +x /opt/mgmt/bin/clusterctl # Copy the clusterctl.yaml and override mkdir -p /root/cluster-api cp -r airgap-resources/clusterctl.yaml airgap-resources/overrides /root/cluster-api/
必须修改
custom/files/metal3.sh
脚本,以使用airgap-resources.tar.gz
文件中包含的本地资源,而不是从互联网下载资源。下面是经过修改的、使用本地资源的metal3.sh
脚本示例:#!/bin/bash set -euo pipefail BASEDIR="$(dirname "$0")" source ${BASEDIR}/basic-setup.sh METAL3LOCKNAMESPACE="default" METAL3LOCKCMNAME="metal3-lock" trap 'catch $? $LINENO' EXIT catch() { if [ "$1" != "0" ]; then echo "Error $1 occurred on $2" ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} fi } # Get or create the lock to run all those steps just in a single node # As the first node is created WAY before the others, this should be enough # TODO: Investigate if leases is better if [ $(${KUBECTL} get cm -n ${METAL3LOCKNAMESPACE} ${METAL3LOCKCMNAME} -o name | wc -l) -lt 1 ]; then ${KUBECTL} create configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} --from-literal foo=bar else exit 0 fi # Wait for metal3 while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CHART_TARGETNAMESPACE} -l app.kubernetes.io/name=metal3-ironic -o name) --timeout=10s; do sleep 2 ; done # If rancher is deployed if [ $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name | wc -l) -ge 1 ]; then cat <<-EOF | ${KUBECTL} apply -f - apiVersion: management.cattle.io/v3 kind: Feature metadata: name: embedded-cluster-api spec: value: false EOF # Disable Rancher webhooks for CAPI ${KUBECTL} delete mutatingwebhookconfiguration.admissionregistration.k8s.io mutating-webhook-configuration ${KUBECTL} delete validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration ${KUBECTL} wait --for=delete namespace/cattle-provisioning-capi-system --timeout=300s fi # Deploy CAPI if [ $(${KUBECTL} get pods -n ${METAL3_CAPISYSTEMNAMESPACE} -o name | wc -l) -lt 1 ]; then # Try this command 3 times just in case, stolen from https://stackoverflow.com/a/33354419 if ! (r=3; while ! /opt/mgmt/bin/clusterctl init \ --core "cluster-api:v${METAL3_CAPICOREVERSION}"\ --infrastructure "metal3:v${METAL3_CAPIMETAL3VERSION}"\ --bootstrap "${METAL3_CAPIPROVIDER}:v${METAL3_CAPIRKE2VERSION}"\ --control-plane "${METAL3_CAPIPROVIDER}:v${METAL3_CAPIRKE2VERSION}"\ --config /root/cluster-api/clusterctl.yaml ; do ((--r))||exit echo "Something went wrong, let's wait 10 seconds and retry" sleep 10;done) ; then echo "clusterctl failed" exit 1 fi # Wait for capi-controller-manager while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CAPISYSTEMNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CAPISYSTEMNAMESPACE} -l cluster.x-k8s.io/provider=cluster-api -o name) --timeout=10s; do sleep 2 ; done # Wait for capm3-controller-manager, there are two pods, the ipam and the capm3 one, just wait for the first one while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CAPM3NAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CAPM3NAMESPACE} -l cluster.x-k8s.io/provider=infrastructure-metal3 -o name | head -n1 ) --timeout=10s; do sleep 2 ; done # Wait for rke2-bootstrap-controller-manager while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_RKE2BOOTSTRAPNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_RKE2BOOTSTRAPNAMESPACE} -l cluster.x-k8s.io/provider=bootstrap-rke2 -o name) --timeout=10s; do sleep 2 ; done # Wait for rke2-control-plane-controller-manager while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_RKE2CONTROLPLANENAMESPACE} $(${KUBECTL} get pods -n ${METAL3_RKE2CONTROLPLANENAMESPACE} -l cluster.x-k8s.io/provider=control-plane-rke2 -o name) --timeout=10s; do sleep 2 ; done fi # Clean up the lock cm ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
必须在
custom/files
文件夹中包含custom/files/airgap-resources.tar.gz
文件,该文件包含用于在隔离环境中运行管理群集的所有资源。必须手动准备此文件,以下载所有资源并将其压缩成此单一文件。airgap-resources.tar.gz
文件包含以下资源:|-- clusterctl |-- clusterctl.yaml |-- overrides |-- bootstrap-rke2 | |-- v0.2.6 | |-- bootstrap-components.yaml | |-- metadata.yaml |-- cluster-api | |-- v1.6.2 | |-- core-components.yaml | |-- metadata.yaml |-- control-plane-rke2 | |-- v0.2.6 | |-- control-plane-components.yaml | |-- metadata.yaml |-- infrastructure-metal3 |-- v1.6.0 |-- cluster-template.yaml |-- infrastructure-components.yaml |-- metadata.yaml
clusterctl.yaml
文件包含的配置用于指定映像位置以及
clusterctl
工具要使用的覆盖值。overrides
文件夹包含要使用的(而不是从互联网下载的)yaml
文件清单。
providers:
# override a pre-defined provider
- name: "cluster-api"
url: "/root/cluster-api/overrides/cluster-api/v1.6.2/core-components.yaml"
type: "CoreProvider"
- name: "metal3"
url: "/root/cluster-api/overrides/infrastructure-metal3/v1.6.0/infrastructure-components.yaml"
type: "InfrastructureProvider"
- name: "rke2"
url: "/root/cluster-api/overrides/bootstrap-rke2/v0.2.6/bootstrap-components.yaml"
type: "BootstrapProvider"
- name: "rke2"
url: "/root/cluster-api/overrides/control-plane-rke2/v0.2.6/control-plane-components.yaml"
type: "ControlPlaneProvider"
images:
all:
repository: registry.suse.com/edge
可以使用以下 curl 命令下载 clusterctl
,以及
overrides
文件夹中包含的其他文件:
# clusterctl binary curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/1.6.2/clusterctl-linux-${GOARCH} -o /usr/local/bin/clusterct # boostrap-components (boostrap-rke2) curl -L https://github.com/rancher-sandbox/cluster-api-provider-rke2/releases/download/v0.2.6/bootstrap-components.yaml curl -L https://github.com/rancher-sandbox/cluster-api-provider-rke2/releases/download/v0.2.6/metadata.yaml # control-plane-components (control-plane-rke2) curl -L https://github.com/rancher-sandbox/cluster-api-provider-rke2/releases/download/v0.2.6/control-plane-components.yaml curl -L https://github.com/rancher-sandbox/cluster-api-provider-rke2/releases/download/v0.2.6/metadata.yaml # cluster-api components curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.6.2/core-components.yaml curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.6.2/metadata.yaml # infrastructure-components (infrastructure-metal3) curl -L https://github.com/metal3-io/cluster-api-provider-metal3/releases/download/v1.6.0/infrastructure-components.yaml curl -L https://github.com/metal3-io/cluster-api-provider-metal3/releases/download/v1.6.0/metadata.yaml
如果您要使用不同版本的组件,可以更改 URL 中的版本以下载特定版本的组件。
下载上述资源后,可以使用以下命令将其压缩成单个文件:
tar -czvf airgap-resources.tar.gz clusterctl clusterctl.yaml overrides
29.5 映像创建 #
按照前面的章节准备好目录结构后(适用于联网方案和隔离方案),运行以下命令来构建映像:
podman run --rm --privileged -it -v $PWD:/eib \ registry.suse.com/edge/edge-image-builder:1.0.2 \ build --definition-file mgmt-cluster.yaml
这会创建 ISO 输出映像文件,在本例中,根据前面所述的映像定义,该文件是
eib-mgmt-cluster-image.iso
。
29.6 置备管理群集 #
上图包含前面介绍的所有组件,可以使用虚拟机或裸机服务器(使用虚拟媒体功能)根据此图置备管理群集。
30 电信功能配置 #
本章将阐释部署了 ATIP 的群集上特定于电信的功能配置。
将使用有关 ATIP 自动置备的一章(第 31 章 “全自动定向网络置备”)中所述的定向网络置备部署方法。
本章涵盖以下主题:
实时内核映像(第 30.1 节 “实时内核映像”):实时内核使用的内核映像。
CPU 已微调配置(第 30.2 节 “CPU 已微调配置”):实时内核使用的已微调配置。
CNI 配置(第 30.3 节 “CNI 配置”):Kubernetes 群集使用的 CNI 配置。
SR-IOV 配置(第 30.4 节 “SR-IOV”):Kubernetes 工作负载使用的 SR-IOV 配置。
DPDK 配置(第 30.5 节 “DPDK”):系统使用的 DPDK 配置。
vRAN 加速卡(第 30.6 节 “vRAN 加速 (
Intel ACC100/ACC200
)”):Kubernetes 工作负载使用的加速卡配置。大页(第 30.7 节 “大页”):Kubernetes 工作负载使用的大页配置。
CPU 固定配置(第 30.8 节 “CPU 固定配置”):Kubernetes 工作负载使用的 CPU 固定配置。
可感知 NUMA 的调度配置(第 30.9 节 “可感知 NUMA 的调度”):Kubernetes 工作负载使用的可感知 NUMA 的调度配置。
MetalLB 配置(第 30.10 节 “MetalLB”):Kubernetes 工作负载使用的 MetalLB 配置。
专用注册表配置(第 30.11 节 “专用注册表配置”):Kubernetes 工作负载使用的专用注册表配置。
30.1 实时内核映像 #
实时内核映像不一定比标准内核更好。它是针对特定用例进行微调的另一种内核。经过微调的实时内核可以降低延迟,但代价是降低了吞吐量。不建议将实时内核用于一般用途,但在本例中,它是建议用于电信工作负载的内核,因为其中的延迟是一项关键考虑因素。
实时内核有四大特性:
确定性执行:
获得更高的可预测性 — 确保关键业务流程每次都能及时完成并提供高质量的服务,即使在承受繁重的系统负载情况下也能如此。通过围隔出关键系统资源供高优先级流程使用,可以确保为时间敏感型应用程序提供更高的可预测性。
低抖动:
基于高确定性技术的低抖动有助于应用程序与现实世界保持同步。这可以为那些需要持续重复计算的服务提供帮助。
优先级继承:
优先级继承是指当较高优先级的进程在完成其任务之前需要先等待较低优先级的进程完成时,较低优先级的进程可以提升为较高优先级的功能。SUSE Linux Enterprise Real Time 解决了任务关键型进程的优先级倒置问题。
线程中断:
在通用操作系统中以中断模式运行的进程不可抢占。在 SUSE Linux Enterprise Real Time 中,这些中断已由可中断的内核线程封装,并允许用户定义的较高优先级进程抢占硬中断和软中断。
在本例中,如果您已安装
SLE Micro RT
之类的实时映像,则就已经安装了实时内核。可以从 SUSE Customer Center 下载实时内核映像。注意有关实时内核的详细信息,请访问 SUSE Real Time。
30.2 CPU 已微调配置 #
使用 CPU 已微调配置可以隔离 CPU 核心供实时内核使用。必须防止操作系统与实时内核使用相同的核心,因为操作系统有可能会使用这些核心,导致提高实时内核的延迟。
要启用和配置此功能,首先应该为我们想要隔离的 CPU 核心创建一个配置文件。在本例中,我们将隔离核心 1-30
和
33-62
。
$ echo "export tuned_params" >> /etc/grub.d/00_tuned $ echo "isolated_cores=1-30,33-62" >> /etc/tuned/cpu-partitioning-variables.conf $ tuned-adm profile cpu-partitioning Tuned (re)started, changes applied.
然后我们需要修改 GRUB 选项来隔离 CPU 核心和其他重要的 CPU 使用参数。请务必根据您的当前硬件规格自定义以下选项:
参数 | 值 | 说明 |
---|---|---|
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 |
我们将使用上面所示的值隔离 60 个核心,并将其中 4 个核心用于操作系统。
以下命令修改 GRUB 配置并应用上述更改,以便下次引导时使用更改的配置:
编辑 /etc/default/grub
文件,在其中添加上述参数:
GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"
更新 GRUB 配置:
$ transactional-update grub.cfg $ reboot
要验证重引导后是否应用了这些参数,可使用以下命令检查内核命令行:
$ cat /proc/cmdline
30.3 CNI 配置 #
30.3.1 Cilium #
Cilium
是 ATIP 的默认 CNI 插件。要在 RKE2 群集上启用 Cilium 作为默认插件,需要在
/etc/rancher/rke2/config.yaml
文件中进行以下配置:
cni:
- cilium
也可以使用命令行参数来指定此配置,即,将 --cni=cilium
添加到
/etc/systemd/system/rke2-server
文件的 server 行中。
要使用下一节(第 30.4 节 “SR-IOV”)中所述的 SR-IOV
网络操作器,请将 Multus
与另一个 CNI 插件(例如 Cilium
或 Calico
)一起用作辅助插件。
cni:
- multus
- cilium
有关 CNI 插件的详细信息,请访问网络选项。
30.4 SR-IOV #
设备(例如网络适配器)可以通过 SR-IOV 在各种 PCIe
硬件功能之间分离对其资源的访问。可以通过多种方式部署 SR-IOV
,本节将介绍两种不同的选项:
选项 1:使用
SR-IOV
CNI 设备插件和配置映射来正确配置 SR-IOV。选项 2(建议):使用 Rancher Prime 中的
SR-IOV
Helm chart 来轻松完成此部署。
选项 1 - 安装 SR-IOV CNI 设备插件并准备配置映射来正确配置 SR-IOV
为设备插件准备配置映射
使用 lspci
命令获取用于填充配置映射的信息:
$ lspci | grep -i acc 8a:00.0 Processing accelerators: Intel Corporation Device 0d5c $ lspci | grep -i net 19:00.0 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11) 19:00.1 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11) 19:00.2 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11) 19:00.3 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11) 51:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02) 51:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02) 51:01.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:01.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:01.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:01.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:11.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:11.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:11.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02) 51:11.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
配置映射由一个 JSON
文件组成,该文件使用用于发现的过滤器来描述设备,并创建接口组。此处的关键在于理解过滤器和组。过滤器用于发现设备,组用于创建接口。
可以设置过滤器:
vendorID:
8086
(Intel)deviceID:
0d5c
(加速卡)driver:
vfio-pci
(驱动程序)pfNames:
p2p1
(物理接口名称)
还可以设置过滤器来匹配更复杂的接口语法,例如:
pfNames:
["eth1#1,2,3,4,5,6"]
或[eth1#1-6]
(物理接口名称)
对于组,我们可为 FEC
卡创建一个组,为 Intel
卡创建另一个组,甚至可以根据用例创建一个前缀:
resourceName:
pci_sriov_net_bh_dpdk
resourcePrefix:
Rancher.io
可以发现许多组合,并创建资源组来为 Pod 分配一些 VF
。
有关过滤器和组的详细信息,请访问 sr-iov 网络设备插件。
根据硬件和用例设置用于匹配接口的过滤器和组后,以下配置映射会显示要使用的示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: sriovdp-config
namespace: kube-system
data:
config.json: |
{
"resourceList": [
{
"resourceName": "intel_fec_5g",
"devicetype": "accelerator",
"selectors": {
"vendors": ["8086"],
"devices": ["0d5d"]
}
},
{
"resourceName": "intel_sriov_odu",
"selectors": {
"vendors": ["8086"],
"devices": ["1889"],
"drivers": ["vfio-pci"],
"pfNames": ["p2p1"]
}
},
{
"resourceName": "intel_sriov_oru",
"selectors": {
"vendors": ["8086"],
"devices": ["1889"],
"drivers": ["vfio-pci"],
"pfNames": ["p2p2"]
}
}
]
}
准备
daemonset
文件以部署设备插件。
设备插件支持多种体系结构(arm
、amd
、ppc64le
),因此同一文件可用于不同的体系结构,以便为每个体系结构部署多个
daemonset
。
apiVersion: v1
kind: ServiceAccount
metadata:
name: sriov-device-plugin
namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-sriov-device-plugin-amd64
namespace: kube-system
labels:
tier: node
app: sriovdp
spec:
selector:
matchLabels:
name: sriov-device-plugin
template:
metadata:
labels:
name: sriov-device-plugin
tier: node
app: sriovdp
spec:
hostNetwork: true
nodeSelector:
kubernetes.io/arch: amd64
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
serviceAccountName: sriov-device-plugin
containers:
- name: kube-sriovdp
image: rancher/hardened-sriov-network-device-plugin:v3.5.1-build20231009-amd64
imagePullPolicy: IfNotPresent
args:
- --log-dir=sriovdp
- --log-level=10
securityContext:
privileged: true
resources:
requests:
cpu: "250m"
memory: "40Mi"
limits:
cpu: 1
memory: "200Mi"
volumeMounts:
- name: devicesock
mountPath: /var/lib/kubelet/
readOnly: false
- name: log
mountPath: /var/log
- name: config-volume
mountPath: /etc/pcidp
- name: device-info
mountPath: /var/run/k8s.cni.cncf.io/devinfo/dp
volumes:
- name: devicesock
hostPath:
path: /var/lib/kubelet/
- name: log
hostPath:
path: /var/log
- name: device-info
hostPath:
path: /var/run/k8s.cni.cncf.io/devinfo/dp
type: DirectoryOrCreate
- name: config-volume
configMap:
name: sriovdp-config
items:
- key: config.json
path: config.json
应用配置映射和
daemonset
后,将部署设备插件,发现接口并将其提供给 Pod 使用。$ kubectl get pods -n kube-system | grep sriov kube-system kube-sriov-device-plugin-amd64-twjfl 1/1 Running 0 2m
检查节点中发现的并可供 Pod 使用的接口:
$ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq { "cpu": "64", "ephemeral-storage": "256196109726", "hugepages-1Gi": "40Gi", "hugepages-2Mi": "0", "intel.com/intel_fec_5g": "1", "intel.com/intel_sriov_odu": "4", "intel.com/intel_sriov_oru": "4", "memory": "221396384Ki", "pods": "110" }
FEC
为intel.com/intel_fec_5g
,值为 1。如果您使用设备插件和配置映射但未使用 Helm chart 部署了 SR-IOV,则
VF
为intel.com/intel_sriov_odu
或intel.com/intel_sriov_oru
。
如果此处没有接口,则继续操作就意义不大,因为 Pod 没有可用的接口。请先检查配置映射和过滤器来解决问题。
选项 2(建议)- 使用 Rancher 和 Helm chart 安装 SR-IOV CNI 和设备插件
获取 Helm(如果没有):
$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
安装 SR-IOV。
可以通过两种方式完成此操作:使用 CLI
或使用 Rancher UI
。
- 从 CLI 安装 Operator
helm repo add suse-edge https://suse-edge.github.io/charts helm install sriov-crd suse-edge/sriov-crd -n sriov-network-operator helm install install sriov-network-operator suse-edge/sriov-network-operator -n sriov-network-operator
- 从 Rancher UI 安装 Operator
安装群集后,如果您可以访问
Rancher UI
,则可以通过Rancher UI
中的应用程序选项卡安装SR-IOV Operator
:
确保选择正确的名称空间来安装 Operator,例如 sriov-network-operator
。
+ image::features_sriov.png[sriov.png]
检查已部署的资源 CRD 和 Pod:
$ kubectl get crd $ kubectl -n sriov-network-operator get pods
检查节点中的标签。
所有资源都运行后,标签会自动出现在您的节点中:
$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable feature.node.kubernetes.io/network-sriov.capable: "true"
查看
daemonset
,您会看到新的sriov-network-config-daemon
和sriov-rancher-nfd-worker
处于活动状态并已准备就绪:
$ kubectl get daemonset -A NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE calico-system calico-node 1 1 1 1 1 kubernetes.io/os=linux 15h sriov-network-operator sriov-network-config-daemon 1 1 1 1 1 feature.node.kubernetes.io/network-sriov.capable=true 45m sriov-network-operator sriov-rancher-nfd-worker 1 1 1 1 1 <none> 45m kube-system rke2-ingress-nginx-controller 1 1 1 1 1 kubernetes.io/os=linux 15h kube-system rke2-multus-ds 1 1 1 1 1 kubernetes.io/arch=amd64,kubernetes.io/os=linux 15h
几分钟后(最多可能需要 10 分钟才会更新),将检测到节点,其上已配置了 SR-IOV
功能:
$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -A NAMESPACE NAME AGE sriov-network-operator xr11-2 83s
检查已检测到的接口。
发现的接口应使用网络设备的 PCI 地址。请在主机中使用 lspci
命令检查此信息。
$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -n kube-system -oyaml apiVersion: v1 items: - apiVersion: sriovnetwork.openshift.io/v1 kind: SriovNetworkNodeState metadata: creationTimestamp: "2023-06-07T09:52:37Z" generation: 1 name: xr11-2 namespace: sriov-network-operator ownerReferences: - apiVersion: sriovnetwork.openshift.io/v1 blockOwnerDeletion: true controller: true kind: SriovNetworkNodePolicy name: default uid: 80b72499-e26b-4072-a75c-f9a6218ec357 resourceVersion: "356603" uid: e1f1654b-92b3-44d9-9f87-2571792cc1ad spec: dpConfigVersion: "356507" status: interfaces: - deviceID: "1592" driver: ice eSwitchMode: legacy linkType: ETH mac: 40:a6:b7:9b:35:f0 mtu: 1500 name: p2p1 pciAddress: "0000:51:00.0" totalvfs: 128 vendor: "8086" - deviceID: "1592" driver: ice eSwitchMode: legacy linkType: ETH mac: 40:a6:b7:9b:35:f1 mtu: 1500 name: p2p2 pciAddress: "0000:51:00.1" totalvfs: 128 vendor: "8086" syncStatus: Succeeded kind: List metadata: resourceVersion: ""
如果此处未检测到您的接口,请确保该接口在下一个配置映射中存在:
$ kubectl get cm supported-nic-ids -oyaml -n sriov-network-operator
如果此处未检测到您的设备,请编辑配置映射,添加要发现的正确值(如有必要,请重启动
sriov-network-config-daemon
daemonset)。
创建
NetworkNode 策略
来配置VF
。
将在设备 (rootDevices
) 中创建一些 VF
(numVfs
),并在其上配置驱动程序 deviceType
和
MTU
:
resourceName
字段不得包含任何特殊字符,并且在整个群集中必须唯一。该示例使用
deviceType: vfio-pci
,因为 dpdk
将与
sr-iov
结合使用。如果您不使用 dpdk
,则 deviceType
应为 deviceType: netdevice
(默认值)。
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
name: policy-dpdk
namespace: sriov-network-operator
spec:
nodeSelector:
feature.node.kubernetes.io/network-sriov.capable: "true"
resourceName: intelnicsDpdk
deviceType: vfio-pci
numVfs: 8
mtu: 1500
nicSelector:
deviceID: "1592"
vendor: "8086"
rootDevices:
- 0000:51:00.0
验证配置:
$ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq { "cpu": "64", "ephemeral-storage": "256196109726", "hugepages-1Gi": "60Gi", "hugepages-2Mi": "0", "intel.com/intel_fec_5g": "1", "memory": "200424836Ki", "pods": "110", "rancher.io/intelnicsDpdk": "8" }
创建 sr-iov 网络(可选操作,仅在需要不同的网络时才执行):
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
name: network-dpdk
namespace: sriov-network-operator
spec:
ipam: |
{
"type": "host-local",
"subnet": "192.168.0.0/24",
"rangeStart": "192.168.0.20",
"rangeEnd": "192.168.0.60",
"routes": [{
"dst": "0.0.0.0/0"
}],
"gateway": "192.168.0.1"
}
vlan: 500
resourceName: intelnicsDpdk
检查创建的网络:
$ kubectl get network-attachment-definitions.k8s.cni.cncf.io -A -oyaml apiVersion: v1 items: - apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: annotations: k8s.v1.cni.cncf.io/resourceName: rancher.io/intelnicsDpdk creationTimestamp: "2023-06-08T11:22:27Z" generation: 1 name: network-dpdk namespace: sriov-network-operator resourceVersion: "13124" uid: df7c89f5-177c-4f30-ae72-7aef3294fb15 spec: config: '{ "cniVersion":"0.3.1", "name":"network-dpdk","type":"sriov","vlan":500,"vlanQoS":0,"ipam":{"type":"host-local","subnet":"192.168.0.0/24","rangeStart":"192.168.0.10","rangeEnd":"192.168.0.60","routes":[{"dst":"0.0.0.0/0"}],"gateway":"192.168.0.1"} }' kind: List metadata: resourceVersion: ""
30.5 DPDK #
DPDK
(数据平面开发包)是一组用于实现快速包处理的库和驱动程序。它用于加速各种 CPU
体系结构上运行的包处理工作负载。DPDK 包含以下组件的数据平面库和优化的网络接口控制器 (NIC
) 驱动程序:
队列管理器实现无锁队列。
缓冲区管理器预先分配固定大小的缓冲区。
内存管理器在内存中分配对象池,并使用环来存储空闲对象;确保对象均匀分布在所有
DRAM
通道上。轮询模式驱动程序 (
PMD
) 可以在没有异步通知的情况下运行,从而降低了开销。包框架以一组库的形式提供,可帮助开发包处理解决方案。
以下步骤说明如何启用 DPDK
,以及如何从 NIC
创建供
DPDK
接口使用的 VF
:
安装
DPDK
软件包:
$ transactional-update pkg install dpdk22 dpdk22-tools libdpdk-23 $ reboot
内核参数:
要使用 DPDK,请采用一些驱动程序来启用内核中的某些参数:
参数 | 值 | 说明 |
---|---|---|
iommu | pt | 此选项允许为 DPDK 接口使用 |
intel_iommu | on | 此选项允许为 |
要启用这些参数,请将其添加到 /etc/default/grub
文件中:
GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"
更新 GRUB 配置,并重引导系统以应用更改:
$ transactional-update grub.cfg $ reboot
加载
vfio-pci
内核模块,并在NIC
上启用SR-IOV
:
$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
从
NIC
创建一些虚拟功能 (VF
)。
例如,要为两个不同的 NIC
创建 VF
,需要运行以下命令:
$ echo 4 > /sys/bus/pci/devices/0000:51:00.0/sriov_numvfs $ echo 4 > /sys/bus/pci/devices/0000:51:00.1/sriov_numvfs
将新的 VF 绑定到
vfio-pci
驱动程序:
$ dpdk-devbind.py -b vfio-pci 0000:51:01.0 0000:51:01.1 0000:51:01.2 0000:51:01.3 \ 0000:51:11.0 0000:51:11.1 0000:51:11.2 0000:51:11.3
检查是否正确应用了配置:
$ dpdk-devbind.py -s Network devices using DPDK-compatible driver ============================================ 0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:01.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:01.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:01.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:11.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:21.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio 0000:51:31.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio Network devices using kernel driver =================================== 0000:19:00.0 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em1 drv=bnxt_en unused=igb_uio,vfio-pci *Active* 0000:19:00.1 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em2 drv=bnxt_en unused=igb_uio,vfio-pci 0000:19:00.2 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em3 drv=bnxt_en unused=igb_uio,vfio-pci 0000:19:00.3 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em4 drv=bnxt_en unused=igb_uio,vfio-pci 0000:51:00.0 'Ethernet Controller E810-C for QSFP 1592' if=eth13 drv=ice unused=igb_uio,vfio-pci 0000:51:00.1 'Ethernet Controller E810-C for QSFP 1592' if=rename8 drv=ice unused=igb_uio,vfio-pci
30.6 vRAN 加速 (Intel ACC100/ACC200
) #
随着通讯服务提供商从 4G 过渡到 5G 网络,有许多提供商正在采用虚拟化无线接入网络 (vRAN
)
体系结构来提高信道容量及简化基于边缘的服务和应用程序的部署。vRAN
解决方案非常适合用于提供低延迟服务,并可以根据实时流量和网络需求灵活地增加或减少容量。
计算密集程度最高的 4G 和 5G 工作负载之一是 RAN 第 1 层 (L1
)
FEC
,它可以解决不可靠或高干扰信道上的数据传输错误。FEC
技术可以检测并纠正 4G 或 5G 数据中有限数量的错误,因此消除了重新传输的需要。由于 FEC
加速事务不包含单元状态信息,因此可以轻松虚拟化,从而带来了池化优势并可实现轻松的单元迁移。
内核参数
要启用 vRAN
加速,需要启用以下内核参数(如果尚未启用):
参数 | 值 | 说明 |
---|---|---|
iommu | pt | 此选项允许为 DPDK 接口使用 vfio。 |
intel_iommu | on | 此选项允许为 VF 使用 vfio。 |
修改 GRUB 文件 /etc/default/grub
,以将这些参数添加到内核命令行:
GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"
更新 GRUB 配置,并重引导系统以应用更改:
$ transactional-update grub.cfg $ reboot
要校验重引导后是否应用了这些参数,请检查命令行:
$ cat /proc/cmdline
加载 vfio-pci 内核模块以启用
vRAN
加速:
$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
获取 Acc100 接口信息:
$ lspci | grep -i acc 8a:00.0 Processing accelerators: Intel Corporation Device 0d5c
将物理接口 (
PF
) 绑定到vfio-pci
驱动程序:
$ dpdk-devbind.py -b vfio-pci 0000:8a:00.0
从物理接口 (
PF
) 创建虚拟功能 (VF
)。
从 PF
创建 2 个 VF
,并按照以下步骤将其绑定到
vfio-pci
:
$ echo 2 > /sys/bus/pci/devices/0000:8a:00.0/sriov_numvfs $ dpdk-devbind.py -b vfio-pci 0000:8b:00.0
使用建议的配置文件配置 acc100:
$ pf_bb_config ACC100 -c /opt/pf-bb-config/acc100_config_vf_5g.cfg Tue Jun 6 10:49:20 2023:INFO:Queue Groups: 2 5GUL, 2 5GDL, 2 4GUL, 2 4GDL Tue Jun 6 10:49:20 2023:INFO:Configuration in VF mode Tue Jun 6 10:49:21 2023:INFO: ROM version MM 99AD92 Tue Jun 6 10:49:21 2023:WARN:* Note: Not on DDR PRQ version 1302020 != 10092020 Tue Jun 6 10:49:21 2023:INFO:PF ACC100 configuration complete Tue Jun 6 10:49:21 2023:INFO:ACC100 PF [0000:8a:00.0] configuration complete!
检查从 FEC PF 创建的新 VF:
$ dpdk-devbind.py -s Baseband devices using DPDK-compatible driver ============================================= 0000:8a:00.0 'Device 0d5c' drv=vfio-pci unused= 0000:8b:00.0 'Device 0d5d' drv=vfio-pci unused= Other Baseband devices ====================== 0000:8b:00.1 'Device 0d5d' unused=
30.7 大页 #
当某个进程使用 RAM
时,CPU
会将 RAM
标记为已由该进程使用。为提高效率,CPU
会以区块的形式分配
RAM
,在许多平台上,默认的区块大小值为 4K
字节。这些区块称为页。页可以交换到磁盘等位置。
由于进程地址空间是虚拟的,CPU
和操作系统需要记住哪些页属于哪个进程,以及每个页存储在哪个位置。页数越多,内存映射的搜索时间就越长。当某个进程使用 1
GB
内存时,需要查找 262144 个项 (1 GB
/ 4
K
)。如果一个页表项占用 8 个字节,则需要查找 2 MB
内存 (262144 * 8)。
当前的大多数 CPU
体系结构都支持大于默认值的页,因此减少了
CPU/操作系统
需要查找的项。
内核参数
要启用大页,应添加以下内核参数:
参数 | 值 | 说明 |
---|---|---|
hugepagesz | 1G | 此选项允许将大页的大小设置为 1 G |
hugepages | 40 | 这是先前定义的大页数量 |
default_hugepagesz | 1G | 这是用于获取大页的默认值 |
修改 GRUB 文件 /etc/default/grub
,以将这些参数添加到内核命令行:
GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"
更新 GRUB 配置,并重引导系统以应用更改:
$ transactional-update grub.cfg $ reboot
要验证重引导后是否应用了这些参数,可以检查命令行:
$ cat /proc/cmdline
使用大页
要使用大页,需要挂载它们:
$ mkdir -p /hugepages $ mount -t hugetlbfs nodev /hugepages
部署 Kubernetes 工作负载,并创建资源和卷:
...
resources:
requests:
memory: "24Gi"
hugepages-1Gi: 16Gi
intel.com/intel_sriov_oru: '4'
limits:
memory: "24Gi"
hugepages-1Gi: 16Gi
intel.com/intel_sriov_oru: '4'
...
...
volumeMounts:
- name: hugepage
mountPath: /hugepages
...
volumes:
- name: hugepage
emptyDir:
medium: HugePages
...
30.8 CPU 固定配置 #
要求
必须根据第 30.2 节 “CPU 已微调配置”一节中所述的性能配置文件微调
CPU
。必须使用 CPU 管理参数配置
RKE2
群集 kubelet,为此请将以下块(示例)添加到/etc/rancher/rke2/config.yaml
文件中:
kubelet-arg:
- "cpu-manager=true"
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=1"
- "system-reserved=cpu=1"
在 Kubernetes 上使用 CPU 固定
根据您在工作负载上定义的请求和限制,可以用三种方式通过 kubelet 中定义的静态策略
来使用该功能:
BestEffort
QoS 类:如果您没有为CPU
定义任何请求或限制,则 Pod 将调度到系统中第一个可用的CPU
上。使用
BestEffort
QoS 类的示例如下:spec: containers: - name: nginx image: nginx
Burstable
QoS 类:如果为 CPU 定义的请求不等于限制,或者没有 CPU 请求,请使用此方式。使用
Burstable
QoS 类的示例如下:spec: containers: - name: nginx image: nginx resources: limits: memory: "200Mi" requests: memory: "100Mi"
或
spec: containers: - name: nginx image: nginx resources: limits: memory: "200Mi" cpu: "2" requests: memory: "100Mi" cpu: "1"
Guaranteed
QoS 类:如果为 CPU 定义的请求等于限制,请使用此方式。使用
Guaranteed
QoS 类的示例如下:spec: containers: - name: nginx image: nginx resources: limits: memory: "200Mi" cpu: "2" requests: memory: "200Mi" cpu: "2"
30.9 可感知 NUMA 的调度 #
非统一内存访问或非统一内存体系结构 (NUMA
) 是
SMP
(多处理器)体系结构中使用的物理内存设计,其中内存访问时间取决于相对于处理器的内存位置。在
NUMA
下,与访问非本地内存(即,另一个处理器本地的内存,或者在处理器之间共享的内存)相比,处理器可以更快地访问自身的本地内存。
30.9.1 识别 NUMA 节点 #
要识别 NUMA
节点,请在系统上使用以下命令:
$ lscpu | grep NUMA NUMA node(s): 1 NUMA node0 CPU(s): 0-63
对于此示例,只有一个 NUMA
节点显示了 64 个 CPU
。
需要在 BIOS
中启用 NUMA
。如果
dmesg
在引导过程中没有 NUMA 初始化记录,则可能表示内核环缓冲区中的
NUMA
相关讯息已被重写。
30.10 MetalLB #
MetalLB
是裸机 Kubernetes 群集的负载平衡器实现,使用
L2
和 BGP
等标准路由协议作为广告协议。它是一个网络负载平衡器,可用于向外部公开 Kubernetes 群集中的服务(因为需要在裸机上使用 Kubernetes
服务类型 LoadBalancer
)。
要在 RKE2
群集中启用 MetalLB
,需要执行以下步骤:
使用以下命令安装
MetalLB
:
$ kubectl apply <<EOF -f apiVersion: helm.cattle.io/v1 kind: HelmChart metadata: name: metallb namespace: kube-system spec: repo: https://metallb.github.io/metallb/ chart: metallb targetNamespace: metallb-system --- apiVersion: helm.cattle.io/v1 kind: HelmChart metadata: name: endpoint-copier-operator namespace: kube-system spec: repo: https://suse-edge.github.io/endpoint-copier-operator chart: endpoint-copier-operator targetNamespace: endpoint-copier-operator EOF
创建
IpAddressPool
和L2advertisement
配置:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- 10.168.200.98/32
serviceAllocation:
priority: 100
namespaces:
- default
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- kubernetes-vip-ip-pool
创建端点服务来公开
VIP
:
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
spec:
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: rke2-api
port: 9345
protocol: TCP
targetPort: 9345
- name: k8s-api
port: 6443
protocol: TCP
targetPort: 6443
sessionAffinity: None
type: LoadBalancer
检查
VIP
是否已创建并且MetalLB
Pod 是否正在运行:
$ kubectl get svc -n default $ kubectl get pods -n default
30.11 专用注册表配置 #
可以配置 Containerd
以连接到专用注册表,然后使用专用注册表提取每个节点上的专用映像。
启动时,RKE2
会检查 /etc/rancher/rke2/
中是否存在
registries.yaml
文件,并指示 containerd
使用该文件中定义的任何注册表。如果您希望使用某个专用注册表,请在要使用该注册表的每个节点上以 root 身份创建此文件。
要添加专用注册表,请创建包含以下内容的 /etc/rancher/rke2/registries.yaml
文件:
mirrors:
docker.io:
endpoint:
- "https://registry.example.com:5000"
configs:
"registry.example.com:5000":
auth:
username: xxxxxx # this is the registry username
password: xxxxxx # this is the registry password
tls:
cert_file: # path to the cert file used to authenticate to the registry
key_file: # path to the key file for the certificate used to authenticate to the registry
ca_file: # path to the ca file used to verify the registry's certificate
insecure_skip_verify: # may be set to true to skip verifying the registry's certificate
或者不设置身份验证:
mirrors:
docker.io:
endpoint:
- "https://registry.example.com:5000"
configs:
"registry.example.com:5000":
tls:
cert_file: # path to the cert file used to authenticate to the registry
key_file: # path to the key file for the certificate used to authenticate to the registry
ca_file: # path to the ca file used to verify the registry's certificate
insecure_skip_verify: # may be set to true to skip verifying the registry's certificate
要使注册表更改生效,需要在节点上启动 RKE2 之前配置此文件,或者在配置的每个节点上重启动 RKE2。
有关详细信息,请查看 RKE2 containerd 注册表配置。
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"
32 生命周期操作 #
本章介绍已部署的 ATIP 群集的生命周期管理操作。
32.1 管理群集升级 #
管理群集的升级涉及到多个组件。有关需要升级的常规组件的列表,请参见 Day 2
管理群集(第 24 章 “管理群集”)文档。
下面介绍了特定于此设置的组件的升级过程。
升级 Metal3
要升级 Metal3
,请使用以下命令更新 Helm
储存库缓存,并从 Helm chart 储存库提取用于安装
Metal3
的最新 chart:
helm repo update helm fetch suse-edge/metal3
然后,最简单的升级方式是将当前配置导出到某个文件,然后使用该文件升级
Metal3
版本。如果需要对新版本进行任何更改,可以先编辑该文件,然后再升级。
helm get values metal3 -n metal3-system -o yaml > metal3-values.yaml helm upgrade metal3 suse-edge/metal3 \ --namespace metal3-system \ -f metal3-values.yaml \ --version=0.7.1
32.2 下游群集升级 #
升级下游群集涉及到更新多个组件。以下章节介绍了每个组件的升级过程。
升级操作系统
对于此过程,请参考此章节来构建包含新操作系统版本的新映像。使用
EIB
生成此新映像后,下一置备阶段将使用提供的新操作系统版本。下一步骤将使用新映像来升级节点。
升级 RKE2 群集
需要做出以下更改才能使用自动化工作流程升级 RKE2
群集:
按照此章节中所示更改
capi-provisioning-example.yaml
中的RKE2ControlPlane
块:在规范文件中添加部署策略。
将
RKE2
群集的版本更改为新版本(请替换以下代码中的${RKE2_NEW_VERSION}
)。
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
rolloutStrategy:
rollingUpdate:
maxSurge: 0
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_NEW_VERSION}
nodeName: "localhost.localdomain"
按照此章节中所示更改
capi-provisioning-example.yaml
中的Metal3MachineTemplate
块:将映像名称与校验和更改为在上一步骤中生成的新版本。
将指令
nodeReuse
设置为true
,以避免创建新节点。将指令
automatedCleaningMode
设置为metadata
,以启用节点自动清理。
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
name: single-node-cluster-controlplane
namespace: default
spec:
nodeReuse: True
template:
spec:
automatedCleaningMode: metadata
dataTemplate:
name: single-node-cluster-controlplane-template
hostSelector:
matchLabels:
cluster-role: control-plane
image:
checksum: http://imagecache.local:8080/${NEW_IMAGE_GENERATED}.sha256
checksumType: sha256
format: raw
url: http://imagecache.local:8080/${NEW_IMAGE_GENERATED}.raw
完成这些更改后,可以使用以下命令将 capi-provisioning-example.yaml
文件应用于群集:
kubectl apply -f capi-provisioning-example.yaml
第 VII 部分 附录 #
- 33 发行说明
SUSE Edge 3.0 是紧密集成且经过全面验证的端到端解决方案,用于解决在边缘处部署基础架构和云原生应用程序时存在的独特挑战。其核心作用是提供一个有主见但高度灵活、高度可缩放且安全的平台,涵盖初始部署映像的构建、节点置备和初始配置、应用程序部署、可观测性和生命周期管理。
33 发行说明 #
33.1 摘要 #
SUSE Edge 3.0 是紧密集成且经过全面验证的端到端解决方案,用于解决在边缘处部署基础架构和云原生应用程序时存在的独特挑战。其核心作用是提供一个有主见但高度灵活、高度可缩放且安全的平台,涵盖初始部署映像的构建、节点置备和初始配置、应用程序部署、可观测性和生命周期管理。
该解决方案的设计考虑到了客户的需求和期望千差万别,因此不存在“以一应百”的边缘平台。边缘部署促使我们解决并不断设想出一些极具挑战性的问题,包括大规模可伸缩性、网络受限情况下的可用性、物理空间限制、新的安全威胁和攻击途径、硬件体系结构和系统资源的差异、部署旧式基础架构和应用程序并与之连接的要求,以及使用寿命较长的客户解决方案。
SUSE Edge 一开始就构建于同类最佳的开源软件基础之上,与我们 30 年来提供安全、稳定且经认证的 SUSE Linux 平台的历史,以及通过 Rancher 产品组合提供高度可缩放且功能丰富的 Kubernetes 管理经验相一致。SUSE Edge 是基于这些功能构建的,可以提供满足众多细分市场需求的功能,包括零售、医疗、交通、物流、电信、智能制造和工业物联网。
SUSE 自适应电信基础架构平台 (ATIP) 是 SUSE Edge 的衍生产品(或下游产品),它进一步经过优化并包含更多组件,使平台能够解决电信用例的要求。除非明确说明,否则所有发行说明都适用于 SUSE Edge 3.0 和 SUSE ATIP 3.0。
33.2 简介 #
除非明确指定和说明,否则下面的发行说明在所有体系结构中都是相同的,并且最新版本以及所有其他 SUSE 产品的发行说明始终在 https://www.suse.com/releasenotes 上在线提供。
说明项只会列出一次,但是,非常重要并且属于多个章节的说明项可能会在多处提到。发行说明通常只会列出两个后续版本之间发生的更改。本发行说明可能重复了旧产品版本的发行说明中的某些重要说明项。为了方便识别这些说明项,发行说明中会通过一条备注来指出这一点。
但是,重复的说明项只是出于便利而提供的。因此,如果您跳过了一个或多个版本,另请查看已跳过的版本的发行说明。如果您只阅读当前版本的发行说明,可能会疏忽对系统行为造成影响的重要更改。
33.3 版本 3.0.0 #
发布日期:2024 年 4 月 26 日
摘要:SUSE Edge 3.0.0 是 SUSE Edge 3.0 产品组合中的第一个版本。
33.3.1 新功能 #
不适用 - 这是 3.0.z 随附的第一个版本。
33.3.2 Bug 和安全修复 #
不适用 - 这是 3.0.z 随附的第一个版本。
33.3.3 组件版本 #
下表描述了构成 3.0.0 版本的各个组件,包括版本、Helm chart 版本(如果适用),以及可从中提取二进制格式的已发布项目的位置。有关用法和部署示例,请参见相关文档。
名称 | 版本 | Helm Chart 版本 | 项目位置(URL/映像) |
SLE Micro | 5.5(最新) | 不适用 | SLE Micro
下载页面 |
SUSE Manager | 4.3.11 | 不适用 | |
K3s | 1.28.8 | 不适用 | |
RKE2 | 1.28.8 | 不适用 | |
Rancher Prime | 2.8.3 | 2.8.3 | |
Longhorn | 1.6.1 | 103.3.0 | |
NM Configurator | 0.2.3 | 不适用 | |
NeuVector | 5.3.0 | 103.0.3 | registry.suse.com/rancher/mirrored-neuvector-controller:5.3.0 |
群集 API (CAPI) | 1.6.2 | 不适用 | registry.suse.com/edge/cluster-api-controller:1.6.2 |
Metal3 | 1.16.0 | 0.6.5 | registry.suse.com/edge/metal3-chart:0.6.5 |
MetalLB | 0.14.3 | 0.14.3 | registry.suse.com/edge/metallb-chart:0.14.3 |
Elemental | 1.4.3 | 103.1.0 | registry.suse.com/rancher/elemental-operator-chart:1.4.3 |
Edge Image Builder | 1.0.1 | 不适用 | registry.suse.com/edge/edge-image-builder:1.0.1 |
KubeVirt | 1.1.1 | 0.2.4 | registry.suse.com/edge/kubevirt-chart:0.2.4 |
KubeVirt 仪表板扩展 | 1.0.0 | 1.0.0 | registry.suse.com/edge/kubevirt-dashboard-extension-chart:1.0.0 |
Containerized Data Importer | 1.58.0 | 0.2.3 | registry.suse.com/edge/cdi-chart:0.2.3 |
Endpoint Copier Operator | 0.2.0 | 0.2.0 | registry.suse.com/edge/endpoint-copier-operator:v0.2.0 |
Akri(技术预览) | 0.12.20 | 0.12.20 | registry.suse.com/edge/akri-chart:0.12.20 |
各个 SUSE Edge z-stream 版本紧密集成,并已作为版本受控的堆栈进行全面测试。将任何一个组件升级到其他版本(而不是上面列出的版本)都可能会导致系统停机。虽然可以在未经测试的配置中运行 Edge 群集,但我们不建议这样做,而且这样可能需要花费更长的时间来通过支持渠道获得问题的解决方法。
33.4 版本 3.0.1 #
发布日期:2024 年 6 月 14 日
摘要:SUSE Edge 3.0.1 是 SUSE Edge 3.0 产品组合中的第一个 z-stream 版本。
33.4.1 新功能 #
Elemental 和 EIB 现在支持对不受管主机执行节点重置
现已包含 SR-IOV 网络运营商 chart
Metal3 chart 现在支持提供额外的可信 CA 证书
NM Configurator 现在支持在不指定任何 MAC 的情况下应用统一配置
为 EIB 添加了
version
子命令;版本还会自动包含在 EIB 构建的每个映像中
33.4.2 Bug 和安全修复 #
EIB 现在会自动在自定义脚本中设置执行位:SUSE Edge 问题 #429
EIB 现在支持扇区大小大于 512 字节的磁盘:SUSE Edge 问题 #447
增强了 EIB 在 Helm chart 中检测容器映像的能力:SUSE Edge 问题 #442
33.4.3 组件版本 #
下表描述了构成 3.0.1 版本的各个组件,包括版本、Helm chart 版本(如果适用),以及可从中提取二进制格式的已发布项目的位置。有关用法和部署示例,请参见相关文档。
名称 | 版本 | Helm Chart 版本 | 项目位置(URL/映像) |
SLE Micro | 5.5(最新) | 不适用 | SLE Micro
下载页面 |
SUSE Manager | 4.3.11 | 不适用 | |
K3s | 1.28.9 | 不适用 | |
RKE2 | 1.28.9 | 不适用 | |
Rancher Prime | 2.8.4 | 2.8.4 | |
Longhorn | 1.6.1 | 103.3.0 | |
NM Configurator | 0.3.0 | 不适用 | |
NeuVector | 5.3.0 | 103.0.3 | registry.suse.com/rancher/mirrored-neuvector-controller:5.3.0 |
群集 API (CAPI) | 1.6.2 | 不适用 | registry.suse.com/edge/cluster-api-controller:1.6.2 |
Metal3 | 1.16.0 | 0.7.1 | registry.suse.com/edge/metal3-chart:0.7.1 |
MetalLB | 0.14.3 | 0.14.3 | registry.suse.com/edge/metallb-chart:0.14.3 |
Elemental | 1.4.4 | 103.1.0 | registry.suse.com/rancher/elemental-operator-chart:1.4.4 |
Edge Image Builder | 1.0.2 | 不适用 | registry.suse.com/edge/edge-image-builder:1.0.2 |
KubeVirt | 1.1.1 | 0.2.4 | registry.suse.com/edge/kubevirt-chart:0.2.4 |
KubeVirt 仪表板扩展 | 1.0.0 | 1.0.0 | registry.suse.com/edge/kubevirt-dashboard-extension-chart:1.0.0 |
Containerized Data Importer | 1.58.0 | 0.2.3 | registry.suse.com/edge/cdi-chart:0.2.3 |
Endpoint Copier Operator | 0.2.0 | 0.2.0 | registry.suse.com/edge/endpoint-copier-operator:v0.2.0 |
Akri(技术预览) | 0.12.20 | 0.12.20 | registry.suse.com/edge/akri-chart:0.12.20 |
SR-IOV Network Operator | 1.2.2 | 1.2.2+up0.1.0 | registry.suse.com/edge/sriov-network-operator-chart:1.2.2 |
33.5 组件校验 #
可以使用软件材料清单 (SBOM) 数据来校验上述组件 - 例如,如下所述使用 cosign
:
从 SUSE 签名密钥来源下载 SUSE Edge 容器公共密钥:
> cat key.pem
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7N0S2d8LFKW4WU43bq7Z
IZT537xlKe17OQEpYjNrdtqnSwA0/jLtK83m7bTzfYRK4wty/so0g3BGo+x6yDFt
SVXTPBqnYvabU/j7UKaybJtX3jc4SjaezeBqdi96h6yEslvg4VTZDpy6TFP5ZHxZ
A0fX6m5kU2/RYhGXItoeUmL5hZ+APYgYG4/455NBaZT2yOywJ6+1zRgpR0cRAekI
OZXl51k0ebsGV6ui/NGECO6MB5e3arAhszf8eHDE02FeNJw5cimXkgDh/1Lg3KpO
dvUNm0EPWvnkNYeMCKR+687QG0bXqSVyCbY6+HG/HLkeBWkv6Hn41oeTSLrjYVGa
T3zxPVQM726sami6pgZ5vULyOleQuKBZrlFhFLbFyXqv1/DokUqEppm2Y3xZQv77
fMNogapp0qYz+nE3wSK4UHPd9z+2bq5WEkQSalYxadyuqOzxqZgSoCNoX5iIuWte
Zf1RmHjiEndg/2UgxKUysVnyCpiWoGbalM4dnWE24102050Gj6M4B5fe73hbaRlf
NBqP+97uznnRlSl8FizhXzdzJiVPcRav1tDdRUyDE2XkNRXmGfD3aCmILhB27SOA
Lppkouw849PWBt9kDMvzelUYLpINYpHRi2+/eyhHNlufeyJ7e7d6N9VcvjR/6qWG
64iSkcF2DTW61CN5TrCe0k0CAwEAAQ==
-----END PUBLIC KEY-----
校验容器映像哈希,例如,使用 crane
进行校验:
> crane digest registry.suse.com/edge/baremetal-operator:0.5.1
sha256:13e8b2c59aeb503f8adaac095495007071559c9d6d8ef5a7cb1ce6fd1430c782
使用 cosign
进行校验:
> cosign verify-attestation --type spdxjson --key key.pem registry.suse.com/edge/baremetal-operator@sha256:13e8b2c59aeb503f8adaac095495007071559c9d6d8ef5a7cb1ce6fd1430c782 > /dev/null
#
Verification for registry.suse.com/edge/baremetal-operator@sha256:13e8b2c59aeb503f8adaac095495007071559c9d6d8ef5a7cb1ce6fd1430c782 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The claims were present in the transparency log
- The signatures were integrated into the transparency log when the certificate was valid
- The signatures were verified against the specified public key
按照上游文档中所述提取 SBOM 数据:
> cosign verify-attestation --type spdxjson --key key.pem registry.suse.com/edge/baremetal-operator@sha256:13e8b2c59aeb503f8adaac095495007071559c9d6d8ef5a7cb1ce6fd1430c782 | jq '.payload | @base64d | fromjson | .predicate'
33.6 升级步骤 #
有关如何升级到新 z-stream 版本的细节,请参见 Day 2 文档。
33.7 已知限制 #
除非另有说明,否则下述限制适用于 3.0.0 版本和所有后续 z-stream 版本。
Akri 的第一个版本是作为技术预览产品发布的,不涵盖在标准支持范围内。
SUSE Edge 中使用的 Rancher UI 扩展目前无法通过 Rancher 商城部署,必须手动部署。Rancher 问题 #29105
如果您使用的是 NVIDIA GPU,则由于缺少 SELinux 策略,无法在 containerd 层启用 SELinux。Bugzilla #1222725
如果使用 Metal3 和群集 API (CAPI) 进行部署,则安装后不会自动将群集导入 Rancher。此问题在将来的版本中会得到解决。
33.8 产品支持生命周期 #
SUSE Edge 享有 SUSE 有口皆碑的支持。SUSE 是广受认可的技术领导者,其在提供企业级支持服务方面拥有经受考验的历史。有关详细信息,请参见 https://www.suse.com/lifecycle 和支持策略页面 (https://www.suse.com/support/policy.html)。如果您在提交支持案例、SUSE 如何划分严重性级别或支持范围方面有任何疑问,请参见技术支持手册 (https://www.suse.com/support/handbook/)。
在本文档发布时,SUSE Edge 的每个次要版本(例如“3.0”)提供 12 个月的生产支持,最初 6 个月提供“全面支持”,随后 6 个月提供“维护支持”。在“全面支持”涵盖期间,SUSE 可能会引入新功能(但不会破坏现有功能)、引入 bug 修复及提供安全补丁。在“维护支持”涵盖期间,只会引入关键的安全修复和 bug 修复,其他修复由我们自行决定是否提供。
除非明确说明,否则列出的所有组件均被视为正式发布 (GA),并涵盖在 SUSE 的标准支持范围内。某些组件可能以“技术预览”版本的形式列出,SUSE 通过此类版本让客户提前体验尚未正式发布的特性和功能以进行评估,但这些组件没有标准支持政策的保障,不建议将其用于生产用例。SUSE 非常欢迎各位对技术预览组件的改进提供反馈和建议,但如果技术预览功能无法满足客户的需求或者达不到我们要求的成熟度,SUSE 保留在正式发布之前弃用该功能的权利。
请注意,SUSE 必须偶尔弃用功能或更改 API 规范。弃用功能或更改 API 的原因包括相应功能已更新或由新的实现取代、有新的功能集、上游技术不再可用,或者上游社区引入了不兼容的更改。在给定的次要版本 (x.z) 中,这种情况预期永远不会发生,因此所有 z-stream 版本都将保持 API 兼容性和原有功能。SUSE 将努力在发行说明中提供弃用警告并发出充足的通告,同时提供解决方法、建议和缓解措施,以最大程度地减少服务中断。
SUSE Edge 团队也欢迎社区提出反馈,你们可以在 https://www.github.com/suse-edge 中的相应代码储存库内提出问题。
33.9 获取源代码 #
本 SUSE 产品包含根据 GNU 通用公共许可证 (GPL) 和其他各种开源许可证授权给 SUSE 的材料。GPL 要求 SUSE 提供与 GPL 授权材料对应的源代码,而 SUSE 必须遵守其他所有开源许可要求。因此,SUSE 将提供所有源代码,一般情况下,这些源代码可以在相关组件的 SUSE Edge GitHub 储存库 (https://www.github.com/suse-edge) 和 SUSE Rancher GitHub 储存库 (https://www.github.com/rancher) 中找到,具体对于 SLE Micro 而言,这些源代码可以在 https://www.suse.com/download/sle-micro 上的“Medium 2”中下载。
33.10 法律声明 #
SUSE 不对本文档的内容或其使用作出任何陈述或保证,并明确否认对适销性或任何特定用途的适用性作出任何明示或暗示保证。此外,SUSE 保留随时修订本出版物和更改其内容的权利,且无义务将此类修订或更改通知任何个人或实体。
此外,SUSE 不对任何软件作出任何陈述或保证,并明确否认对适销性或任何特定用途的适用性作出任何明示或暗示保证。此外,SUSE 保留随时更改 SUSE 软件任何或所有部分的权利,且无义务将此类更改通知任何个人或实体。
根据本协议提供的任何产品或技术信息可能受到美国出口管制和其他国家/地区贸易法的约束。您同意遵守所有出口管制法规,并在出口、再出口或进口可交付产品之前取得所有必要的许可证或分类证书。您同意不向美国目前的出口排除列表上的实体,或美国出口法中规定的任何禁运国家/地区或支持恐怖主义的国家/地区出口或再出口。您同意不将可交付产品用于受禁核武器、导弹或生化武器的最终用途。有关出口 SUSE 软件的详细信息,请参见 https://www.suse.com/company/legal/。如果您未能取得任何必要的出口许可,SUSE 对此不承担任何责任。
版权所有 © 2024 SUSE LLC。
本发行说明文档根据 Creative Commons Attribution-NoDerivatives 4.0 国际许可证 (CC-BY-ND-4.0) 授权。您应已随本文档收到了该许可证的副本。如果没有,请参见 https://creativecommons.org/licenses/by-nd/4.0/。
SUSE 拥有与本文档所述产品中体现的技术相关的知识产权。具体而言,这些知识产权可能包括但不限于 https://www.suse.com/company/legal/ 中列出的一项或多项美国专利,以及美国和其他国家/地区的一项或多项其他专利或正在申请的专利。
有关 SUSE 商标,请参见 SUSE 商标和服务标记列表 (https://www.suse.com/company/legal/)。所有第三方商标均是其各自所有者的财产。有关 SUSE 品牌信息和使用要求,请参见 https://brand.suse.com/ 上发布的准则。