×

支持多种架构和操作系统(或平台)的 Red Hat 支持的 Operator 项目可以在比仅支持单个平台的 Operator 项目更多的 Kubernetes 和 OpenShift Container Platform 集群上运行。示例架构包括amd64arm64ppc64les390x。示例操作系统包括 Linux 和 Windows。

执行以下操作以确保您的 Operator 项目可以在多个 OpenShift Container Platform 平台上运行

  • 构建一个清单,指定您的 Operator 支持的平台。

  • 设置 Operator 的节点亲和性以支持多架构计算机器。

Red Hat 支持的 Operator SDK CLI 工具版本(包括与 Operator 项目相关的脚手架和测试工具)已弃用,并计划在未来的 OpenShift Container Platform 版本中删除。Red Hat 将在此版本的生命周期内为此功能提供错误修复和支持,但此功能将不再接收增强功能,并将从未来的 OpenShift Container Platform 版本中删除。

不建议使用 Red Hat 支持的 Operator SDK 版本创建新的 Operator 项目。拥有现有 Operator 项目的 Operator 作者可以使用 OpenShift Container Platform 4.17 版本中发布的 Operator SDK CLI 工具来维护其项目并创建面向更新版本的 OpenShift Container Platform 的 Operator 版本。

以下与 Operator 项目相关的基础镜像被弃用。这些基础镜像的运行时功能和配置 API 仍然受支持,用于修复错误和解决 CVE。

  • 基于 Ansible 的 Operator 项目的基础镜像

  • 基于 Helm 的 Operator 项目的基础镜像

有关 OpenShift Container Platform 中已弃用或删除的主要功能的最新列表,请参阅 OpenShift Container Platform 发行说明的已弃用和已删除的功能部分。

有关不受支持的、社区维护的 Operator SDK 版本的信息,请参阅 Operator SDK (Operator Framework)

构建 Operator 支持的平台清单

可以使用make docker-buildx命令构建 Operator 及其操作数支持的平台清单。清单引用一个或多个架构的特定镜像清单。镜像清单指定镜像支持的平台。

如果您的 Operator 项目部署应用程序或其他工作负载资源,则以下过程假定应用程序的多平台镜像是在应用程序发布过程中构建的。

先决条件
  • 使用 Operator SDK 1.36.1 或更高版本构建的 Operator 项目

  • 已安装 Docker

步骤
  1. 检查 Operator 和操作数的镜像清单,以查找您的 Operator 项目可以支持哪些平台。运行以下命令以检查镜像清单

    $ docker manifest inspect <image_manifest> (1)
    1 指定镜像清单,例如redhat/ubi9:latest

    Operator 和操作数互相同意支持的平台决定了 Operator 项目的平台兼容性。

    示例输出
    {
        "manifests": [
            {
                "digest": "sha256:c0669ef34cdc14332c0f1ab0c2c01acb91d96014b172f1a76f3a39e63d1f0bda",
                "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
                "platform": {
                    "architecture": "amd64",
                    "os": "linux"
                },
                "size": 528
            },
    ...
            {
                "digest": "sha256:30e6d35703c578ee703230b9dc87ada2ba958c1928615ac8a674fcbbcbb0f281",
                "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
                "platform": {
                    "architecture": "arm64",
                    "os": "linux",
                    "variant": "v8"
                },
                "size": 528
            },
    ...
        ]
    }
  2. 如果之前的命令没有输出平台信息,则指定的基镜像可能是一个单镜像而不是镜像清单。您可以通过运行以下命令找到镜像支持的架构

    $ docker inspect <image>
  3. 对于基于 Go 的 Operator 项目,Operator SDK 在项目的 Dockerfile 中显式引用了amd64架构。请对您的 Dockerfile 进行以下更改,以将环境变量设置为平台标志指定的值

    示例 Dockerfile
    FROM golang:1.19 as builder
    ARG TARGETOS
    ARG TARGETARCH
    ...
    RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager main.go (1)
    1 GOARCH字段从amd64更改为$TARGETARCH
  4. 您的 Operator 项目的 Makefile 定义了PLATFORMS环境变量。如果您的 Operator 镜像不支持默认设置的所有平台,请编辑该变量以指定支持的平台。以下示例将支持的平台定义为linux/arm64linux/amd64

    示例 Makefile
    # ...
    PLATFORMS ?= linux/arm64,linux/amd64 (1)
    .PHONY: docker-buildx
    # ...
    1 默认情况下设置以下PLATFORMS值:linux/arm64linux/amd64linux/s390xlinux/ppc64le

    运行make docker buildx命令生成清单时,Operator SDK 会为PLATFORMS变量指定的每个平台创建一个镜像清单。

  5. 从您的 Operator 项目目录运行以下命令来构建您的管理器镜像。运行该命令将构建具有多平台支持的管理器镜像并将清单推送到您的注册表。

    $ make docker-buildx \
      IMG=<image_registry>/<organization_name>/<repository_name>:<version_or_sha>

关于多架构计算机器和 Operator 工作负载的节点亲和性规则

必须设置节点亲和性规则,以确保您的 Operator 工作负载可以在多架构计算机器上运行。节点亲和性是一组由调度程序使用的规则,用于定义 Pod 的放置位置。设置节点亲和性规则可确保您的 Operator 工作负载被调度到具有兼容架构的计算机器。

如果您的 Operator 在特定架构上性能更好,则可以设置首选节点亲和性规则,以将 Pod 调度到具有指定架构的机器。

更多信息,请参阅“关于具有多架构计算机器的集群”和“使用节点亲和性规则控制节点上的 Pod 放置”。

使用必需的节点亲和性规则来支持 Operator 项目的多架构计算机器

如果希望您的 Operator 支持多架构计算机器,则必须定义 Operator 的必需节点亲和性规则。

先决条件
  • 使用 Operator SDK 1.36.1 或更高版本创建或维护的 Operator 项目。

  • 定义 Operator 支持的平台的清单。

步骤
  1. 搜索您的 Operator 项目以查找定义 Pod 规范和 Pod 模板规范对象的 Kubernetes 清单。

    由于对象类型名称未在 YAML 文件中声明,因此请在您的 Kubernetes 清单中查找必需的containers字段。在指定 Pod 规范和 Pod 模板规范对象时,都需要containers字段。

    必须在所有定义 Pod 规范或 Pod 模板规范的 Kubernetes 清单中设置节点亲和性规则,包括PodDeploymentDaemonSetStatefulSet等对象。

    示例 Kubernetes 清单
    apiVersion: v1
    kind: Pod
    metadata:
      name: s1
    spec:
      containers:
        - name: <container_name>
          image: docker.io/<org>/<image_name>
  2. 在定义 Pod 规范和 Pod 模板规范对象的 Kubernetes 清单中设置必需的节点亲和性规则,类似于以下示例

    示例 Kubernetes 清单
    apiVersion: v1
    kind: Pod
    metadata:
      name: s1
    spec:
      containers:
        - name: <container_name>
          image: docker.io/<org>/<image_name>
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: (1)
            nodeSelectorTerms: (2)
            - matchExpressions: (3)
              - key: kubernetes.io/arch (4)
                operator: In
                values:
                - amd64
                - arm64
                - ppc64le
                - s390x
              - key: kubernetes.io/os (5)
                operator: In
                values:
                    - linux
    1 定义必需规则。
    2 如果指定与nodeAffinity类型关联的多个nodeSelectorTerms,则只有当其中一个nodeSelectorTerms满足条件时,才能将 Pod 调度到节点上。
    3 如果指定与nodeSelectorTerms关联的多个matchExpressions,则只有当所有matchExpressions都满足条件时,才能将 Pod 调度到节点上。
    4 指定清单中定义的架构。
    5 指定清单中定义的操作系统。
  3. 使用动态创建的工作负载的基于 Go 的 Operator 项目可能会将 Pod 规范和 Pod 模板规范对象嵌入到 Operator 的逻辑中。

    如果您的项目将 Pod 规范或 Pod 模板规范对象嵌入到 Operator 的逻辑中,请类似于以下示例编辑您的 Operator 逻辑。以下示例显示了如何使用 Go API 更新PodSpec对象

    Template: corev1.PodTemplateSpec{
        ...
        Spec: corev1.PodSpec{
            Affinity: &corev1.Affinity{
                NodeAffinity: &corev1.NodeAffinity{
                    RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
                        NodeSelectorTerms: []corev1.NodeSelectorTerm{
                            {
                                MatchExpressions: []corev1.NodeSelectorRequirement{
                                    {
                                        Key:      "kubernetes.io/arch",
                                        Operator: "In",
                                        Values:   []string{"amd64","arm64","ppc64le","s390x"},
                                    },
                                    {
                                        Key:      "kubernetes.io/os",
                                        Operator: "In",
                                        Values:   []string{"linux"},
                                    },
                                },
                            },
                        },
                    },
                },
            },
            SecurityContext: &corev1.PodSecurityContext{
                ...
            },
            Containers: []corev1.Container{{
                ...
            }},
        },

    其中

    RequiredDuringSchedulingIgnoredDuringExecution

    定义必需规则。

    NodeSelectorTerms

    如果指定与nodeAffinity类型关联的多个nodeSelectorTerms,则只有当其中一个nodeSelectorTerms满足条件时,才能将 Pod 调度到节点上。

    MatchExpressions

    如果指定与nodeSelectorTerms关联的多个matchExpressions,则只有当所有matchExpressions都满足条件时,才能将 Pod 调度到节点上。

    kubernetes.io/arch

    指定清单中定义的架构。

    kubernetes.io/os

    指定清单中定义的操作系统。

如果未设置节点亲和性规则并且容器被调度到架构不兼容的计算机器上,则 Pod 会失败并触发以下事件之一

CrashLoopBackOff

当镜像清单的入口点无法运行并且日志中打印exec format error消息时发生。

ImagePullBackOff

当清单不包含 Pod 调度的架构的清单或节点亲和性术语设置为错误值时发生。

使用首选节点亲和性规则为 Operator 项目配置对多架构计算机器的支持

如果您的 Operator 在特定架构上性能更好,则可以配置首选节点亲和性规则以将 Pod 调度到指定架构的节点。

先决条件
  • 使用 Operator SDK 1.36.1 或更高版本创建或维护的 Operator 项目。

  • 定义 Operator 支持的平台的清单。

  • 已为您的 Operator 项目设置必需的节点亲和性规则。

步骤
  1. 搜索您的 Operator 项目以查找定义 Pod 规范和 Pod 模板规范对象的 Kubernetes 清单。

    示例 Kubernetes 清单
    apiVersion: v1
    kind: Pod
    metadata:
      name: s1
    spec:
      containers:
        - name: <container_name>
          image: docker.io/<org>/<image_name>
  2. 在定义 Pod 规范和 Pod 模板规范对象的 Kubernetes 清单中设置 Operator 的首选节点亲和性规则,类似于以下示例

    示例 Kubernetes 清单
    apiVersion: v1
    kind: Pod
    metadata:
      name: s1
    spec:
      containers:
        - name: <container_name>
          image: docker.io/<org>/<image_name>
      affinity:
          nodeAffinity:
            preferredDuringSchedulingIgnoredDuringExecution: (1)
              - preference:
                matchExpressions: (2)
                  - key: kubernetes.io/arch (3)
                    operator: In (4)
                    values:
                    - amd64
                    - arm64
                weight: 90 (5)
    1 定义首选规则。
    2 如果指定与nodeSelectorTerms关联的多个matchExpressions,则只有当所有matchExpressions都满足条件时,才能将 Pod 调度到节点上。
    3 指定清单中定义的架构。
    4 指定一个operator。Operator 可以是InNotInExistsDoesNotExist。例如,使用In的值要求标签在节点中。
    5 指定节点的权重,有效值为1-100。优先选择权重最高的节点。