ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Operator SDK Ansible 开发实战指南:从 Kubernetes Collection 到自定义资源状态管理

Operator SDK Ansible 开发实战指南:从 Kubernetes Collection 到自定义资源状态管理 云原生后端开发工具微服务【免费下载链接】operator-sdkSDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding.项目地址https://gitcode.com/gh_mirrors/op/operator-sdk点击查看免费下载本篇技术指南以 Operator SDK 官方文档 Development Tips 为骨架系统讲解如何开发由 Ansible 驱动的 Kubernetes Operator包括安装与本地调试 Kubernetes Collection for Ansible、通过watches.yaml将自定义资源CR事件映射到 Ansible Role、CR 注解与额外变量extra vars的传递机制以及 CRstatus子资源的状态管理策略。读完本文你将掌握一套从本地跑通 playbook到集群内运行 Operator 并排查日志的完整 Ansible Operator 开发工作流。1. 认识 Kubernetes Collection for AnsibleAnsible Operator 的核心理念是用 Ansible 描述应用在 Kubernetes 上的生命周期管理。实现这一点的桥梁是 Kubernetes Collection for Ansiblekubernetes.core。该 Collection 允许开发者直接复用已有的 Kubernetes 资源文件YAML 编写或用原生 Ansible 语法表达资源的生命周期管理最关键的是结合 Jinja 模板仅凭 Ansible 中少量变量即可对部署进行定制化无需为每个变体重写资源清单。这也是 Ansible Operator 相比 Go Operator 的核心优势——运维逻辑与 K8s 资源描述解耦业务团队可以零 Go 基础参与 Operator 开发。2. 安装 Kubernetes Collection for Ansible2.1 前置条件首先需要安装 Ansible 2.9。以 Fedora/CentOS 为例sudo dnf install ansible随后安装 Python Kubernetes Clientk8s系列模块依赖它访问集群 APIpip3 install kubernetes2.2 从 ansible-galaxy 安装 Collectionansible-galaxy collection install kubernetes.core2.3 通过 requirements.yml 安装推荐如果你已经用operator-sdk init初始化过 Operator项目顶层会有一个requirements.yml文件它声明了 Operator 运行所需的 Ansible 依赖。默认内容会安装两个 Collectionkubernetes.core提供k8s、k8s_info等与 Kubernetes 交互的模块operator_sdk.util提供 Operator 专用的模块与插件其中最典型的是k8s_status用于管理 CR 状态见下文第 6 节。安装依赖ansible-galaxy collection install -r requirements.yml3. 本地测试 Kubernetes Collection反复修改代码 → 重新构建 Operator 镜像 → 部署的循环成本很高。因此官方推荐在本地直接用ansible-playbook验证 Ansible 逻辑。3.1 初始化项目并安装依赖mkdir memcached-operator cd memcached-operator operator-sdk init --pluginsansible --domainexample.com --groupcache --versionv1alpha1 --kindMemcached --generate-role ansible-galaxy collection install -r requirements.yml3.2 编写 Role创建/删除 ConfigMap编辑roles/memcached/tasks/main.yml根据变量state的值创建或删除 ConfigMap--- - name: set ConfigMap example-config to {{ state }} kubernetes.core.k8s: api_version: v1 kind: ConfigMap name: example-config namespace: default state: {{ state }} ignore_errors: trueNote设置ignore_errors: true是为了避免删除一个不存在的 ConfigMap时任务报错中断。编辑roles/memcached/defaults/main.yml将state默认值设为present--- state: present3.3 编写并运行 playbook在项目顶层创建playbook.yml引入memcachedRole--- - hosts: localhost roles: - memcached运行$ 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 : ok2 changed1 unreachable0 failed0验证 ConfigMap 已创建$ kubectl get configmaps NAME STATUS AGE example-config Active 3s再以stateabsent重跑验证删除逻辑$ ansible-playbook playbook.yml --extra-vars stateabsent$ kubectl get configmaps No resources found in default namespace.这印证了文档中的核心观点Ansible 与既有 Kubernetes 资源文件结合的最大收益就是用几个变量的变化驱动整个部署的增删改。4. 在 Operator 中使用 Ansiblewatches.yaml 映射机制本地验证通过后下一步是让自定义资源CR变更自动触发 Ansible 逻辑。映射关系定义在watches.yaml文件中该文件位于项目顶层容器内约定路径为/opt/ansible/watches.yaml。Operator 会监听该文件中声明的资源以及通过 ownerReferences 关联的子资源并在事件发生时执行对应的 Role 或 Playbook。watches.yaml的关键字段完整参考见 Watches 文档字段含义group/version/kind被监听 CR 的 G/V/K 三元组role默认要执行的 Role与playbook互斥可以是绝对路径、ANSIBLE_ROLES_PATH下的相对路径、当前工作目录下roles子目录的相对路径甚至是已安装 Collection 的 FQCNplaybook要执行的 playbook 名称通常仅作为调用 Role 的入口vars附加的 key-value 映射会作为extra_vars传给该 watch 对应的 playbook/rolereconcilePeriod最大协调间隔默认 10 小时见下文第 5 节manageStatus是否由 Operator 统一管理 CR 状态默认trueblacklist不被监听/缓存的子资源 GVK 列表一个较完整的示例--- - version: v1alpha1 group: cache.example.com kind: Memcached role: memcached manageStatus: False vars: foo: bar blacklist: - group: version: v1 kind: ConfigMap4.1 自定义资源CR文件格式CR 文件就是标准 Kubernetes 资源文件包含以下字段apiVersion要创建的 CR 的 API 版本kind要创建的 CR 的种类metadataKubernetes 元数据spec传给 Ansible 的 key-value 变量列表可选默认空annotations追加到 CR 上的 Kubernetes 注解可选其中ansible.operator-sdk/reconcile-period等注解可修改 Operator 行为。5. CR 注解reconcile-period 与协调周期控制ansible.operator-sdk/reconcile-period注解指定了触发一次协调reconciliation的最大等待时间apiVersion: cache.example.com/v1alpha1 kind: Memcached metadata: name: example annotations: ansible.operator-sdk/reconcile-period: 30s实现细节与使用注意事项解析规则该值使用 Go 标准库time.ParseDuration解析默认单位后缀为s秒。因此30与30s等价性能权衡更短的周期能更快纠正漂移entropy但在监听了大量资源时每次协调都很昂贵过低的周期反而会降低对变更的响应能力适用场景文档明确建议仅在高级用例中使用——即watchDependentResources设置为False、且无法依赖 watch 机制的情况下例如管理不产生 Kubernetes 事件的外部资源在watches.yaml中对应的配置键为reconcilePeriod默认值为 10 小时见 Watches 文档 中的特性表。新版本 SDK 也支持以ansible.sdk.operatorframework.io/reconcile-period注解按资源覆盖该配置。6. 本地测试 Ansible Operator6.1 前置条件先通读 Ansible Operator 教程本地安装ansible-operator的 Python 依赖Pipfile.lock 及对应操作系统的编译前置包。6.2 make install runrunMakefile 目标会在本地运行ansible-operator二进制它读取./watches.yaml并像k8s模块一样使用~/.kube/config与 Kubernetes 集群通信。install目标则把 Operator 的MemcachedCRD 注册到 apiserver$ make install run /home/user/memcached-operator/bin/kustomize build config/crd | kubectl apply -f - customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created /home/user/go/bin/ansible-operator run {level:info,ts:1595899073.9861593,logger:cmd,msg:Version,Go Version:go1.13.12,GOOS:linux,GOARCH:amd64,ansible-operator:v0.19.0git} {level:info,ts:1595899073.987384,logger:cmd,msg:WATCH_NAMESPACE environment variable not set. Watching all namespaces.,Namespace:} {level:info,ts:1595899074.9504397,logger:controller-runtime.metrics,msg:metrics server is starting to listen,addr::8080} {level:info,ts:1595899074.9522583,logger:watches,msg:Environment variable not set; using default value,envVar:ANSIBLE_VERBOSITY_MEMCACHED_CACHE_EXAMPLE_COM,default:2} {level:info,ts:1595899074.9524004,logger:cmd,msg:Environment variable not set; using default value,Namespace:,envVar:ANSIBLE_DEBUG_LOGS,ANSIBLE_DEBUG_LOGS:false} {level:info,ts:1595899074.9524298,logger:ansible-controller,msg:Watching resource,Options.Group:cache.example.com,Options.Version:v1,Options.Kind:Memcached}Note可通过环境变量ANSIBLE_ROLES_PATH或--ansible-roles-path旗标自定义 Roles 路径。如果在该路径下找不到 RoleOperator 会回退到{{当前目录}}/roles下查找该机制在 Scaffolding 文档 中有同样说明。6.3 创建 CR 触发 AnsibleOperator 开始监听Memcached后创建 CR 即会触发 Role 执行。查看config/samples/cache_v1alpha1_memcached.yamlapiVersion: cache.example.com/v1alpha1 kind: Memcached metadata: name: memcached-sample由于没有设置specAnsible 被调用时不带任何额外变量——这正是第 8 节要讲的内容也解释了为 Role 的变量设置合理默认值为何如此重要。创建 CR 实例state取默认值presentkubectl create -f config/samples/cache_v1alpha1_memcached.yaml验证 ConfigMap 已创建$ kubectl get configmaps NAME STATUS AGE example-config Active 3s修改 sample 文件将state设为absent并 apply确认 ConfigMap 被删除apiVersion: cache.example.com/v1alpha1 kind: Memcached metadata: name: memcached-sample spec: state: absentkubectl apply -f config/samples/cache_v1alpha1_memcached.yaml kubectl get configmaps7. 集群内测试与日志查看7.1 构建镜像并部署生产环境中 Operator 以 Pod 形式运行在集群内。构建并推送镜像make docker-build docker-push IMGexample.com/memcached-operator:v0.0.1部署 Operatormake install make deploy IMGexample.com/memcached-operator:v0.0.1验证 Deployment 状态$ kubectl get deployment -n memcached-operator-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 1m7.2 查看 Ansible 日志kubectl logs deployment/memcached-operator-controller-manager -n memcached-operator-system日志中记录了 Ansible 每次运行的信息是排查 Role 任务问题的主要手段同时它也包含 Operator 内部与 Kubernetes 交互的详细过程。开启完整调试日志设置环境变量ANSIBLE_DEBUG_LOGSTrue可以在日志中看到完整的 Ansible 运行结果。在config/manager/manager.yaml和config/default/manager_metrics_patch.yaml中配置... containers: - name: manager env: - name: ANSIBLE_DEBUG_LOGS value: True ...7.3 按 CR 调整 Ansible 详细级别开发阶段还可在单个 CR 上加ansible.sdk.operatorframework.io/verbosity注解按需提高该资源对应的 Ansible 输出详细度避免全局开启造成日志洪泛apiVersion: cache.example.com/v1alpha1 kind: Memcached metadata: name: example-memcached annotations: ansible.sdk.operatorframework.io/verbosity: 4 spec: size: 48. 自定义资源状态管理Custom Resource Status Management8.1 默认的通用状态输出默认情况下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: Running8.2 用 k8s_status 模块自定义状态如果默认状态不满足需求可以使用operator_sdk.utilCollection 提供的k8s_statusAnsible 模块从 Ansible 内部以任意 key/value 对更新status。该机制在仓库的 ansible-operator-status 提案 中标记为implemented模块接收apiVersion、kind、name、namespace以及状态 blob 和条件列表条件会校验是否符合 Kubernetes API 约定随后更新指定资源的状态子资源。完全放弃 Operator 管理状态如果希望状态完全由应用或 Role 自行维护可在watches.yaml中设置manageStatus: false- version: v1 group: api.example.com kind: Memcached role: memcached manageStatus: false调用 k8s_status 模块最简单的方式是使用完整限定 Collection 名FQCNoperator_sdk.util.k8s_status。下面的例子把status子资源更新为 keyfoo、valuebar- operator_sdk.util.k8s_status: api_version: app.example.com/v1 kind: Memcached name: {{ ansible_operator_meta.name }} namespace: {{ ansible_operator_meta.namespace }} status: foo: bar在 Role 的 meta 中声明 Collection新脚手架生成的 Ansible Operator 会在 Role 的meta/main.yml中声明 Collectionscollections: - operator_sdk.util声明后即可直接调用模块无需 FQCN- k8s_status: snip status: foo: bar8.3 Ansible Operator 的条件Conditions协调过程中 Operator 会维护少量主要条件RunningOperator 正在为该 CR 执行 Ansible 协调Successful运行结束且无错误时标记为 Successful随后等待下一次协调动作——协调周期到期、依赖资源 watch 触发或资源被更新Failed协调运行中出现任何错误时标记为 Failed并携带导致该条件的原始 Ansible 错误输出。若失败是间歇性的Operator 重跑协调循环后通常可自动恢复。9. 传给 Ansible 的额外变量Extra Vars9.1 变量来源与结构Operator 统一管理传给 Ansible 的额外变量CR 的spec中的 key-value 对会作为额外变量传递等价于命令行ansible-playbook --extra-vars的效果此外 Operator 还会在ansible_operator_meta字段下补充 CR 的名称与命名空间。对于如下 CRapiVersion: cache.example.com/v1alpha1 kind: Memcached metadata: name: memcached-sample spec: message: Hello world 2 newParameter: newParam传给 Ansible 的额外变量结构为{ ansible_operator_meta: { name: cr-name, namespace: cr-namespace, }, message: Hello world 2, new_parameter: newParam, _app_example_com_database: { Full CR }, _app_example_com_database_spec: { Full CR .spec }, }要点解读message与newParameter位于顶层作为额外变量newParameter被自动转换为 snake_case 的new_parameter——这一行为由watches.yaml中的snakeCaseParameters特性控制默认开启见 Watches 文档 的特性表ansible_operator_meta提供 CR 的元信息可在 Ansible 中通过点号访问--- - debug: msg: name: {{ ansible_operator_meta.name }}, {{ ansible_operator_meta.namespace }}此外还有_group_version_kind与_group_version_kind_spec两个隐藏变量分别携带完整 CR 与 CR 的spec便于在 Playbook 中做深度引用。10. 小结本文覆盖了 Ansible Operator 开发的全链路要点本地先行用kubernetes.coreCollection ansible-playbook在本地快速验证 Role 逻辑避免频繁重建镜像事件驱动通过watches.yaml把 CR 的 G/V/K 映射到 Role/Playbook用reconcile-period注解与reconcilePeriod配置掌控协调节奏状态自治默认通用状态输出之外可用operator_sdk.util.k8s_status模块 manageStatus: false实现完全自定义的状态管理变量贯通理解spec、ansible_operator_meta与 snake_case 转换规则为 Role 设置合理的默认值是写出健壮 Operator 的基础。需要深入的部分可继续阅读仓库内的 Ansible Operator 教程、Watches 参考文档、依赖 watch 说明 以及 状态管理设计提案。赞分享云原生后端开发工具微服务【免费下载链接】operator-sdkSDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding.项目地址https://gitcode.com/gh_mirrors/op/operator-sdk点击查看免费下载相关推荐Operator SDK自定义资源定义扩展Kubernetes功能Operator SDK自定义资源定义扩展Kubernetes功能 你还在为Kubernetes原生资源无法满足业务需求而烦恼吗当Deployment、Se云原生后端开发工具微服务如何使用CocoaPods-Rome快速生成动态框架完整安装与配置指南如何使用CocoaPods Rome快速生成动态框架完整安装与配置指南 CocoaPods Rome是一款强大的CocoaPods插件能够帮助开发者轻松生成Arnis 自定义存储路径Minecraft 世界文件想存哪就存哪Arnis 自定义存储路径Minecraft 世界文件想存哪就存哪 生成一座大城市的 Minecraft 世界后几十 GB 的文件落在系统盘并不理想。Arn桌面应用游戏开发GIS上一篇如何在Windows95 Electron模拟器中实现SoundBlaster 16声卡模拟完整指南下一篇Octotree性能优化异步加载与缓存策略的实现原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进