多云容器编排 Karmada-Operator 实践
作者:vivo 互联网服务器团队-Zhang Rong
Karmada 作为开源的云原生多云容器编排项目,吸引了众多企业共同参与项目开发,并运行于生产环境中。同时多云也逐步成为数据中心建设的基础架构,多区域容灾与多活、大规模多集群管理、跨云弹性与迁移等场景推动云原生多云相关技术的快速发展。
一、 背景
随着 vivo 业务不断迁移到 k8s 上,集群规模和集群的数量快速增长,运维难度也急剧增加。为了构建多集群技术,我们也自研了多集群管理,但无法解决我们遇到的更多的问题。后来开始对社区相关项目做了细致的调研和测试,我们最终选择了 Karmada。
主要原因如下:
具备对多套 K8s 集群的统一管理能力,业务通过服务维度去管理资源,降低容器平台的管理难度。
跨集群的弹性伸缩和调度能力,实现跨集群的资源合理利用,从而提升资源利用率并节约成本。
Karmada 完全使用了 K8s 原生的 API,改造成本低。
容灾,Karmada 控制平面与 member 集群解藕,集群异常时支持资源重新分配。
可扩展性,如可以添加自研的调度插件和添加自研 Openkruise 解释器插件等。
在我们探索怎么使用 Karmada 的同时,我们也遇到了 Karmada 自身运维的问题。
社区部署工具较多,需要用户自己选择。当前用户部署方式如下:
Karmadactl
Karmada charts
二进制部署
hack 目录下脚本
对于上面的几种工具,在 Karmada 的社区开展了问卷调研,并生成了统计报告。
主要总结如下:
社区部署工具较多,需要用户自己选择。
部署脚本也存在缺陷,需要用户自己解决,github 上关于这方面的提问较多。
黑屏化操作,没有提供 k8s api 操作,用户难以产品化,我们主要期望对接我们的容器平台,实现可视化安装。
缺少 CI 测试和部署工具的发布计划。
etcd 集群缺少生产环境的关键功能点,如 etcd 的高可用、定期备份和恢复。
需要安装很多依赖插件,涉及到 Karmada 控制平面、Karmada 的 host 集群和 member 集群。
缺少一键部署和配置繁琐等痛点。
针对以上问题,本文将分享 Karmada-Operator 的 vivo 实践,包括 Operator 的方案选择、API、架构设计和 CI 构建等。
二、Karmada-Operator 的落地实践
2.1 Operator SDK 介绍
Operator Framework 是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Kubernetes 原生应用程序,即 Operator。Operator 利用 Kubernetes 的可扩展性来展现云服务的自动化优势,如置备、扩展以及备份和恢复,同时能够在 Kubernetes 可运行的任何地方运行。
Operator 有助于简化对 Kubernetes 上的复杂、有状态的应用程序的管理。然而,现在编写 Operator 并不容易,会面临一些挑战,如使用低级别 API、编写样板文件以及缺乏模块化功能(这会导致重复工作)。
Operator SDK 是一个框架,通过提供以下内容来降低 Operator 的编写难度:
高级 API 和抽象,用于更直观地编写操作逻辑
支架和代码生成工具,用于快速引导新项目
扩展项,覆盖常见的 Operator 用例
如上图所示,operator sdk 可以基于 helm、ansilbe 和 go 构建 operator,我们需根据当前的情况选择我们合适的 operator 框架。
2.2 方案选择
方案一:golang 开发 Operator
方案二:ansible 开发 Operator
方案三:golang 和 ansible 混合开发 Operator
根据 Karmada 的实际生产部署调研情况和 vivo 自身的实践,可以总结如下:
要支持在 K8s 集群和不依赖 K8s 集群二进制部署。
支持外部独立的 etcd 集群部署或者对接已有的 etcd 集群。
Karmada 集群具备迁移能力,如机房裁撤和机器故障等,就需要 etcd 集群管理有备份和恢复能力,如根据 etcd 备份数据快速在其它机房恢复集群。
需要支持第三方的 vip 给 Karmada-apiserver 提供负载均衡,目前 vivo 都是基于外部 vip,并提供了域名。没有使用 K8s 的 service 给 Karmada-apiserver 提供负载均衡。
Karmada 控制平面一键部署和 member 集群的自动化注册和注销。也需要获取 member 集群的 kubeconfig,pull 模式也需要在 member 集群部署 Karmada-agent。
Karmada 集群的 addons 插件安装,如 istio、anp、第三方的 crd 等安装,需要在 Karmada 的控制平面、host 主机集群,甚至需要在 member 集群上进行配置。
提供 api 能力,实现可视化部署。
针对 Karmada 单个组件的单独升级和全量升级。
支持在 offline 和离线模式。
面对 Karmada 如此复杂的条件限制,我们再来分析下上面 3 个方案谁可能比较合适。
方案一,基于 go 开发的 Operator,比较适合基于 K8s 集群的有状态服务管理,如 etcd,数据库等,比较成熟的有 etcd-Operator。Karmada 涉及到不依赖 K8s 集群二进制部署、外部 etcd、member 集群的注册、注销和插件安装,不能很好的支持或者需要增加开发量。
方案二,基于 ansible 开发的 Operator,既可以基于 K8s 集群的对状态服务管理,也可以脱离 K8s 集群对如不依赖 K8s 集群二进制部署、外部 etcd、member 集群的注册、注销和插件安装。这里主要通过 ansible 的 ssh 登录能力和 K8s 模块管理,通过调研我们也发现 90%以上的用户可以提供 ssh 登录。
方案三,基于 go+ansible 的混合的 Operator,读者可以阅读 vivo 开发的 Kubernetes-Operator,就是基于这种方案。方案三具备方案二的所有能力,因为底层都是通过 ansible 去执行。
首先我们排除了方案一,对于方案二和方案三,本人也纠结了很长是时间,最终我们选择了方案二。主要原因如下:
Operator SDK ansible 已具备了和 Operator SDK go 相等的能力,并提供 K8s、K8s_status 模块、相似的 webhook 功能去对 k8s 的资源管理,以及 reconciliation 的能力。
符合目前 Karmada 实际生产部署的需求。
简单易学,只要知道 ansbile 的 jinja 模版、和 K8s 相同的 yaml 文件。你只需要编写 ansible task,开箱即用,reconciliation 由 Operator SDK 解决。
对于常用 ansible 的人比较友好,不需要写 golang 代码。
扩展能力强,用户可自定义插件。管理端也支持 local、ssh、zeromq 三种方式连接。local 模式可以直接对接 K8s 接口,ssh 模式可以登录执行脚本。可以很好的混合使用,解决我们当前的需求。
Karmada 运维操作相对 K8s 要简单,不需要复杂的 crd 定义,ansible 需要解析少量 vars 去执行 playbook 就行。golang+ansible 模式比较适合复杂 CRD 定义和业务逻辑复杂的系统。
2.3 API 设计
如上图所示,我们只需要执行 Operator-SDK create api 命令,就可以创建 KarmadaDeployment 的 CRD,然后就可以定义 KarmadaDeployment 的 API。在 watches.yaml 里实现 Reconcile 的业务逻辑。
这里主要定义 KarmadaDeployment、EtcdBackup 和 EtcdRestore 个资源,分别用于 Karmada 的部署,和 etcd 的数据备份和恢复。ansible Operator 会根据 spec 里定义解析成 ansible 的 vars。status 将通过 ansible runner 输出为用户自定义的状态。也可以通过 ansible 的 k8s_status 更新 KarmadaDeployment 的状态。当前主要考虑的是在 K8s 运行 Karmada,后面会添加二进制部署模式,当前的 CR 没有涉及。
2.4 架构设计
如图所示 Karmada Operator 提供了容器化和二进制集群部署设计,其中 Karmada 的容器化部署不需要执行 ssh 登录,只需通过 K8s 和 k8s_status 就可以完成 karmada 控制面的管控。Karmada 的二进制部署主要通过 ssh 登录完成 Karmada 控制平面的管控。member 集群的 join 和 unjoin 需要提前提供 member 集群的 kubeconfig 文件,也可以设置 member 的登录权限操作,需要在 CR 里定义 member 集群的用户和密钥。
执行流程如下。
用户通过 KarmadaDeployment 定义 Karmada 操作
Karmada Operator 感知 KarmadaDeployment 的 CR 变化,开始进入控制器逻辑
根据用户的定义,选择是容器化部署或者二进制部署,开始执行安装、扩所容和备份等操作
执行 join/unjoin 操作,将 member 集群注册到 Karmada 集群或者注销 member 集群
2.5 Karmada 控制平面管理
如上图所示,主要是 karmada 控制平面生命周期管理,对比当前社区的部署工具我们如下优化:
标准化证书管理,主要是用 openssl 生成证书。其中 etcd 和 Karmada 证书单独分开维护,和 k8s 集群证书命名相同,方便接入我们的监控。
Karmada-apiserver 支持外部负载均衡,不限于当前的 k8s service 提供的负载均衡。
更灵活的升级策略,支持单独组件升级和全量升级。
更丰富的全局变量定义,计划支持组件配置变更等。
2.6 etcd 集群管理
etcd 集群是 Karmada 的元数据集群,生产中需要保证 etcd 集群高可用和故障恢复等。如上图展示了 etcd 集群必要的生产要素,如自动扩缩容、升级、备份和 etcd 集群的故障恢复。自研了基于 ansible 的plugins和library, 实现 etcd 集群管理能力如下:
添加 member 到存在的 etcd 集群。
etcd 集群删除 member。
etcd 集群的备份,比如支持 cephfs 的数据备份。
etcd 集群故障恢复。
etcd 集群健康状态查询。
这里定义了 etcdBackup 和 etcdRestore 的 CR,没有合并到 KarmadaDeployment 里。主要考虑到 etcd 集群本身操作的安全性和简化 KarmadaDeployment 的 ansible 任务。其中 etcdRestore 功能,可以根据 etcd 集群备份数据,实现导入到新的 etcd 集群,从而恢复 Karmada 集群所有的业务状态。当前主要场景如下:
Karmada 集群所在的机房裁撤,需要备份 etcd 数据,迁移到新的 Karmada 集群。
期望通过 Karmada-Operator 管理 Karmada 集群,只需备份 etcd 数据,实现 etcdRestore 功能即可。
Karmada 集群故障,可以通过 etcd 备份数据,结合 etcdRestroe 实现故障恢复。
2.7 member 集群管理
member 集群的生命周期管理主要有注册和注销,上图是执行的流程。为了处理 member 集群的注册和注销,这里会动态的生成 inventory。Ansible Inventory 是包含静态 Inventory 和动态 Inventory 两部分的,静态 Inventory 指的是在文件中指定的主机和组,动态 Inventory 指通过外部脚本获取主机列表,并按照 ansible 所要求的格式返回给 ansilbe 命令的。
这里 Karmada-Operator 基于 k8s 的 CR 实现了动态inventory plugins,主要通过解析 KarmadaDeployment 的 members 定义去动态的生成 inventory。这里添加了 add-member 和 del-member 2 个角色, add-member 里集群会被注册到 Karmada 控制平面,del-member 里的集群会被从 Karmada 控制平面注销,这样就可以并发的注册和注销多个 member 集群。同时也可以提供 ssh 登录模式,方便后期扩展。
三、Karmada-Operator 的 CI 介绍
为了更好的提高开发人员的体验,计划提供 Karmada-Operator 的 CI 构建能力。这里在 K8s 集群里部署 github 的 self-hosted Runner 和 kubevirt。
用户在 github 上提交 PR
触发 github Actions,我们在 self-hosted 里定义的流程
执行语法和单元测试
通过 kubevirt 创建 vm
在多个 vm 里部署 1 个 host 和 2 个 member 集群
部署 Karmada 和添加 member 集群
执行 Karmada e2e 和 bookfinfo 案例测试
计划添加的 CI 矩阵测试如下:
语法测试:
ansible-lint
shellcheck
yamllint
syntax-check
pep8
集群部署测试:
Karmadactl、charts、yaml 和二进制部署和所有配置项安装测试
join/ unjoin member 集群
升级 Karmada
etcd 集群的备份和恢复
功能测试:
Karmada e2e 测试
创建 bookinfo 案例
性能测试:
我们主要通过 kubemark 组件模拟了多个 2000 节点的 member 集群进行了性能测试,其中一个测试案例是集群故障转移,结论是 4w 个无状态 pod 能够在 15 分钟完成故障迁移,有机会可以分享我们的性能测试。
四、总结
通过社区的调研和 vivo 的实践,最终确定了 Karmada-Operator 方案设计。Karmada-Operator 具有高度可扩展性、可靠性、更直观地编写操作逻辑和开箱即用等特点,我们相信通过这种高度可扩展的声明式、自我修复云原生系统管理 Karmada,为我们全面切换到 Karmada 去管理业务提供了强有力可靠保障。
基于 ansible 的 operator 也存在如下缺点。第一点没有提供 webhook 的能力,需要自己添加或者在 ansible 的 task 添加相关的校验;第二点是自动生成了通用的 CRD 模版,没有详细可定义的脚手架工具去自动生成 CRD。
当前 Karmada-operator 还在初始阶段,提供了方案和部分实践,具体功能还需不断的完善和改进。具体可以查看 vivo 的Karmada-Operator 仓库,欢迎大家试用和提建议。当前代码提供的能力矩阵可以查看项目规划。
版权声明: 本文为 InfoQ 作者【vivo互联网技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/a665421ae10551db61836fe76】。文章转载请联系作者。
评论