×

Operator开发者可以利用Operator SDK中对Helm的支持来构建一个用于Nginx的基于Helm的示例Operator,并管理其生命周期。本教程将逐步讲解以下流程

  • 创建Nginx部署

  • 确保部署大小与Nginx自定义资源(CR)规范中指定的大小相同

  • 使用状态写入器更新Nginx CR状态,其中包含nginx Pod的名称

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

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

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

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

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

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

此过程是使用Operator Framework的两个核心组件完成的

Operator SDK

operator-sdk CLI工具和controller-runtime库API

Operator Lifecycle Manager (OLM)

在集群上安装、升级和基于角色的访问控制(RBAC) Operator

本教程比OpenShift Container Platform文档中的基于Helm的Operator的Operator SDK入门更详细。

前提条件

  • 已安装Operator SDK CLI

  • 已安装OpenShift CLI (oc)

  • 使用具有dedicated-admin权限的帐户通过oc登录到Red Hat OpenShift Service on AWS集群

  • 要允许集群拉取镜像,您推送镜像的仓库必须设置为公共仓库,或者您必须配置镜像拉取密钥

创建项目

使用Operator SDK CLI创建一个名为nginx-operator的项目。

步骤
  1. 为项目创建一个目录

    $ mkdir -p $HOME/projects/nginx-operator
  2. 切换到该目录

    $ cd $HOME/projects/nginx-operator
  3. 使用helm插件运行operator-sdk init命令来初始化项目

    $ operator-sdk init \
        --plugins=helm \
        --domain=example.com \
        --group=demo \
        --version=v1 \
        --kind=Nginx

    默认情况下,helm插件使用样板Helm图表初始化项目。您可以使用其他标志(例如--helm-chart标志)来使用现有Helm图表初始化项目。

    init命令专门创建nginx-operator项目来监视API版本为example.com/v1且类型为Nginx的资源。

  4. 对于基于Helm的项目,init命令根据图表默认清单将部署的资源在config/rbac/role.yaml文件中生成RBAC规则。验证此文件中生成的规则是否满足Operator的权限要求。

现有的Helm图表

您可以选择使用现有图表(来自本地文件系统或远程图表仓库),而不是使用样板Helm图表创建项目,方法是使用以下标志

  • --helm-chart

  • --helm-chart-repo

  • --helm-chart-version

如果指定了--helm-chart标志,则--group--version--kind标志将变为可选。如果未设置,则使用以下默认值

标志

--domain

my.domain

--group

charts

--version

v1

--kind

从指定的图表中推断

如果--helm-chart标志指定本地图表存档(例如example-chart-1.2.0.tgz)或目录,则会验证和解压或复制图表到项目中。否则,Operator SDK将尝试从远程仓库获取图表。

如果--helm-chart-repo标志未指定自定义仓库URL,则支持以下图表引用格式

格式 描述

<repo_name>/<chart_name>

从名为<repo_name>的Helm图表仓库中获取名为<chart_name>的Helm图表,如$HELM_HOME/repositories/repositories.yaml文件中指定。使用helm repo add命令配置此文件。

<url>

从指定的URL获取Helm chart归档文件。

如果通过--helm-chart-repo指定了自定义仓库URL,则支持以下chart引用格式:

格式 描述

<chart_name>

--helm-chart-repo URL值指定的Helm chart仓库中获取名为<chart_name>的Helm chart。

如果未设置--helm-chart-version标志,则Operator SDK将获取Helm chart的最新可用版本。否则,它将获取指定的版本。当使用--helm-chart标志指定的chart引用特定版本时(例如,它是本地路径或URL),则不使用可选的--helm-chart-version标志。

更多细节和示例,请运行

$ operator-sdk init --plugins helm --help

PROJECT 文件

operator-sdk init命令生成的几个文件当中,包含一个Kubebuilder PROJECT文件。随后从项目根目录运行的operator-sdk命令以及help输出都会读取此文件,并知道项目类型为Helm。例如:

domain: example.com
layout:
- helm.sdk.operatorframework.io/v1
plugins:
  manifests.sdk.operatorframework.io/v2: {}
  scorecard.sdk.operatorframework.io/v2: {}
  sdk.x-openshift.io/v1: {}
projectName: nginx-operator
resources:
- api:
    crdVersion: v1
    namespaced: true
  domain: example.com
  group: demo
  kind: Nginx
  version: v1
version: "3"

理解Operator逻辑

在此示例中,nginx-operator项目为每个Nginx自定义资源(CR)执行以下协调逻辑:

  • 如果不存在,则创建一个Nginx deployment。

  • 如果不存在,则创建一个Nginx service。

  • 如果已启用且不存在,则创建一个Nginx ingress。

  • 确保deployment、service和可选的ingress与Nginx CR中指定的所需配置匹配,例如副本数量、镜像和服务类型。

默认情况下,nginx-operator项目监视watches.yaml文件中所示的Nginx资源事件,并使用指定的chart执行Helm releases。

# Use the 'create api' subcommand to add watches to this file.
- group: demo
  version: v1
  kind: Nginx
  chart: helm-charts/nginx
# +kubebuilder:scaffold:watch

示例Helm chart

创建Helm Operator项目时,Operator SDK会创建一个示例Helm chart,其中包含一组用于简单Nginx release的模板。

在此示例中,提供了deployment、service和ingress资源的模板,以及一个NOTES.txt模板,Helm chart开发者使用它来传达有关release的有用信息。

如果您还不熟悉Helm chart,请查看Helm开发者文档

修改自定义资源规范

Helm使用一个称为values的概念来提供对Helm chart默认值的自定义,这些默认值在values.yaml文件中定义。

您可以通过在自定义资源(CR)规范中设置所需的值来覆盖这些默认值。您可以使用副本数量作为示例。

步骤
  1. helm-charts/nginx/values.yaml文件有一个名为replicaCount的值,默认为1。要在您的deployment中拥有两个Nginx实例,您的CR规范必须包含replicaCount: 2

    编辑config/samples/demo_v1_nginx.yaml文件以设置replicaCount: 2

    apiVersion: demo.example.com/v1
    kind: Nginx
    metadata:
      name: nginx-sample
    ...
    spec:
    ...
      replicaCount: 2
  2. 类似地,默认服务端口设置为80。要使用8080,请编辑config/samples/demo_v1_nginx.yaml文件以设置spec.port: 8080,这将添加服务端口覆盖。

    apiVersion: demo.example.com/v1
    kind: Nginx
    metadata:
      name: nginx-sample
    spec:
      replicaCount: 2
      service:
        port: 8080

Helm Operator应用整个规范,就像它是values文件的内容一样,就像helm install -f ./overrides.yaml命令一样。

启用代理支持

Operator开发者可以开发支持网络代理的Operator。拥有dedicated-admin角色的管理员可以为Operator Lifecycle Manager (OLM)处理的环境变量配置代理支持。要支持使用代理的集群,您的Operator必须检查环境中是否存在以下标准代理变量,并将这些值传递给Operands。

  • HTTP_PROXY

  • HTTPS_PROXY

  • NO_PROXY

本教程使用HTTP_PROXY作为示例环境变量。

先决条件
  • 一个启用了集群范围出口代理的集群。

步骤
  1. 编辑watches.yaml文件,通过添加overrideValues字段来包含基于环境变量的覆盖。

    ...
    - group: demo.example.com
      version: v1alpha1
      kind: Nginx
      chart: helm-charts/nginx
      overrideValues:
        proxy.http: $HTTP_PROXY
    ...
  2. helm-charts/nginx/values.yaml文件中添加proxy.http值。

    ...
    proxy:
      http: ""
      https: ""
      no_proxy: ""
  3. 为确保chart模板支持使用这些变量,请编辑helm-charts/nginx/templates/deployment.yaml文件中的chart模板,使其包含以下内容:

    containers:
      - name: {{ .Chart.Name }}
        securityContext:
          - toYaml {{ .Values.securityContext | nindent 12 }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
          - name: http_proxy
            value: "{{ .Values.proxy.http }}"
  4. 通过向config/manager/manager.yaml文件添加以下内容来设置Operator deployment上的环境变量:

    containers:
     - args:
       - --leader-elect
       - --leader-election-id=ansible-proxy-demo
       image: controller:latest
       name: manager
       env:
         - name: "HTTP_PROXY"
           value: "http_proxy_test"

运行Operator

要构建和运行您的Operator,请使用Operator SDK CLI打包您的Operator,然后使用Operator Lifecycle Manager (OLM)将其部署到集群。

如果您希望在OpenShift Container Platform集群而不是AWS上的Red Hat OpenShift Service集群上部署您的Operator,则还有两种额外的部署选项:

  • 在集群外部作为Go程序本地运行。

  • 作为集群上的deployment运行。

其他资源

打包Operator并使用Operator Lifecycle Manager部署

打包Operator

Operator bundle格式是Operator SDK和Operator Lifecycle Manager (OLM)的默认打包方法。您可以使用Operator SDK构建和推送您的Operator项目作为bundle镜像,从而使您的Operator能够在OLM上使用。

先决条件
  • 在开发工作站上安装Operator SDK CLI

  • 已安装OpenShift CLI (oc) v+

  • 使用Operator SDK初始化Operator项目

步骤
  1. 在您的Operator项目目录中运行以下make命令以构建和推送您的Operator镜像。修改以下步骤中的IMG参数以引用您有权访问的仓库。您可以在Quay.io等仓库站点获取用于存储容器的帐户。

    1. 构建镜像

      $ make docker-build IMG=<registry>/<user>/<operator_image_name>:<tag>

      SDK为Operator生成的Dockerfile明确引用了GOARCH=amd64用于go build。这可以修改为GOARCH=$TARGETARCH以用于非AMD64架构。Docker将自动将环境变量设置为–platform指定的值。对于Buildah,需要使用–build-arg来实现此目的。更多信息,请参见多架构

    2. 将镜像推送到仓库

      $ make docker-push IMG=<registry>/<user>/<operator_image_name>:<tag>
  2. 运行make bundle命令创建您的 Operator 包清单,此命令会调用多个命令,包括 Operator SDK 的generate bundlebundle validate子命令。

    $ make bundle IMG=<registry>/<user>/<operator_image_name>:<tag>

    Operator 的包清单描述了如何显示、创建和管理应用程序。make bundle命令会在您的 Operator 项目中创建以下文件和目录:

    • 一个名为bundle/manifests的包清单目录,其中包含一个ClusterServiceVersion对象。

    • 一个名为bundle/metadata的包元数据目录。

    • config/crd目录中的所有自定义资源定义 (CRD)。

    • 一个 Dockerfile 文件:bundle.Dockerfile

    然后,这些文件会使用operator-sdk bundle validate自动验证,以确保磁盘上的包表示正确。

  3. 运行以下命令构建和推送您的包镜像。OLM 使用索引镜像来使用 Operator 包,索引镜像会引用一个或多个包镜像。

    1. 构建包镜像。使用注册表、用户命名空间和您打算推送镜像的镜像标签设置BUNDLE_IMG

      $ make bundle-build BUNDLE_IMG=<registry>/<user>/<bundle_image_name>:<tag>
    2. 推送包镜像。

      $ docker push <registry>/<user>/<bundle_image_name>:<tag>

使用 Operator Lifecycle Manager 部署 Operator

Operator Lifecycle Manager (OLM) 可帮助您安装、更新和管理 Kubernetes 集群上 Operator 及其相关服务的生命周期。OLM 在 Red Hat OpenShift Service on AWS 上默认安装,并作为 Kubernetes 扩展运行,因此您可以使用 Web 控制台和 OpenShift CLI (oc) 完成所有 Operator 生命周期管理功能,无需任何其他工具。

Operator 包格式是 Operator SDK 和 OLM 的默认打包方法。您可以使用 Operator SDK 快速在 OLM 上运行包镜像,以确保其正常运行。

先决条件
  • 在开发工作站上安装Operator SDK CLI

  • 已构建并推送到注册表的 Operator 包镜像

  • 安装在基于 Kubernetes 的集群上的 OLM(如果您使用apiextensions.k8s.io/v1 CRD,则版本为 1.16.0 或更高版本,例如 Red Hat OpenShift Service on AWS)

  • 使用具有dedicated-admin权限的帐户通过oc登录到集群。

步骤
  • 输入以下命令在集群上运行 Operator:

    $ operator-sdk run bundle \(1)
        -n <namespace> \(2)
        <registry>/<user>/<bundle_image_name>:<tag> (3)
    1 run bundle命令会创建一个有效的基于文件的目录,并使用 OLM 在您的集群上安装 Operator 包。
    2 可选:默认情况下,该命令会将 Operator 安装在~/.kube/config文件中当前活动的项目中。您可以添加-n标志来设置安装的不同命名空间范围。
    3 如果您未指定镜像,则该命令使用quay.io/operator-framework/opm:latest作为默认索引镜像。如果您指定了镜像,则该命令使用包镜像本身作为索引镜像。

    从 Red Hat OpenShift Service on AWS 4.11 开始,run bundle命令默认支持 Operator 目录的基于文件的目录格式。已弃用的 Operator 目录的 SQLite 数据库格式仍然受支持;但是,它将在未来的版本中删除。建议 Operator 作者将其工作流程迁移到基于文件的目录格式。

    此命令执行以下操作:

    • 创建一个引用您的包镜像的索引镜像。索引镜像是不透明且短暂的,但准确地反映了如何在生产环境中将包添加到目录。

    • 创建一个指向您的新索引镜像的目录源,使 OperatorHub 能够发现您的 Operator。

    • 通过创建OperatorGroupSubscriptionInstallPlan和所有其他必需的资源(包括 RBAC)将您的 Operator 部署到您的集群。

创建自定义资源

安装 Operator 后,您可以通过创建自定义资源 (CR) 来测试它,该资源现在由 Operator 在集群上提供。

先决条件
  • 在集群上安装的示例 Nginx Operator,它提供了Nginx CR。

步骤
  1. 更改到安装 Operator 的命名空间。例如,如果您使用make deploy命令部署了 Operator。

    $ oc project nginx-operator-system
  2. 编辑config/samples/demo_v1_nginx.yaml处的示例Nginx CR 清单,使其包含以下规范:

    apiVersion: demo.example.com/v1
    kind: Nginx
    metadata:
      name: nginx-sample
    ...
    spec:
    ...
      replicaCount: 3
  3. Nginx 服务帐户需要特权访问才能在 Red Hat OpenShift Service on AWS 上运行。为nginx-sample pod 的服务帐户添加以下安全上下文约束 (SCC):

    $ oc adm policy add-scc-to-user \
        anyuid system:serviceaccount:nginx-operator-system:nginx-sample
  4. 创建 CR。

    $ oc apply -f config/samples/demo_v1_nginx.yaml
  5. 确保Nginx Operator 使用正确的规模为示例 CR 创建部署。

    $ oc get deployments
    示例输出:
    NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-operator-controller-manager       1/1     1            1           8m
    nginx-sample                            3/3     3            3           1m
  6. 检查 pod 和 CR 状态,以确认状态已更新为 Nginx pod 名称。

    1. 检查 pod:

      $ oc get pods
      示例输出:
      NAME                                  READY     STATUS    RESTARTS   AGE
      nginx-sample-6fd7c98d8-7dqdr          1/1       Running   0          1m
      nginx-sample-6fd7c98d8-g5k7v          1/1       Running   0          1m
      nginx-sample-6fd7c98d8-m7vn7          1/1       Running   0          1m
    2. 检查 CR 状态:

      $ oc get nginx/nginx-sample -o yaml
      示例输出:
      apiVersion: demo.example.com/v1
      kind: Nginx
      metadata:
      ...
        name: nginx-sample
      ...
      spec:
        replicaCount: 3
      status:
        nodes:
        - nginx-sample-6fd7c98d8-7dqdr
        - nginx-sample-6fd7c98d8-g5k7v
        - nginx-sample-6fd7c98d8-m7vn7
  7. 更新部署规模。

    1. 更新config/samples/demo_v1_nginx.yaml文件,将Nginx CR 中的spec.size字段从3更改为5

      $ oc patch nginx nginx-sample \
          -p '{"spec":{"replicaCount": 5}}' \
          --type=merge
    2. 确认 Operator 已更改部署规模。

      $ oc get deployments
      示例输出:
      NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
      nginx-operator-controller-manager       1/1     1            1           10m
      nginx-sample                            5/5     5            5           3m
  8. 运行以下命令删除 CR:

    $ oc delete -f config/samples/demo_v1_nginx.yaml
  9. 清理本教程中创建的资源。

    • 如果您使用make deploy命令测试了 Operator,请运行以下命令:

      $ make undeploy
    • 如果您使用operator-sdk run bundle命令测试了 Operator,请运行以下命令:

      $ operator-sdk cleanup <project_name>

其他资源