zl程序教程

您现在的位置是:首页 >  APP

当前栏目

云原生应用管理:原理与实践

2023-03-14 22:34:38 时间

第13章 全面了解Operator

  • 随着Kubernetes的蓬勃发展,在数据分析、机器学习等领域相继出现了一些场景更为复杂的分布式应用系统,这也给社区和相关应用的开发运维人员提出了新的挑战
  1. 不同场景下的分布式系统通常维护了一套自身的模型定义规范,如何在Kubernetes平台中表达或兼容出应用原先的模型定义?
  2. 当应用系统发生扩缩容或升级时,如何保证当前已有实例服务的可用性;如何保证它们之间的可连通性?
  3. 如何重新配置或定义复杂的分布式应用;是否需要大量的专业模板定义和复杂的命令操作;是否可以向无状态应用那样用一条kubectl命令就完成应用的更新?
  4. 如何备份和管理系统状态和应用数据?如何协调系统集群各成员间在不同生命周期的应用状态?

13.1 初识Operator

CoreOS在2016年底提出了Operator的概念,当时的一段官方定义如下Operator可以通过软件的方式定义人类的运维操作,并可靠地管理应用

  • 对于普通的应用开发者或是大多数的应用SRE人员来说,在他们的日常开发运维工作中,都需要基于自身的应用背景和领域知识构建相应的自动化任务,以满足业务应用的管理、监控、运维等需求。在这个过程中,Kubernetes自身的基础模型元素已经无法支撑不同业务领域下复杂的自动化场景
  • Kubernetes社区在1.7版本中提出了custom resources and controllers的概念,这正是Operator的核心概念
  • 基于custom resources和相应的自定义资源控制器,我们可以自定义扩展Kubernetes原生的模型元素,这样的自定义模型可以如同原生模型一样被Kubernetes API管理,支持kubectl命令行;
  • 这样的设计范式使得应用部署者只需要专注于配置自身应用的期望运行状态,而无须再投入大量的精力在手工部署或是业务在运行时刻的烦琐运维操作
  • Operator还提供了一套应用在运行时刻的监控管理方法,应用领域专家通过将业务关联的运维逻辑编写融入到Operator自身控制器中,而运行中的Operator就像一个7×24不间断工作的优秀运维团队,它可以时刻监控应用自身状态和该应用在Kubernetes集群中的关注事件,并在毫秒级基于期望终态做出对监听事件的处理,比如对应用的自动化容灾响应或是滚动升级等高级运维操作
  • Operator的出现无疑极大加速了这些传统的复杂分布式应用的“上云”过程

历史上第一个Operatoretcdoperatoretcdoperator可以让用户通过短短几条命令快速部署一个etcd集群,使得一个普通的开发者就可以基于kubectl命令行实现etcd集群滚动更新、灾备、备份恢复等复杂的运维操作,极大降低了etcd集群的使用门槛,在很短的时间内便成为当时K8S社区关注的焦点项目

  • 2018年初,RedHat完成了对CoreOS的收购,并在几个月后发布了OperatorFramework,通过提供SDK等管理工具进一步降低了应用开发与Kubernetes底层API知识体系间的依赖
  • 在监控方面,CoreOS开发的prometheusoperator早已成为社区的明星项目,JaegerFluentDGrafana等主流监控应用也由官方或开发者迅速推出相应的Operator并持续演进;在安全领域,AquaTwistlockSysdig等各大容器安全厂商也不甘落后,通过Operator的形式简化了相对门槛较高的容器安全应用配置
  • Operator在很短的时间内就成为了分布式应用在Kubernetes集群中部署的事实标准。同时,Operator应用如此广泛的覆盖面也使它超过了分布式应用这个原始的范畴,成为整个Kubernetes云原生应用下一个重要的存在
  • RedHat在2019年初联合AWS、谷歌、微软等大厂推出了OperatorHub.io,希望其作为Kubernetes社区的延伸,向广大Operator用户提供一个集中式的公共仓库
  • 一个Operator项目从开发到开源再到被使用的全生命周期流程
  1. 开发者首先使用OperatorSDK创建一个Operator项目
  2. 利用SDK生成Operator对应的脚手架代码,然后扩展相应业务模型和API,最后实现业务逻辑,完成一个Operator的代码编写
  3. 参考社区测试指南进行业务逻辑的本地测试以及打包和发布格式的本地校验
  4. 在完成测试后根据规定格式向社区提交PR,会有专人进行审阅
  5. 待社区审核通过完成merge后,终端用户就可以在OperatorHub.io页面上找到业务对应的Operator
  6. 用户可以在OperatorHub.io上找到业务Operator对应的说明文档和安装指南,通过简单的命令行操作即可在目标集群上完成Operator实例的安装
  7. Operator实例会根据配置创建所需的业务应用,OLMOperatorMetering等组件可以帮助用户完成业务应用对应的运维和监控采集等管理操作

图131 Operator开源生命周期流程图

13.2 Operator Framework

  • OperatorFrameworkRedHatKubernetes社区共同推出的开源项目框架,旨在帮助开发者高效快速地开发自身业务对应的Operator
  • OperatorFramework是一组用于快速开发Operator的开源工具集,它主要包含了如下3个组件

(1)OperatorSDK

  • 一个Operator开发者可以利用SDK方便地生成一套具备基础框架的Operator脚手架代码,并不需要了解如何扩展复杂的KubernetesAPI模型和具体的controller框架,开发者只需要按需完成如伸缩、升级或者灾备这样的业务强相关逻辑即可(见图132)

图132 使用OperatorSDK的构建和测试迭代过程

(2)OperatorLifecycleManager

  • 当开发者使用SDK构建好自己的Operator后,我们可以使用OperatorLifecycleManager(以下简称OLM)将其部署到对应的Kubernetes集群中。通过OLM,集群管理员可以控制Operator部署在哪些namespaces中,又有哪些合法用户或团队可以与已经运行的Operator实例进行交互

(3)OperatorMetering

  • OperatorMetering用于监控Operator实例中的应用资源使用率,除了常用的CPU和内存使用率外,用户还可以自定义其他的Metering目标;同时OperatorMetering还封装了相应的监控报告(Report)模型,方便用户定义报告的输出形式、存储目标和采集方案等具体信息
  • 首先Operator开发者利用SDK命令生成框架代码并填写业务逻辑,同时可以基于SDK完成本地和集群测试后进行Operator的打包发布

图133 OperatorFramework的应用流程

  • 应用集群管理员根据业务的需要选择OperatorOLM规定方式进行Operatorpackage的上传
  • 此时具有权限的集群用户可以通过OLM指定接口获取可供部署使用的Operator列表,并基于OLM提供的标准接口进行Operator指定版本实例的部署,同时利用OLM标准接口和OperatorMetering的计量能力进行业务应用实例的运维操作
  • OperatorFramework使得不同部门的业务应用可以在一个统一的规范下进行构建和运维,从而很好地节约企业的运维人力成本

13.3 Operator工作原理

  • CustomResource和基于业务逻辑的自定义控制器(controller)是Operator的两个重要组成部分
  • 一个完整的Operator通常需要包含如下元素
  1. 应用业务逻辑抽象出的扩展资源定义(CRD)、对应的扩展KubernetesAPI及应用运行期望终态的定义标准
  2. 用于监控应用运行状态的自定义控制器(customcontroller
  3. 控制器中的自定义业务运维逻辑,即面向CR期望终态不断进行调谐(reconcile)的业务代码
  4. Operator中自定义控制器的管理逻辑
  5. 封装OperatorCR的部署模型,比如k8sdeployment

图134 Operator工作流程

  • 这里我们以etcdoperator为例进行说明,假如我们有一个使用etcdoperator创建和维护的业务集群,有一天某运维人员因为操作失误删除了集群中的一个pod,此时operator会通过informer的机制实时捕捉到该删除事件,并通过与EtcdCluster中定义的集群期望状态进行分析比较,快速触发集群恢复的业务逻辑,进行期望版本集群pod的重新创建,保证业务的稳定性
  • 当某一天运维管理员需要对etcd集群升级时,只需要修改该etcd集群对应的扩展模型spec中的期望版本,Operator会同时收到业务更新的事件请求,并自动安排运行对应的业务升级逻辑
  • 每个Operator会在自己的生命周期中不断循环往复这个基本的工作流程,好像一个从不停歇的运维专家,时刻守护着目标业务
  • Operator在对业务逻辑的运维管理能力上更加灵活,且编程友好度高。比如当一个集群扩容时,我们希望的往往不只是单纯的增加集群容量,也希望将已有的业务数据及时同步到新增节点上,这时我们可以通过在Operator控制器中定义相应的数据迁移逻辑,进而方便地实现这样的需求

第14章 Operator Framework功能详解

14.1 Operator SDK

  • 要想使用OperatorSDK,首先需要安装其CLI工具
$ brew install operator-sdk
  • 使用如下gpgverify命令进行签名的验证
$ gpg --verify-operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
  • new命令,它是用于新建Operator项目的框架代码,通过第一个参数指定项目名称
  1. --type:初始化Operator的类型,支持ansiblehelmgo类型的Operator创建(默认类型是“go”),当创建ansiblehelm类型的Operator时需要显示指定type配置
  2. --apiversion:对应业务CRD模型中的APIVersion参数,格式为GROUP_NAME/VERSION(例如app.example.com/v1alpha1)
  3. --kind:对应业务CRD模型中的Kind字段(比如AppService
  4. --generate-playbook:生成playbook架构(仅当typeansible时生效)
  5. --helmChart:通过该参数指定的HelmChart初始化Operator,格式为,/,或一个指定的本地路径
  6. --helm-Chart-repo:指定Helm Chart的仓库地址
  7. --helm-Chart-version:指定Helm Chart的版本(默认为latest

helm类型

$ operator-sdk new app-operator --type=helm --api-version=app.example.com/v1alpha1 --kind=AppService --helmChart=myrepo/app
$ operator-sdk new app-operator --type=helm --helm-Chart=app --helm-Chart-repo=https://Charts.cloud.com/helmChartversion=1.2.3
$ operator-sdk new appoperator-type=helm --helm-Chart=/path/to/local/Chart/app1.2.3.tgz

add api

  • 使用addapi命令可以在pkg/apis目录下帮助用户生成自定义业务模型的相关定义文件,同时在depoy/crds/...目录下生成CRDCR相关模板文件。自动生成Kubernetesdeecopy和新接口在OpenAPIv3校验规范下的相关模板定义
  • apiversion:CRD的APIVersion,格式为GROUP_NAME/VERSION(比如app.example.com/v1alpha1)
  • `kindCRD类型(比如AppService
  • pkg/controller//...目录下生成新的controller,该控制器默认调谐通过apiversionkind参数指定的自定义扩展资源,controller命令支持的参数配置如下所示
  • apiversion:CRDAPIVersion,格式为GROUP_NAME/VERSION(如app.example.com/v1alpha1)
  • kindCRDKind.(如AppService
  • 生成指定apiversionkindCRDCR文件,crd命令支持的参数配置如下所示
  • 使用operatorsdkuplocal命令会在本地主机上启动Operator并支持通过kubeconfig访问目标集群,同时会为开发者设置好operator在集群中运行所需的环境变量。对于go类型的operatoruplocal命令会在本地编译并运行编译成功的二进制文件。对于非go类型的operator,命令会将operatorsdk的二进制文件作为目标operator启动运行
  1. ·enabledelve:布尔型参数,表示是否在本地开启delve调试器并监听2345端口
  2. ·kubeconfig:连接Kubernetes集群的kubeconfig文件路径,默认为$HOME/.kube/config
  3. ·namespaceoperator监听运行的指定命名空间,默认为"default
  • 我们的operator中必须通过获取WATCH_NAMESPACE环境变量并在启动时进行配置指定,这里可以使用sdkk8sutil包中的k8sutil.GetWatchNamespace方法获取
  • 通过uplocal进行operator开发的本地调试,可以有效减少重新编译过程中制作Docker镜像的时间。同时会通过{home}/.kube/config路径下或是KUBECONFIG环境变量中指定的kubeconfig连接指定集群,实现了operator在集群外的调试运行和日志查看
  • SDK生成的operator既可以监听和管理单个命名空间内的资源,也可以监听全集群所有命名空间的资源
  • 基于namespace的监控和管理显然具有更好的灵活性。我们可以为不同命名空间的operator制定解耦的升级、容灾和监控方案,同时也可以在不同命名空间下扩展相应的API定义
  1. ·deploy/operator.yaml
  2. ·设置WATCH_NAMESPACE=""为空以监听所有namespaces
  3. ·deploy/role.yaml
  4. ·使用ClusterRole替代命名空间资源Role
  5. ·deploy/role_binding.yaml
  6. ·使用ClusterRoleBinding替换RoleBinding
  7. ·在集群绑定的roleRef字段中使用ClusterRole替换Role
  8. ·如果subject中的namespace字段不为空,需要将其值设定为operator被部署的指定命名空间