12.2. 创建基于 Ansible 的 Operator
本指南概述了 Operator SDK 中的 Ansible 支持,通过一些示例指导 Operator 作者通过使用 Ansible playbook 和模块的 operator-sdk
CLI 工具来构建和运行基于 Ansible 的 Operator。
12.2.1. Operator SDK 中的 Ansible 支持
Operator Framework 是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Kubernetes 原生应用程序,即 Operator。该框架中包含 Operator SDK,可协助开发人员利用自己的专业知识来引导和构建 Operator,而无需了解 Kubernetes API 复杂性。
通过 Operator SDK 生成 Operator 项目的其中一种方案是利用现有 Ansible playbook 和模块来部署 Kubernetes 资源作为统一应用程序,而无需编写任何 Go 代码。
12.2.1.1. 自定义资源文件
Operator 会使用 Kubernetes 的扩展机制,即自定义资源定义 (CRD),这样您的自定义资源 (CR) 的外观和行为均类似于内置的原生 Kubernetes 对象。
CR 文件格式是一个 Kubernetes 资源文件。该对象具有必填和选填字段:
字段 | 描述 |
---|---|
| 要创建 CR 的版本。 |
| 要创建 CR 的类型。 |
| 要创建的 Kubernetes 特定元数据。 |
| 传输至 Ansible 的变量键值列表。本字段默认为空。 |
|
总结对象的当前状态。对于基于 Ansible 的 Operator, |
| 要附于 CR 的 Kubernetes 特定注解。 |
以下 CR 注解列表会修改 Operator 的行为:
注解 | 描述 |
---|---|
|
为 CR 指定协调间隔。该值将通过标准 Golang 软件包 |
基于 Ansible 的 Operator 注解示例
apiVersion: "foo.example.com/v1alpha1" kind: "Foo" metadata: name: "example" annotations: ansible.operator-sdk/reconcile-period: "30s"
12.2.1.2. Watches 文件
Watches 文件中包含从自定义资源 (CR)(通过 Group
、Version
和 Kind
标识)到 Ansible 角色或 playbook 的映射列表。Operator 期望该映射文件位于预定义位置,/opt/ansible/watches.yaml
。
字段 | 描述 |
---|---|
| 要监视的 CR 组。 |
| 要监视的 CR 版本。 |
| 要监视的 CR 类型 |
|
添加至容器中的 Ansible 角色的路径。例如:如果您的 |
|
添加至容器中的 Ansible playbook 的路径。该 playbook 需要以简单方式调用角色。该字段与 |
| 给定 CR 的协调间隔,角色或 playbook 运行的频率。 |
|
如果设置为 |
Watches 文件示例
- version: v1alpha1 1 group: foo.example.com kind: Foo role: /opt/ansible/roles/Foo - version: v1alpha1 2 group: bar.example.com kind: Bar playbook: /opt/ansible/playbook.yml - version: v1alpha1 3 group: baz.example.com kind: Baz playbook: /opt/ansible/baz.yml reconcilePeriod: 0 manageStatus: false
12.2.1.2.1. 高级选项
高级功能可通过添加至每个 GVK(group、version 和 kind)的 Watches 文件中进行启用。它们可放在 group
、version
、kind
和 playbook
或 role
字段下方。
可使用自定义资源 (CR) 上的注解覆盖每个资源的某些功能。可覆盖的选项会指定以下注解。
功能 | YAML 密钥 | 描述 | 覆盖注解 | 默认值 |
---|---|---|---|---|
协调周期 |
| 特定 CR 的协调运行间隔时间。 |
|
|
管理状态 |
|
支持 Operator 管理每个 CR |
| |
监视依赖资源 |
| 支持 Operator 动态监视由 Ansible 创建的资源。 |
| |
监控集群范围内的资源 |
| 支持 Operator 监视由 Ansible 创建的集群范围的资源。 |
| |
最大运行程序工件 |
| 管理 Ansible Runner 在 Operator 容器中为每个单独资源保存的构件目录的数量。 |
|
|
带有高级选项的 Watches 文件示例
- version: v1alpha1 group: app.example.com kind: AppService playbook: /opt/ansible/playbook.yml maxRunnerArtifacts: 30 reconcilePeriod: 5s manageStatus: False watchDependentResources: False
12.2.1.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: {{ meta.name }}, {{ meta.namespace }}"
12.2.1.4. Ansible Runner 目录
Ansible Runner 会将与 Ansible 运行相关的信息保存至容器中。具体位于:/tmp/ansible-operator/runner/<group>/<version>/<kind>/<namespace>/<name>
。
其他资源
-
要了解有关
runner
目录的更多信息,请参阅 Ansible Runner 文档。
12.2.2. 安装 Operator SDK CLI
Operator SDK 配有一个 CLI 工具,可协助开发人员创建、构建和部署新的 Operator 项目。您可在工作站上安装 SDK CLI,为编写您自己的 Operator 做准备。
12.2.2.1. 从 GitHub 版本安装
您可从 GitHub 上的项目下载并安装 SDK CLI 的预构建发行版文件。
先决条件
- Go v1.13+
-
docker
v17.03+、podman
v1.2.0+ 或buildah
v1.7+ -
已安装 OpenShift CLI (
oc
) 4.4+ - 访问基于 Kubernetes v1.12.0+ 的集群
- 访问容器 registry
流程
设置发行版本变量:
RELEASE_VERSION=v0.15.0
下载发行版二进制文件。
Linux:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
macOS:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
验证所下载的发行版本二进制文件。
下载所提供的 ASC 文件。
Linux:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
macOS:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
将二进制文件与对应的 ASC 文件放在同一个目录中,并运行以下命令来验证该二进制文件:
Linux:
$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
macOS:
$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
如果您的工作站上没有维护人员公钥,则会出现以下错误:
$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc $ gpg: assuming signed data in 'operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin' $ gpg: Signature made Fri Apr 5 20:03:22 2019 CEST $ gpg: using RSA key <key_id> 1 $ gpg: Can't check signature: No public key
- 1
- RSA 密钥字符串。
要下载密钥,请运行以下命令,用上一条命令输出的 RSA 密钥字符串来替换
<key_id>
:$ gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>" 1
- 1
- 如果您尚未配置密钥服务器,请使用
--keyserver
选项指定一个密钥服务器。
在您的
PATH
中安装发行版本二进制文件:Linux:
$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk $ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
macOS:
$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk $ rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
验证是否已正确安装 CLI 工具:
$ operator-sdk version
12.2.2.2. 通过 Homebrew 安装
可使用 Homebrew 来安装 SDK CLI。
先决条件
- Homebrew
-
docker
v17.03+、podman
v1.2.0+ 或buildah
v1.7+ -
已安装 OpenShift CLI (
oc
) 4.4+ - 访问基于 Kubernetes v1.12.0+ 的集群
- 访问容器 registry
流程
使用
brew
命令安装 SDK CLI:$ brew install operator-sdk
验证是否已正确安装 CLI 工具:
$ operator-sdk version
12.2.2.3. 通过源代码编译并安装
可获取 Operator SDK 源代码来编译和安装 SDK CLI。
先决条件
流程
克隆
operator-sdk
存储库:$ mkdir -p $GOPATH/src/github.com/operator-framework $ cd $GOPATH/src/github.com/operator-framework $ git clone https://github.com/operator-framework/operator-sdk $ cd operator-sdk
检查所需的发行版本分支:
$ git checkout master
编译并安装 SDK CLI:
$ make dep $ make install
该操作会在 $GOPATH/bin 中安装 CLI 二进制
operator-sdk
。验证是否已正确安装 CLI 工具:
$ operator-sdk version
12.2.3. 使用 Operator SDK 来构建基于 Ansible 的 Operator
本流程介绍了使用 Operator SDK 中的工具和库来构建由 Ansible playbook 和模块提供技术支持的简单 Memcached Operator 示例。
先决条件
- 开发工作站已安装 Operator SDK CLI
-
使用具有
cluster-admin
权限的账户访问基于 Kubernetes 的集群 v1.11.3+(如 OpenShift Container Platform 4.4) -
已安装 OpenShift CLI (
oc
) v4.1+ -
ansible
v2.6.0+ -
ansible-runner
v1.1.0+ -
ansible-runner-http
v1.0.0+
流程
创建新 Operator 项目。命名空间范围的 Operator 会监视和管理单一命名空间中的资源。命名空间范围的 Operator 因具有高灵活性而常被视为首选。这类 Operator 支持解耦升级、针对故障和监控隔离命名空间以及区别化 API 定义。
要创建基于 Ansible 的、全命名空间范围的新
memcached-operator
项目并改为其目录,请使用以下命令:$ operator-sdk new memcached-operator \ --api-version=cache.example.com/v1alpha1 \ --kind=Memcached \ --type=ansible $ cd memcached-operator
这样会创建一个
memcached-operator
项目,专门用于监视 APIVersion 为example.com/v1apha1
、Kind 为Memcached
的 Memcached 资源。自定义 Operator 逻辑。
在本例中,
memcached-operator
会针对每个Memcached
自定义资源 (CR) 执行以下协调逻辑:-
如果尚无
memcached
Deployment,请创建一个。 -
确保 Deployment 大小与
Memcached
CR 指定的大小相同。
默认情况下,
memcached-operator
会监视Memcached
资源事件,如watches.yaml
文件中所示,并执行 Ansible 角色Memcached
:- version: v1alpha1 group: cache.example.com kind: Memcached
您可选择在
watches.yaml
文件中自定义以下逻辑:指定
role
选项会将 Operator 配置为在通过 Ansible 角色启动ansible-runner
时使用该指定路径。默认情况下,新命令会填写一个绝对路径,指向您的角色应前往的位置:- version: v1alpha1 group: cache.example.com kind: Memcached role: /opt/ansible/roles/memcached
指定
watches.yaml
文件中的playbook
选项会将 Operator 配置为在通过 Ansible playbook 启动ansible-runner
时使用该指定路径。- version: v1alpha1 group: cache.example.com kind: Memcached playbook: /opt/ansible/playbook.yaml
-
如果尚无
构建 Memcached Ansible 角色。
修改
roles/memcached/
目录下生成的 Ansible 角色。该 Ansible 角色会控制修改资源时所执行的逻辑。定义
Memcached
spec。可完全在 Ansible 中定义基于 Ansible 的 Operator spec。Ansible Operator 会将 CR spec 字段中列出的所有键值对作为变量传递给 Ansible。在运行 Ansible 之前,Operator 会将 spec 字段中所有变量的名称转换为 snake 格式(小写并附带下划线)。例如,spec 中的
serviceAccount
在 Ansible 中会变成service_account
。提示您应在 Ansible 中对变量执行一些类型验证,以确保应用程序收到所需输入。
如果用户未设置
spec
字段,则请修改roles/memcached/defaults/main.yml
文件设置默认值:size: 1
定义
Memcached
Deployment。定义了
Memcached
spec 后,即可定义资源发生更改时实际应执行的 Ansible。因为这是一个 Ansible 角色,所以默认行为是执行roles/memcached/tasks/main.yml
文件中的任务。目的是在不存在 Deployment 的情况下让 Ansible 创建 Deployment,该 Deployment 将运行
memcached:1.4.36-alpine
镜像。Ansible 2.7+ 支持 k8s Ansible 模块,本示例利用该模块来控制 Deployment 定义。修改
roles/memcached/tasks/main.yml
以匹配以下内容:- name: start memcached k8s: definition: kind: Deployment apiVersion: apps/v1 metadata: name: '{{ meta.name }}-memcached' namespace: '{{ 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
注意本示例使用
size
变量来控制Memcached
Deployment 的副本数。本示例将默认值设定为1
,但任何用户都可以创建一个 CR 覆盖该默认值。
部署 CRD。
在运行 Operator 之前,Kubernetes 需要了解 Operator 将会监视的新自定义资源定义 (CRD)。部署
Memcached
CRD:$ oc create -f deploy/crds/cache.example.com_memcacheds_crd.yaml
构建并运行 Operator。
有两种方式来构建和运行 Operator:
- 作为 Kubernetes 集群内的一个 Pod。
-
作为集群外的 Go 程序,使用
operator-sdk up
命令。
选择以下任一方法:
作为 Kubernetes 集群内的一个 Pod 来运行。这是生产环境的首先方法。
构建
memcached-operator
镜像并将其推送至 registry:$ operator-sdk build quay.io/example/memcached-operator:v0.0.1 $ podman push quay.io/example/memcached-operator:v0.0.1
deploy/operator.yaml
文件中会生成 Deployment 清单。本文件中的部署镜像需要从占位符REPLACE_IMAGE
修改为之前构建的镜像。为此,请运行:$ sed -i 's|REPLACE_IMAGE|quay.io/example/memcached-operator:v0.0.1|g' deploy/operator.yaml
部署
memcached-operator
:$ oc create -f deploy/service_account.yaml $ oc create -f deploy/role.yaml $ oc create -f deploy/role_binding.yaml $ oc create -f deploy/operator.yaml
验证
memcached-operator
是否正在运行:$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 1m
在集群外运行。这是开发阶段的首选方法,可加快部署和测试的速度。
请确保已安装 Ansible Runner 和 Ansible Runner HTTP Plug-in,否则在创建 CR 时,系统会显示 Ansible Runner 出现意外错误。
此外,还务必要确保您的计算机上存在
watches.yaml
文件中引用的角色路径。因为通常会在磁盘上角色所处的位置使用容器,所以必须手动将角色复制到已配置的 Ansible 角色路径中(如/etc/ansible/roles
)。要使用
$HOME/.kube/config
中的默认 Kubernetes 配置文件在本地运行 Operator:$ operator-sdk run --local
要使用所提供的 Kubernetes 配置文件在本地运行 Operator:
$ operator-sdk run --local --kubeconfig=config
创建一个
Memcached
CR。按所示方式修改
deploy/crds/cache_v1alpha1_memcached_cr.yaml
文件并创建一个Memcached
CR:$ cat deploy/crds/cache_v1alpha1_memcached_cr.yaml apiVersion: "cache.example.com/v1alpha1" kind: "Memcached" metadata: name: "example-memcached" spec: size: 3 $ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
确保
memcached-operator
为 CR 创建 Deployment:$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 2m example-memcached 3 3 3 3 1m
检查 pod,确认已创建三个副本:
$ oc get pods NAME READY STATUS RESTARTS AGE example-memcached-6fd7c98d8-7dqdr 1/1 Running 0 1m example-memcached-6fd7c98d8-g5k7v 1/1 Running 0 1m example-memcached-6fd7c98d8-m7vn7 1/1 Running 0 1m memcached-operator-7cc7cfdf86-vvjqk 1/1 Running 0 2m
更新大小。
将
memcached
CR 中的spec.size
字段从3
改为4
,并应用以下更改:$ cat deploy/crds/cache_v1alpha1_memcached_cr.yaml apiVersion: "cache.example.com/v1alpha1" kind: "Memcached" metadata: name: "example-memcached" spec: size: 4 $ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
确认 Operator 已更改 Deployment 大小:
$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE example-memcached 4 4 4 4 5m
清理资源:
$ oc delete -f deploy/crds/cache_v1alpha1_memcached_cr.yaml $ oc delete -f deploy/operator.yaml $ oc delete -f deploy/role_binding.yaml $ oc delete -f deploy/role.yaml $ oc delete -f deploy/service_account.yaml $ oc delete -f deploy/crds/cache_v1alpha1_memcached_crd.yaml
12.2.4. 使用 k8s Ansible 模块来管理应用程序生命周期
要使用 Ansible 管理 Kubernetes 上的应用程序生命周期,您可使用 k8s
Ansible 模块。该 Ansible 模块支持开发人员利用其现有 Kubernetes 资源文件(用 YAML 编写),或用原生 Ansible 来表达生命周期管理。
将 Ansible 与现有 Kubernetes 资源文件相结合的一个最大好处在于可使用 Jinja 模板,这样您只需借助 Ansible 中的几个变量即可轻松自定义资源。
本部分将详细介绍 k8s
Ansible 模块的用途。开始之前,请先在本地工作站安装该模块,然后使用 playbook 进行测试,最后移至 Operator 中继续使用。
12.2.4.1. 安装 k8s Ansible 模块
要在本地工作站中安装 k8s
Ansible 模块:
流程
安装 Ansible 2.6+:
$ sudo yum install ansible
使用
pip
来安装 OpenShift python 客户端软件包:$ pip install openshift
12.2.4.2. 在本地测试 k8s Ansible 模块
有时,开发人员最好在其本地机器上运行 Ansible 代码,而不必每次都运行和重构 Operator。
流程
初始化基于 Ansible 的新 Operator 项目:
$ operator-sdk new --type ansible --kind Foo --api-version foo.example.com/v1alpha1 foo-operator Create foo-operator/tmp/init/galaxy-init.sh Create foo-operator/tmp/build/Dockerfile Create foo-operator/tmp/build/test-framework/Dockerfile Create foo-operator/tmp/build/go-test.sh Rendering Ansible Galaxy role [foo-operator/roles/Foo]... Cleaning up foo-operator/tmp/init Create foo-operator/watches.yaml Create foo-operator/deploy/rbac.yaml Create foo-operator/deploy/crd.yaml Create foo-operator/deploy/cr.yaml Create foo-operator/deploy/operator.yaml Run git init ... Initialized empty Git repository in /home/dymurray/go/src/github.com/dymurray/opsdk/foo-operator/.git/ Run git init done
$ cd foo-operator
使用所需 Ansible 逻辑来修改
roles/foo/tasks/main.yml
文件。本示例通过变量切换来创建和删除命名空间。- name: set test namespace to {{ state }} k8s: api_version: v1 kind: Namespace state: "{{ state }}" name: test ignore_errors: true 1
- 1
- 设置
ignore_errors: true
可确保删除不存在的项目不会失败。
修改
roles/foo/defaults/main.yml
文件,将默认state
设置为present
。state: present
在顶层目录中创建一个 Ansible playbook
playbook.yml
文件,其中包含Foo
角色:- hosts: localhost roles: - Foo
运行 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] *************************************************************************** PROCEDURE [Gathering Facts] ********************************************************************* ok: [localhost] Task [Foo : set test namespace to present] changed: [localhost] PLAY RECAP ********************************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0
检查是否已创建命名空间:
$ oc get namespace NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d test Active 3s
重新运行 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] *************************************************************************** PROCEDURE [Gathering Facts] ********************************************************************* ok: [localhost] Task [Foo : set test namespace to absent] changed: [localhost] PLAY RECAP ********************************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0
检查是否已删除命名空间:
$ oc get namespace NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d
12.2.4.3. 在 Operator 内测试 k8s Ansible 模块
熟悉在本地使用 k8s
Ansible 模块后,您可在 Operator 内触发自定义资源 (CR) 发生变化时的相同 Ansible 逻辑。本示例将 Ansible 角色映射到 Operator 所监视的特定 Kubernetes 资源。该映射在 Watches 文件中完成。
12.2.4.3.1. 本地测试基于 Ansible 的 Operator
熟悉在本地测试 Ansible 工作流后,您可以在本地运行的基于 Ansible 的 Operator 内测试逻辑。
为此,请使用 Operator 项目顶层目录中的 operator-sdk run --local
命令。该命令读取 ./watches.yaml
文件,并使用 ~/.kube/config
文件与 Kubernetes 集群通信,就像 k8s
Ansible 一样。
流程
因为
run --local
命令是从./watches.yaml
文件中读取的,所以有一些选项可供 Operator 作者使用。如果role
独立存在(默认为/opt/ansible/roles/<name>
),则必须直接从 Operator 中复制该角色至/opt/ansible/roles/
目录。这很麻烦,因为更改不会反映在当前目录中。相反,可更改
role
字段以指向当前目录并注释掉现有行:- version: v1alpha1 group: foo.example.com kind: Foo # role: /opt/ansible/roles/Foo role: /home/user/foo-operator/Foo
为自定义资源 (CR)
Foo
创建自定义资源定义 (CRD) 和适当的基于角色的访问控制 (RBAC) 定义。operator-sdk
命令会在deploy/
目录中自动生成这些文件:$ oc create -f deploy/crds/foo_v1alpha1_foo_crd.yaml $ oc create -f deploy/service_account.yaml $ oc create -f deploy/role.yaml $ oc create -f deploy/role_binding.yaml
运行
run --local
命令:$ operator-sdk run --local [...] INFO[0000] Starting to serve on 127.0.0.1:8888 INFO[0000] Watching foo.example.com/v1alpha1, Foo, default
现在 Operator 正在监视资源
Foo
中的事件,创建 CR 会触发您的 Ansible 角色运行。查看deploy/cr.yaml
文件:apiVersion: "foo.example.com/v1alpha1" kind: "Foo" metadata: name: "example"
因为未设置
spec
字段,所以调用 Ansible 时无额外变量。下一部分将介绍额外变量如何从 CR 传递至 Ansible。这也是务必要为 Operator 设置合理默认值的原因。创建
Foo
的 CR 实例,并将默认变量state
设置为present
:$ oc create -f deploy/cr.yaml
检查是否已创建命名空间
test
:$ oc get namespace NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d test Active 3s
修改
deploy/cr.yaml
文件,将state
字段设置为absent
:apiVersion: "foo.example.com/v1alpha1" kind: "Foo" metadata: name: "example" spec: state: "absent"
应用这些更改,并确认已删除命名空间:
$ oc apply -f deploy/cr.yaml $ oc get namespace NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d
12.2.4.3.2. 在集群上测试基于 Ansible 的 Operator
熟悉了在基于 Ansible 的 Operator 内部本地运行 Ansible 逻辑之后,您可在 Kubernetes 集群(如 OpenShift Container Platform)上的 Pod 内部测试 Operator。作为 Pod 在集群中运行是生产环境的首选方法。
流程
构建
foo-operator
镜像并将其推送至 registry:$ operator-sdk build quay.io/example/foo-operator:v0.0.1 $ podman push quay.io/example/foo-operator:v0.0.1
deploy/operator.yaml
文件中会生成 Deployment 清单。本文件中的 Deployment 镜像必须从占位符REPLACE_IMAGE
修改为之前构建的镜像。为此,请运行以下命令:$ sed -i 's|REPLACE_IMAGE|quay.io/example/foo-operator:v0.0.1|g' deploy/operator.yaml
如果要在 OSX 中执行这些步骤,使用以下命令:
$ sed -i "" 's|REPLACE_IMAGE|quay.io/example/foo-operator:v0.0.1|g' deploy/operator.yaml
部署
foo-operator
:$ oc create -f deploy/crds/foo_v1alpha1_foo_crd.yaml # if CRD doesn't exist already $ oc create -f deploy/service_account.yaml $ oc create -f deploy/role.yaml $ oc create -f deploy/role_binding.yaml $ oc create -f deploy/operator.yaml
验证
foo-operator
是否正在运行:$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE foo-operator 1 1 1 1 1m
12.2.5. 使用 operator_sdk.util Ansible 集合来管理自定义资源状态
基于 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 collection 中。作者可以根据需要使用任意键值对从 Ansible 内部更新 status
。
基于 Ansible 的 Operator 默认始终包含如上所示的通用 Ansible 运行输出。如果不希望您的应用程序使用 Ansible 输出来更新状态,您可以通过应用程序来手动跟踪状态。
流程
要通过应用程序手动跟踪 CR 状态,请将
manageStatus
字段设置为false
来更新 Watches 文件:- version: v1 group: api.example.com kind: Foo role: Foo manageStatus: false
然后,使用
operator_sdk.util.k8s_status
Ansible 模块来更新子资源。例如:要使用键foo
和值bar
来更新,可使用operator_sdk.util
,如下所示:- operator_sdk.util.k8s_status: api_version: app.example.com/v1 kind: Foo name: "{{ meta.name }}" namespace: "{{ meta.namespace }}" status: foo: bar
集合也可以在角色的 meta/main.yml
中声明,用于新构建的 Ansible Operator。
collections: - operator_sdk.util
在角色 meta 中声明集合可让您直接调用 k8s_status
模块:
+
k8s_status: <snip> status: foo: bar
其他资源
- 有关基于 Ansible 的 Operator 中用户驱动状态管理的更多详情,请参阅Operator SDK 的基于 Ansible 的 Operator 状态建议。
12.2.6. 其他资源
- 有关 Operator SDK 所创建的项目目录结构的信息,请参阅附录。
- Reaching for the Stars with Ansible Operator - 红帽 OpenShift 博客
- 面向红帽合作伙伴的 Operator 开发指南