5.5. 基于 Ansible 的 Operator
5.5.1. 基于 Ansible 的 Operator 的 Operator SDK 入门
Operator SDK 包括生成 Operator 项目的选项,它利用现有 Ansible playbook 和模块将 Kubernetes 资源部署为统一应用程序,而无需编写任何 Go 代码。
如需演示使用 Operator SDK 提供的工具和库设置并运行基于 Ansible 的 Operator 的基本知识,Operator 开发人员可以为 Memcached、分布式键值存储构建基于 Ansible 的 Operator 示例,并将它部署到集群中。
5.5.1.1. 先决条件
- 已安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
)v4.8+ - Ansible 版本 v2.9.0
- Ansible Runner 版本 v1.1.0+
- Ansible Runner HTTP Event Emitter plug-in 版本 v1.0.0+
- OpenShift Python client 版本 v0.11.2+
-
使用具有
cluster-admin
权限的oc
登录到 OpenShift Container Platform 4.8 集群 - 要允许集群拉取镜像,推送镜像的存储库必须设置为公共的存储库,或必须配置一个镜像 pull secret
5.5.1.2. 创建并部署基于 Ansible 的 Operator
您可以使用 Operator SDK 为 Memcached 构建和部署简单的基于 Ansible 的 Operator。
流程
创建一个项目。
创建您的项目目录:
$ mkdir memcached-operator
切换到项目所在的目录:
$ cd memcached-operator
使用
ansible
插件运行operator-sdk init
命令以初始化项目:$ operator-sdk init \ --plugins=ansible \ --domain=example.com
创建 API。
创建简单的 Memcached API:
$ operator-sdk create api \ --group cache \ --version v1 \ --kind Memcached \ --generate-role 1
- 1
- 为 API 生成 Ansible 角色。
构建并推送 Operator 镜像。
使用默认的
Makefile
目标来构建和推送 Operator。使用镜像的 pull spec 设置IMG
,该 spec 使用您可推送到的 registry:$ make docker-build docker-push IMG=<registry>/<user>/<image_name>:<tag>
运行 Operator。
安装 CRD:
$ make install
将项目部署到集群中。将
IMG
设置为您推送的镜像:$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
创建示例自定义资源(CR)。
创建一个示例 CR:
$ oc apply -f config/samples/cache_v1_memcached.yaml \ -n memcached-operator-system
查看 CR 协调 Operator:
$ oc logs deployment.apps/memcached-operator-controller-manager \ -c manager \ -n memcached-operator-system
输出示例
... I0205 17:48:45.881666 7 leaderelection.go:253] successfully acquired lease memcached-operator-system/memcached-operator {"level":"info","ts":1612547325.8819902,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting EventSource","source":"kind source: cache.example.com/v1, Kind=Memcached"} {"level":"info","ts":1612547325.98242,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting Controller"} {"level":"info","ts":1612547325.9824686,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting workers","worker count":4} {"level":"info","ts":1612547348.8311093,"logger":"runner","msg":"Ansible-runner exited successfully","job":"4037200794235010051","name":"memcached-sample","namespace":"memcached-operator-system"}
清理。
运行以下命令清理在此流程中创建的资源:
$ make undeploy
5.5.1.3. 后续步骤
- 如需更深入地了解如何构建基于 Ansible 的 Operator,请参阅基于 Ansible 的 Operator SDK 指南。
5.5.2. 基于 Ansible 的 Operator 的 operator SDK 指南
operator 开发人员可以利用 Operator SDK 中的 Ansible 支持来为 Memcached 构建基于 Ansible 的示例 Operator、分布式键值存储并管理其生命周期。本教程介绍了以下过程:
- 创建 Memcached 部署
-
确保部署大小与
Memcached
自定义资源(CR)spec 指定的大小相同 -
使用 status writer 带有
memcached
Pod 的名称来更新Memcached
CR 状态
此过程可通过以下两个 Operator Framework 核心组件完成:
- Operator SDK
-
operator-sdk
CLI 工具和controller-runtime
库 API - Operator Lifecycle Manager (OLM)
- 集群中 Operator 的安装、升级和基于角色的访问控制(RBAC)
本教程的内容比基于 Ansible 的 Operator 开始使用 Operator SDK 内容更详细。
5.5.2.1. 先决条件
- 已安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
)v4.8+ - Ansible 版本 v2.9.0
- Ansible Runner 版本 v1.1.0+
- Ansible Runner HTTP Event Emitter plug-in 版本 v1.0.0+
- OpenShift Python client 版本 v0.11.2+
-
使用具有
cluster-admin
权限的oc
登录到 OpenShift Container Platform 4.8 集群 - 要允许集群拉取镜像,推送镜像的存储库必须设置为公共的存储库,或必须配置一个镜像 pull secret
5.5.2.2. 创建一个项目
使用 Operator SDK CLI 创建名为 memcached-operator 的
项目。
流程
为项目创建一个目录:
$ mkdir -p $HOME/projects/memcached-operator
进入该目录:
$ cd $HOME/projects/memcached-operator
使用
ansible
插件运行operator-sdk init
命令以初始化项目:$ operator-sdk init \ --plugins=ansible \ --domain=example.com
5.5.2.2.1. PROJECT 文件
operator-sdk init
命令生成的文件中是一个 Kubebuilder PROJECT
文件。从项目 root 运行的后续 operator-sdk
命令以及 help
输出可读取该文件,并注意到项目的类型是 Ansible。例如:
domain: example.com layout: ansible.sdk.operatorframework.io/v1 projectName: memcached-operator version: 3
5.5.2.3. 创建 API
使用 Operator SDK CLI 创建 Memcached API。
流程
运行以下命令创建带有组
cache
、版本v1
和种类Memcached
的 API:$ operator-sdk create api \ --group cache \ --version v1 \ --kind Memcached \ --generate-role 1
- 1
- 为 API 生成 Ansible 角色。
创建 API 后,Operator 项目会以以下结构更新:
- Memcached CRD
-
包括一个
Memcached
资源示例 - Manager(管理者)
使用以下方法将集群状态协调到所需状态的程序:
- 一个协调器,可以是 Ansible 角色或 playbook
-
一个
watches.yaml
文件,将Memcached
资源连接到memcached
Ansible 角色
5.5.2.4. 修改管理者
更新您的 Operator 项目,以提供协调逻辑,其格式为 Ansible 角色,它在每次创建、更新或删除 Memcached
资源时运行。
流程
用下列结构更新
roles/memcached/tasks/main.yml
文件:--- - name: start memcached community.kubernetes.k8s: definition: kind: Deployment apiVersion: apps/v1 metadata: name: '{{ ansible_operator_meta.name }}-memcached' namespace: '{{ ansible_operator_meta.namespace }}' spec: replicas: "{{size}}" selector: matchLabels: app: memcached template: metadata: labels: app: memcached spec: containers: - name: memcached command: - memcached - -m=64 - -o - modern - -v image: "docker.io/memcached:1.4.36-alpine" ports: - containerPort: 11211
这个
memcached
角色可确保存在memcached
部署并设置部署大小。通过编辑
roles/memcached/defaults/main.yml
文件,为您的 Ansible 角色中使用的变量设置默认值:--- # defaults file for Memcached size: 1
使用以下结构更新
config/samples/cache_v1_memcached.yaml
文件中的Memcached
示例资源:apiVersion: cache.example.com/v1 kind: Memcached metadata: name: memcached-sample spec: size: 3
自定义资源(CR)spec 中的键值对作为额外变量传递给 Ansible。
在运行 Ansible 前,Operator 会将 spec
字段中所有变量的名称转换为 snake case,即小写并附带下划线。例如,spec 中的 serviceAccount
在 Ansible 中会变成 service_account
。
您可以通过在 watches.yaml
文件中将 snakeCaseParameters
选项设置为 false
来禁用大小写转换。建议您在 Ansible 中对变量执行一些类型验证,以确保应用程序收到所需输入。
5.5.2.5. 运行 Operator
您可以使用 Operator SDK CLI 构建和运行 Operator:
- 作为 Go 程序在集群外本地运行。
- 作为集群的部署运行。
- 捆绑 Operator,并使用 Operator Lifecycle Manager(OLM)在集群中部署。
5.5.2.5.1. 在集群外本地运行
您可以作为集群外的 Go 程序运行您的 Operator 项目。这可以加快部署和测试的速度,对于开发非常有用。
流程
运行以下命令,以在
~/.kube/config
文件中配置的集群中安装自定义资源定义(CRD),并在本地运行 Operator:$ make install run
输出示例
... {"level":"info","ts":1612589622.7888272,"logger":"ansible-controller","msg":"Watching resource","Options.Group":"cache.example.com","Options.Version":"v1","Options.Kind":"Memcached"} {"level":"info","ts":1612589622.7897573,"logger":"proxy","msg":"Starting to serve","Address":"127.0.0.1:8888"} {"level":"info","ts":1612589622.789971,"logger":"controller-runtime.manager","msg":"starting metrics server","path":"/metrics"} {"level":"info","ts":1612589622.7899997,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting EventSource","source":"kind source: cache.example.com/v1, Kind=Memcached"} {"level":"info","ts":1612589622.8904517,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting Controller"} {"level":"info","ts":1612589622.8905244,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting workers","worker count":8}
5.5.2.5.2. 作为集群的部署运行
您可以作为一个部署在集群中运行 Operator 项目。
流程
运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<image_name>:<tag>
注意镜像的名称和标签,如
IMG=<registry> /<user> /<image_name>:<tag>
,在两个命令中都可在您的 Makefile 中设置。修改IMG ?= controller:latest
值来设置您的默认镜像名称。
运行以下命令来部署 Operator:
$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
默认情况下,这个命令会创建一个带有 Operator 项目名称的命名空间,格式为
<project_name>-system
,用于部署。此命令还从config/rbac
安装 RBAC 清单。验证 Operator 是否正在运行:
$ oc get deployment -n <project_name>-system
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE <project_name>-controller-manager 1/1 1 1 8m
5.5.2.5.3. 捆绑 Operator 并使用 Operator Lifecycle Manager 进行部署
5.5.2.5.3.1. 捆绑 Operator
Operator 捆绑包格式是 Operator SDK 和 Operator Lifecycle Manager(OLM)的默认打包方法。您可以使用 Operator SDK 来构建和推送 Operator 项目作为捆绑包镜像,使 Operator 可供 OLM 使用。
先决条件
- 在开发工作站上安装 operator SDK CLI
-
已安装 OpenShift CLI(
oc
))v4.8+ - 使用 Operator SDK 初始化 operator 项目
流程
在 Operator 项目目录中运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<operator_image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<operator_image_name>:<tag>
运行
make bundle
命令创建 Operator 捆绑包清单,该命令调用多个命令,其中包括 Operator SDKgenerate bundle
和bundle validate
子命令:$ make bundle IMG=<registry>/<user>/<operator_image_name>:<tag>
Operator 的捆绑包清单描述了如何显示、创建和管理应用程序。
make bundle
命令在 Operator 项目中创建以下文件和目录:-
包含
ClusterServiceVersion
对象的捆绑包清单目录,名为bundle/manifests
-
名为
bundle/metadata
的捆绑包元数据目录 -
config/crd
目录中的所有自定义资源定义(CRD) -
一个 Dockerfile
bundle.Dockerfile
然后,使用
operator-sdk bundle validate
自动验证这些文件,以确保磁盘上的捆绑包的格式是正确的。-
包含
运行以下命令来构建和推送捆绑包镜像。OLM 使用索引镜像来消耗 Operator 捆绑包,该镜像引用一个或多个捆绑包镜像。
构建捆绑包镜像。使用您要推送镜像的 registry、用户命名空间和镜像标签的详情,设置
BUNDLE_IMG
:$ make bundle-build BUNDLE_IMG=<registry>/<user>/<bundle_image_name>:<tag>
推送捆绑包镜像:
$ docker push <registry>/<user>/<bundle_image_name>:<tag>
5.5.2.5.3.2. 使用 Operator Lifecycle Manager 部署 Operator
Operator Lifecycle Manager(OLM)可帮助您在 Kubernetes 集群中安装、更新和管理 Operator 及其相关服务的生命周期。OLM 在 OpenShift Container Platform 上默认安装,并作为 Kubernetes 扩展运行,以便您可以在没有任何额外工具的情况下将 Web 控制台和 OpenShift CLI(oc
)用于所有 Operator 生命周期管理功能。
Operator Bundle Format 是 Operator SDK 和 OLM 的默认打包方法。您可以使用 Operator SDK 在 OLM 上快速运行捆绑包镜像,以确保它正确运行。
先决条件
- 在开发工作站上安装 operator SDK CLI
- 构建并推送到 registry 的 Operator 捆绑包镜像
-
OLM安装在一个基于 Kubernetes 的集群上(如果使用
apiextensions.k8s.io/v1
CRD,则为 v1.16.0 或更新版本,如 OpenShift Container Platform 4.8) -
使用具有
cluster-admin
权限的账户使用oc
登录到集群
流程
输入以下命令在集群中运行 Operator:
$ operator-sdk run bundle \ [-n <namespace>] \1 <registry>/<user>/<bundle_image_name>:<tag>
- 1
- 默认情况下,命令会在
~/.kube/config
文件中当前活跃的项目中安装 Operator。您可以添加-n
标志来为安装设置不同的命名空间范围。
这个命令执行以下操作:
- 创建引用捆绑包镜像的索引镜像。索引镜像不透明且具有临时性,但准确反映了如何将捆绑包添加到生产中的目录中。
- 创建指向新索引镜像的目录源,以便 OperatorHub 能够发现 Operator。
-
通过创建一个
OperatorGroup
、Subscription
、InstallPlan
和所有其他必要的对象(包括 RBAC),将 Operator 部署到集群中。
5.5.2.6. 创建自定义资源
安装 Operator 后,您可以通过创建一个由 Operator 在集群中提供的自定义资源(CR)来测试它。
先决条件
-
在集群中安装的 Memcached Operator 示例,它提供
Memcached
CR
流程
切换到安装 Operator 的命名空间。例如,如果使用
make deploy
命令部署 Operator:$ oc project memcached-operator-system
编辑
config/samples/cache_v1_memcached.yaml
上的Memcached
CR 清单示例,使其包含以下规格:apiVersion: cache.example.com/v1 kind: Memcached metadata: name: memcached-sample ... spec: ... size: 3
创建 CR:
$ oc apply -f config/samples/cache_v1_memcached.yaml
确保
Memcached
Operator 为示例 CR 创建部署,其大小正确:$ oc get deployments
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE memcached-operator-controller-manager 1/1 1 1 8m memcached-sample 3/3 3 3 1m
检查 pod 和 CR 状态,以确认其状态是否使用 Memcached pod 名称更新。
检查 pod:
$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE memcached-sample-6fd7c98d8-7dqdr 1/1 Running 0 1m memcached-sample-6fd7c98d8-g5k7v 1/1 Running 0 1m memcached-sample-6fd7c98d8-m7vn7 1/1 Running 0 1m
检查 CR 状态:
$ oc get memcached/memcached-sample -o yaml
输出示例
apiVersion: cache.example.com/v1 kind: Memcached metadata: ... name: memcached-sample ... spec: size: 3 status: nodes: - memcached-sample-6fd7c98d8-7dqdr - memcached-sample-6fd7c98d8-g5k7v - memcached-sample-6fd7c98d8-m7vn7
更新部署大小。
更新
config/samples/cache_v1_memcached.yaml
文件,将Memcached
CR 中的spec.size
字段从3
改为5
:$ oc patch memcached memcached-sample \ -p '{"spec":{"size": 5}}' \ --type=merge
确认 Operator 已更改部署大小:
$ oc get deployments
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE memcached-operator-controller-manager 1/1 1 1 10m memcached-sample 5/5 5 5 3m
清理本教程中创建的资源。
如果使用
make deploy
命令来测试 Operator,请运行以下命令:$ make undeploy
如果使用
operator-sdk run bundle
命令来测试 Operator,请运行以下命令:$ operator-sdk cleanup <project_name>
5.5.2.7. 其他资源
- 请参阅基于 Ansible 的 Operator 的项目布局,以了解 Operator SDK 创建的目录结构。
5.5.3. 基于 Ansible 的 Operator 的项目布局
operator-sdk
CLI 可为每个 Operator 项目生成或 scaffold 多个 软件包和文件。
5.5.3.1. 基于 Ansible 的项目布局
使用 operator-sdk init --plugins ansible
命令生成的基于 Ansible 的 Operator 项目包含以下目录和文件:
文件或目录 | 用途 |
---|---|
| 用于为 Operator 构建容器镜像的 Dockerfile。 |
| 用于构建、发布、部署容器镜像的目标,其中包含 Operator 二进制文件,用于安装和卸载自定义资源定义(CRD)。 |
| 包含 Operator 元数据信息的 YAML 文件。 |
|
基本 CRD 文件和 |
|
为部署收集所有 Operator 清单。被 |
| Controller Manager 部署。 |
|
用于监控 Operator 的 |
| 领导选举和身份验证代理的角色和角色绑定。 |
| 为 CRD 创建的资源示例。 |
| 用于测试的示例配置。 |
| 要运行的 playbook 的子目录。 |
| 要运行的角色树的子目录。 |
|
要监视的资源的 Group/version/kind(GVK)和 Ansible 调用方法。使用 |
| 包含要在构建期间安装的 Ansible 集合和角色依赖项的 YAML 文件。 |
| 模拟您角色和 Operator 端到端测试的场景。 |
5.5.4. Operator SDK 中的 Ansible 支持
5.5.4.1. 自定义资源文件
Operator 会使用 Kubernetes 的扩展机制,即自定义资源定义 (CRD),这样您的自定义资源 (CR) 的外观和行为均类似于内置的原生 Kubernetes 对象。
CR 文件格式是一个 Kubernetes 资源文件。该对象具有必填和选填字段:
字段 | 描述 |
---|---|
| 要创建 CR 的版本。 |
| 要创建 CR 的类型。 |
| 要创建的 Kubernetes 特定元数据。 |
| 传输至 Ansible 的变量键值列表。本字段默认为空。 |
|
总结对象的当前状态。对于基于 Ansible 的 Operator, |
| 要附于 CR 的 Kubernetes 特定注解。 |
以下 CR 注解列表会修改 Operator 的行为:
注解 | 描述 |
---|---|
|
为 CR 指定协调间隔。该值将通过标准 Golang 软件包 |
基于 Ansible 的 Operator 注解示例
apiVersion: "test1.example.com/v1alpha1" kind: "Test1" metadata: name: "example" annotations: ansible.operator-sdk/reconcile-period: "30s"
5.5.4.2. watches.yaml 文件
group/version/kind (GVK) 是 Kubernetes API 的唯一标识符。watches.yaml
文件包含从自定义资源(CR)中标识的自定义资源(CR)到 Ansible 角色或 playbook 的映射列表。Operator 期望这个映射文件位于 /opt/ansible/watches.yaml
的预定义位置。
字段 | 描述 |
---|---|
| 要监视的 CR 组。 |
| 要监视的 CR 版本。 |
| 要监视的 CR 类型 |
|
添加至容器中的 Ansible 角色的路径。例如:如果您的 |
|
添加至容器中的 Ansible playbook 的路径。期望这个 playbook 作为一种调用角色的方法。该字段与 |
| 给定 CR 的协调间隔,角色或 playbook 运行的频率。 |
|
如果设置为 |
watches.yaml
文件示例
- version: v1alpha1 1 group: test1.example.com kind: Test1 role: /opt/ansible/roles/Test1 - version: v1alpha1 2 group: test2.example.com kind: Test2 playbook: /opt/ansible/playbook.yml - version: v1alpha1 3 group: test3.example.com kind: Test3 playbook: /opt/ansible/test3.yml reconcilePeriod: 0 manageStatus: false
5.5.4.2.1. 高级选项
高级功能可通过添加至每个 GVK 的 watches.yaml
文件中来启用。它们可放在 group
、version
、kind
和 playbook
或 role
字段下方。
可使用 CR 上的注解覆盖每个资源的一些功能。可覆盖的选项会指定以下注解。
功能 | YAML 密钥 | 描述 | 覆盖注解 | 默认值 |
---|---|---|---|---|
协调周期 |
| 特定 CR 的协调运行间隔时间。 |
|
|
管理状态 |
|
允许 Operator 管理每个 CR |
| |
监视依赖资源 |
| 支持 Operator 动态监视由 Ansible 创建的资源。 |
| |
监控集群范围内的资源 |
| 支持 Operator 监视由 Ansible 创建的集群范围的资源。 |
| |
最大运行程序工件 |
| 管理 Ansible Runner 在 Operator 容器中为每个单独资源保存的构件目录的数量。 |
|
|
带有高级选项的 watches.yml 文件示例
- version: v1alpha1 group: app.example.com kind: AppService playbook: /opt/ansible/playbook.yml maxRunnerArtifacts: 30 reconcilePeriod: 5s manageStatus: False watchDependentResources: False
5.5.4.3. 发送至 Ansible 的额外变量
额外变量可发送至 Ansible,然后由 Operator 管理。自定义资源 (CR) 的 spec
部分作为额外变量按照键值对传递。等同于传递给 ansible-playbook
命令的额外变量。
Operator 还会在 meta
字段下传递额外变量,用于 CR 的名称和 CR 的命名空间。
对于以下 CR 示例:
apiVersion: "app.example.com/v1alpha1" kind: "Database" metadata: name: "example" spec: message: "Hello world 2" newParameter: "newParam"
作为额外变量传递至 Ansible 的结构为:
{ "meta": { "name": "<cr_name>", "namespace": "<cr_namespace>", }, "message": "Hello world 2", "new_parameter": "newParam", "_app_example_com_database": { <full_crd> }, }
message
和 newParameter
字段在顶层被设置为额外变量,meta
则为 Operator 中定义的 CR 提供相关元数据。meta
字段可使用 Ansible 中的点符号来访问,如:
--- - debug: msg: "name: {{ ansible_operator_meta.name }}, {{ ansible_operator_meta.namespace }}"
5.5.4.4. Ansible Runner 目录
Ansible Runner 会将与 Ansible 运行相关的信息保存至容器中。具体位于:/tmp/ansible-operator/runner/<group>/<version>/<kind>/<namespace>/<name>
。
其他资源
-
要了解有关
runner
目录的更多信息,请参阅 Ansible Runner 文档。
5.5.5. Kubernetes Collection for Ansible
要使用 Ansible 管理 Kubernetes 上的应用程序生命周期,您可以使用 Kubernetes Collection for Ansible。此 Ansible 模块集合允许开发人员利用通过 YAML 编写的现有 Kubernetes 资源文件,或用原生 Ansible 表达生命周期管理。
将 Ansible 与现有 Kubernetes 资源文件相结合的一个最大好处在于可使用 Jinja 模板,这样您只需借助 Ansible 中的几个变量即可轻松自定义资源。
本节详细介绍了 Kubernetes 集合的使用方法。开始之前,在本地工作站上安装集合,并使用 playbook 进行测试,然后再移至 Operator 内使用它。
5.5.5.1. 为 Ansible 安装 Kubernetes 集合
您可以在本地工作站上安装 Kubernetes Collection for Ansible。
流程
安装 Ansible 2.9+:
$ sudo dnf install ansible
安装 OpenShift python 客户端 软件包:
$ pip3 install openshift
使用以下方法之一安装 Kubernetes Collection:
您可以直接从 Ansible Galaxy 安装集合:
$ ansible-galaxy collection install community.kubernetes
如果您已初始化了 Operator,则可能在项目顶层都有一个
requirements.yml
文件。此文件指定必须安装的 Ansible 依赖项,才能让 Operator 正常工作。默认情况下,此文件会安装community.kubernetes
集合以及operator_sdk.util
集合,它为特定 Operator 的 fuctions 提供模块和插件。安装来自
requirements.yml
文件的依赖模块:$ ansible-galaxy collection install -r requirements.yml
5.5.5.2. 本地测试 Kubernetes Collection
operator 开发人员可以从其本地机器运行 Ansible 代码,而不是每次运行和重建 Operator。
先决条件
- 初始化基于 Ansible 的 Operator 项目,并使用 Operator SDK 创建具有生成 Ansible 角色的 API
- 安装 Kubernetes Collection for Ansible
流程
在基于 Ansible 的 Operator 项目目录中,使用您想要的 Ansible 逻辑来修改
roles/<kind> /tasks/main.yml
文件。在创建 API 时,当使用--generate-role
标志时,会创建roles/<kind> /
目录。<kind>
可替换与您为 API 指定的类型匹配。以下示例根据名为
state
的变量值创建并删除配置映射:--- - name: set ConfigMap example-config to {{ state }} community.kubernetes.k8s: api_version: v1 kind: ConfigMap name: example-config namespace: default 1 state: "{{ state }}" ignore_errors: true 2
修改
roles/<kind> /defaults/main.yml
文件,将默认state
设置为present
:--- state: present
通过在项目目录的顶层创建一个
playbook.yml
文件来创建一个 Ansible playbook,其中包含您的<kind>
角色:--- - hosts: localhost roles: - <kind>
运行 playbook:
$ ansible-playbook playbook.yml
输出示例
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [localhost] ******************************************************************************** TASK [Gathering Facts] ******************************************************************************** ok: [localhost] TASK [memcached : set ConfigMap example-config to present] ******************************************************************************** changed: [localhost] PLAY RECAP ******************************************************************************** localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证配置映射是否已创建:
$ oc get configmaps
输出示例
NAME DATA AGE example-config 0 2m1s
重新运行 playbook,设置
state
为absent
:$ ansible-playbook playbook.yml --extra-vars state=absent
输出示例
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [localhost] ******************************************************************************** TASK [Gathering Facts] ******************************************************************************** ok: [localhost] TASK [memcached : set ConfigMap example-config to absent] ******************************************************************************** changed: [localhost] PLAY RECAP ******************************************************************************** localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证配置映射是否已删除:
$ oc get configmaps
5.5.5.3. 后续步骤
- 如需了解当自定义资源(CR)更改时在 Operator 内触发自定义 Ansible 逻辑的详情,请参阅在 Operator 中使用 Ansible。
5.5.6. 在 Operator 中使用 Ansible
熟悉在本地使用 Kubernetes Collection for Ansible 后,当自定义资源(CR)发生变化时,您可以在 Operator 内部触发相同的 Ansible 逻辑。本示例将 Ansible 角色映射到 Operator 所监视的特定 Kubernetes 资源。该映射在 watches.yaml
文件中完成。
5.5.6.1. 自定义资源文件
Operator 会使用 Kubernetes 的扩展机制,即自定义资源定义 (CRD),这样您的自定义资源 (CR) 的外观和行为均类似于内置的原生 Kubernetes 对象。
CR 文件格式是一个 Kubernetes 资源文件。该对象具有必填和选填字段:
字段 | 描述 |
---|---|
| 要创建 CR 的版本。 |
| 要创建 CR 的类型。 |
| 要创建的 Kubernetes 特定元数据。 |
| 传输至 Ansible 的变量键值列表。本字段默认为空。 |
|
总结对象的当前状态。对于基于 Ansible 的 Operator, |
| 要附于 CR 的 Kubernetes 特定注解。 |
以下 CR 注解列表会修改 Operator 的行为:
注解 | 描述 |
---|---|
|
为 CR 指定协调间隔。该值将通过标准 Golang 软件包 |
基于 Ansible 的 Operator 注解示例
apiVersion: "test1.example.com/v1alpha1" kind: "Test1" metadata: name: "example" annotations: ansible.operator-sdk/reconcile-period: "30s"
5.5.6.2. 本地测试基于 Ansible 的 Operator
您可以使用 Operator 项目的顶层目录中的 make run
命令,测试本地运行的基于 Ansible 的 Operator 内部的逻辑。make run
Makefile 目标在本地运行 ansible-operator
二进制文件,从 watches.yaml
文件中读取并使用 ~/.kube/config
文件与 Kubernetes 集群通信,就像 k8s
模块一样。
您可以通过设置环境变量 ANSIBLE_ROLES_PATH
或者使用 ansible-roles-path
标记来自定义角色路径。如果在 ANSIBLE_ROLES_PATH
值中没有找到该角色,Operator 会在 {{current directory}}/roles
中查找它。
先决条件
- Ansible Runner 版本 v1.1.0+
- Ansible Runner HTTP Event Emitter plug-in 版本 v1.0.0+
- 执行前面的步骤在本地测试 Kubernetes Collection
流程
为自定义资源(CR)安装自定义资源定义(CRD)和正确的基于角色的访问控制(RBAC)定义:
$ make install
输出示例
/usr/bin/kustomize build config/crd | kubectl apply -f - customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created
运行
make run
命令:$ make run
输出示例
/home/user/memcached-operator/bin/ansible-operator run {"level":"info","ts":1612739145.2871568,"logger":"cmd","msg":"Version","Go Version":"go1.15.5","GOOS":"linux","GOARCH":"amd64","ansible-operator":"v1.8.0","commit":"1abf57985b43bf6a59dcd18147b3c574fa57d3f6"} ... {"level":"info","ts":1612739148.347306,"logger":"controller-runtime.metrics","msg":"metrics server is starting to listen","addr":":8080"} {"level":"info","ts":1612739148.3488882,"logger":"watches","msg":"Environment variable not set; using default value","envVar":"ANSIBLE_VERBOSITY_MEMCACHED_CACHE_EXAMPLE_COM","default":2} {"level":"info","ts":1612739148.3490262,"logger":"cmd","msg":"Environment variable not set; using default value","Namespace":"","envVar":"ANSIBLE_DEBUG_LOGS","ANSIBLE_DEBUG_LOGS":false} {"level":"info","ts":1612739148.3490646,"logger":"ansible-controller","msg":"Watching resource","Options.Group":"cache.example.com","Options.Version":"v1","Options.Kind":"Memcached"} {"level":"info","ts":1612739148.350217,"logger":"proxy","msg":"Starting to serve","Address":"127.0.0.1:8888"} {"level":"info","ts":1612739148.3506632,"logger":"controller-runtime.manager","msg":"starting metrics server","path":"/metrics"} {"level":"info","ts":1612739148.350784,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting EventSource","source":"kind source: cache.example.com/v1, Kind=Memcached"} {"level":"info","ts":1612739148.5511978,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting Controller"} {"level":"info","ts":1612739148.5512562,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting workers","worker count":8}
现在,Operator 会监控 CR 的事件,创建 CR 将触发您的 Ansible 角色运行。
注意考虑
config/samples/<gvk>.yaml
CR 清单示例:apiVersion: <group>.example.com/v1alpha1 kind: <kind> metadata: name: "<kind>-sample"
因为未设置
spec
字段,所以调用 Ansible 时无额外变量。其他部分将涵盖从 CR 传递给 Ansible 的额外变量。为 Operator 设置适当的默认值是很重要的。创建 CR 实例,并将默认变量
state
设置为present
:$ oc apply -f config/samples/<gvk>.yaml
检查
example-config
配置映射是否已创建:$ oc get configmaps
输出示例
NAME STATUS AGE example-config Active 3s
修改
config/samples/<gvk>.yaml
文件,将state
字段设置为absent
。例如:apiVersion: cache.example.com/v1 kind: Memcached metadata: name: memcached-sample spec: state: absent
应用更改:
$ oc apply -f config/samples/<gvk>.yaml
确认配置映射已被删除:
$ oc get configmap
5.5.6.3. 在集群上测试基于 Ansible 的 Operator
在 Operator 本地测试了自定义 Ansible 逻辑后,您可以在 OpenShift Container Platform 集群的 pod 内测试 Operator,该集群首选在生产环境中使用该逻辑。
您可以作为一个部署在集群中运行 Operator 项目。
流程
运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<image_name>:<tag>
注意镜像的名称和标签,如
IMG=<registry> /<user> /<image_name>:<tag>
,在两个命令中都可在您的 Makefile 中设置。修改IMG ?= controller:latest
值来设置您的默认镜像名称。
运行以下命令来部署 Operator:
$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
默认情况下,这个命令会创建一个带有 Operator 项目名称的命名空间,格式为
<project_name>-system
,用于部署。此命令还从config/rbac
安装 RBAC 清单。验证 Operator 是否正在运行:
$ oc get deployment -n <project_name>-system
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE <project_name>-controller-manager 1/1 1 1 8m
5.5.6.4. Ansible 日志
基于 Ansible 的 Operator 提供有关 Ansible 运行的日志,可用于调试 Ansible 任务。日志也可以包含有关 Operator 内部及其与 Kubernetes 交互的详细信息。
5.5.6.4.1. 查看 Ansible 日志
先决条件
- 基于 Ansible 的 Operator 作为在集群中的部署方式运行
流程
要查看基于 Ansible 的 Operator 的日志,请运行以下命令:
$ oc logs deployment/<project_name>-controller-manager \ -c manager \1 -n <namespace> 2
输出示例
{"level":"info","ts":1612732105.0579333,"logger":"cmd","msg":"Version","Go Version":"go1.15.5","GOOS":"linux","GOARCH":"amd64","ansible-operator":"v1.8.0","commit":"1abf57985b43bf6a59dcd18147b3c574fa57d3f6"} {"level":"info","ts":1612732105.0587437,"logger":"cmd","msg":"WATCH_NAMESPACE environment variable not set. Watching all namespaces.","Namespace":""} I0207 21:08:26.110949 7 request.go:645] Throttling request took 1.035521578s, request: GET:https://172.30.0.1:443/apis/flowcontrol.apiserver.k8s.io/v1alpha1?timeout=32s {"level":"info","ts":1612732107.768025,"logger":"controller-runtime.metrics","msg":"metrics server is starting to listen","addr":"127.0.0.1:8080"} {"level":"info","ts":1612732107.768796,"logger":"watches","msg":"Environment variable not set; using default value","envVar":"ANSIBLE_VERBOSITY_MEMCACHED_CACHE_EXAMPLE_COM","default":2} {"level":"info","ts":1612732107.7688773,"logger":"cmd","msg":"Environment variable not set; using default value","Namespace":"","envVar":"ANSIBLE_DEBUG_LOGS","ANSIBLE_DEBUG_LOGS":false} {"level":"info","ts":1612732107.7688901,"logger":"ansible-controller","msg":"Watching resource","Options.Group":"cache.example.com","Options.Version":"v1","Options.Kind":"Memcached"} {"level":"info","ts":1612732107.770032,"logger":"proxy","msg":"Starting to serve","Address":"127.0.0.1:8888"} I0207 21:08:27.770185 7 leaderelection.go:243] attempting to acquire leader lease memcached-operator-system/memcached-operator... {"level":"info","ts":1612732107.770202,"logger":"controller-runtime.manager","msg":"starting metrics server","path":"/metrics"} I0207 21:08:27.784854 7 leaderelection.go:253] successfully acquired lease memcached-operator-system/memcached-operator {"level":"info","ts":1612732107.7850506,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting EventSource","source":"kind source: cache.example.com/v1, Kind=Memcached"} {"level":"info","ts":1612732107.8853772,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting Controller"} {"level":"info","ts":1612732107.8854098,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting workers","worker count":4}
5.5.6.4.2. 启用完整的 Ansible 结果会包括在日志中
您可以将环境变量 ANSIBLE_DEBUG_LOGS
设置为 True
,以启用检查完整 Ansible 结果日志,这在调试时很有用。
流程
编辑
config/manager/manager.yaml
和config/default/manager_auth_proxy_patch.yaml
文件,使其包含以下配置:containers: - name: manager env: - name: ANSIBLE_DEBUG_LOGS value: "True"
5.5.6.4.3. 在日志中启用详细调试
在开发基于 Ansible 的 Operator 时,在日志中启用额外的调试可能会有所帮助。
流程
在自定义资源中添加
ansible.sdk.operatorframework.io/verbosity
注解,以启用您想要的详细程度。例如:apiVersion: "cache.example.com/v1alpha1" kind: "Memcached" metadata: name: "example-memcached" annotations: "ansible.sdk.operatorframework.io/verbosity": "4" spec: size: 4
5.5.7. 自定义资源状态管理
5.5.7.1. 基于 Ansible 的 Operator 中的自定义资源状态
基于 Ansible 的 Operator 会自动将上一次 Ansible 运行的一般信息更新到自定义资源 (CR) status
子资源中。其中包括成功和失败任务的数量以及相关的错误消息,如下所示:
status: conditions: - ansibleResult: changed: 3 completion: 2018-12-03T13:45:57.13329 failures: 1 ok: 6 skipped: 0 lastTransitionTime: 2018-12-03T13:45:57Z message: 'Status code was -1 and not [200]: Request failed: <urlopen error [Errno 113] No route to host>' reason: Failed status: "True" type: Failure - lastTransitionTime: 2018-12-03T13:46:13Z message: Running reconciliation reason: Running status: "True" type: Running
基于 Ansible 的 Operator 还支持 Operator 作者通过 k8s_status
Ansible 模块提供自定义状态值,该模块包含在 operator_sdk.util
集中。作者可以根据需要使用任意键值对从 Ansible 内部更新 status
。
基于 Ansible 的 Operator 默认始终包含如上所示的通用 Ansible 运行输出。如果不希望您的应用程序使用 Ansible 输出来更新状态,您可以通过应用程序来手动跟踪状态。
5.5.7.2. 手动跟踪自定义资源状态
您可以使用 operator_sdk.util
集合来修改基于 Ansible 的 Operator,以手动从应用程序跟踪自定义资源(CR)状态。
先决条件
- 使用 Operator SDK 创建基于 Ansible 的 Operator 项目
流程
更新
watches.yaml
文件,把一个manageStatus
项设置为false
:- version: v1 group: api.example.com kind: <kind> role: <role> manageStatus: false
使用
operator_sdk.util.k8s_status
Ansible 模块来更新子资源。例如,使用键test
和值data
更新,operator_sdk.util
可以按以下方式使用:- operator_sdk.util.k8s_status: api_version: app.example.com/v1 kind: <kind> name: "{{ ansible_operator_meta.name }}" namespace: "{{ ansible_operator_meta.namespace }}" status: test: data
您可以为角色在
meta/main.yml
文件中声明集合,用于构建基于 Ansible 的 Operator:collections: - operator_sdk.util
在角色 meta 中声明集合后,您可以直接调用
k8s_status
模块:k8s_status: ... status: key1: value1