跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / SUSE Edge 文档 / 产品文档 / 设置管理群集

29 设置管理群集

29.1 简介

管理群集是用于管理运行时堆栈的置备和生命周期的 ATIP 组成部分。从技术角度讲,管理群集包含以下组件:

  • SUSE Linux Enterprise Micro(操作系统)。可以根据用例自定义某些配置,例如网络、存储、用户和内核参数。

  • RKE2(Kubernetes 群集)。可以根据用例将其配置为使用特定的 CNI 插件,例如 MultusCilium 等。

  • 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 设置管理群集的步骤

需要执行以下步骤来设置管理群集(使用单个节点):

ATIP 产品管理群集 1

使用声明性方法设置管理群集需要执行三个主要步骤:

  1. 为联网环境准备映像(第 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 文件夹包含管理群集节点要使用的网络配置文件。

  2. 为隔离环境准备映像(第 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 文件中包含的本地资源,而不是从互联网下载资源。

  3. 创建映像(第 29.5 节 “映像创建”:此步骤使用 Edge Image Builder 工具创建映像(适用于联网方案和隔离方案)。在系统上运行 Edge Image Builder 工具之前请先检查先决条件(第 9 章 “Edge Image Builder)。

  4. 置备管理群集(第 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 通常从容器内部运行,因此,如果您目前无法运行容器,则首先需要安装 PodmanRancher 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 CenterSUSE 下载页面下载 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 是用于安装操作系统的设备,usernameencryptedPassword 是用于访问系统的身份凭证,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 组件要使用网络配置,例如 apiHostapiVIPapiVIP 应是网络中未使用的 IP 地址,并且不属于 DHCP 池(如果使用 DHCP)。此外,如果我们在多节点群集中使用 apiVIP,apiVIP 将用于访问 Kubernetes API 服务器。apiHostRKE2 组件要使用的 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 版本的配置参数,以及 RancherMetalLB 基本参数。请仅在您要更改所要使用的组件或名称空间的版本时才修改此文件。

    #!/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.yamlmgmt-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 CenterSUSE 下载页面下载 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 置备管理群集

上图包含前面介绍的所有组件,可以使用虚拟机或裸机服务器(使用虚拟媒体功能)根据此图置备管理群集。