在 Kubernetes中我们经常使用Deployment、DaemonSet、Service、ConfigMap等资源,这些资源都是 Kubernetes 的内置资源,它们的创建、更新、删除等均由 ControllerManager负责管理,触发相应的动作来满足期望状态(Spec),这种声明式的方式简化了用户的操作,用户在使用时只需关心应用程序的最终状态即可。随着 Kubernetes的发展,在大数据、人工智能等领域出现了一些场景更为复杂的分布式应用系统,原生Kubernetes内置资源在这些场景下就显得有些力不从心。
(1)不同应用平台需要管理的目标各有差异,如何在 Kubernetes中兼容定义管理的目标?
(2)如何管理和备份系统的应用数据,协调各应用之间不同生命周期的状态?
(3)能否用同样的 Kubectl 命令来管理自己定义的复杂分布式应用?
在这些场景下,Kubernetes 自身基础模型已经无法支撑不同业务领域下的自动化场景。为了满足这些需求,谷歌提出了 ThirdPartyResources(TPR)概念,允许开发者根据业务需求的变化自定义资源和控制器,用于编写面向领域知识的业务逻辑控制,这就是Operator的核心概念。
Operator是一种封装、 部署和管理 Kubernetes应用的方法, 用户可以使用KubernetesAPI和 Kubectl工 具 在 Kubernetes上 部 署 并 管 理 Kubernetes应 用。Operator基于基本 Kubernetes 资源和控制器概念构建,但又涵盖了特定领域或应用的知识,用于实现其所管理软件的整个生命周期的自动化,它是一种特定于应用的控制器,可 扩展 KubernetesAPI的功能,是 Kubernetes 用户创建、配置和管理复杂应用的实例。
在 Kubernetes内置资源中,ControllerManager实施控制循环,反复比较集群中的期望状态和实际状态,如果集群的实际状态和期望状态不一致,则采取措施使二者一致。Operator使用自定义资源(CR)管理应用,CR引入新的对象类型后,Operator监视 CR类型,并采取特定于应用的操作,确保 CR 对象当前实际状态和期望状态一致,用户可通过在Operator中编写自定义规则来扩展新功能和更新现有功能,可以像操作Kubernetes原生组件一样,通过声明式的方式定义一组业务应用的期望状态,监控操作自定义资源,该特性使Operator几乎可以在Kubernetes 中执行任何操作,包括扩展复杂的应用、版本升级、管理有状态的服务等。这种设计使应用维护人员只需要关注配置自身应用的期望运行状态,而无须投入大量的精力在部署应用或业务运行过程中频繁操作可能出错的运维命令。
1.2.1 Operator 简介
1. Operator历史
Kubernetes(k8s)作为云原生应用的基石,已然成为当今容器编排的事实标准,为用户提供了很多拿来即用的基础资源组件,如Deployment、Pod、Service、Configmap等,这些基础组件为用户应用的部署和运维提供了极大的方便,Operator的出现更是将Kubernetes在容器化道路上推向了一个新的高度。现在,让我们先来了解 Kubernetes和 Operator的历史。
Docker在 2014—2015年是容器领域的佼佼者。Docker公司前身是一个平台即服务的初创公司 dotCloud,它们发现,许多应用程序在管理依赖关系和二进制文件时需要做大量的工作,因此它们将LinuxCgroups和 Namespaces的一些功能组合成一个包,这个包就是 Docker镜像,它可以让应用程序在任何基础设施上持续运行,并提供简单的命令操作 Docker。随着 Docker的风靡,Docker容器上的应用越来越多,如何协调编排这些容器成为一个新的研究方向,因此,涌现了一批容器编排工具,包括 Nomad、Kubernetes、DockerSwarm等,各种编排工具都可以使用容器来部署、管理和扩展应用程序,但是每个工具侧重点不同,最终 Kubernetes脱颖而出。
谷 歌 于 2015年 2月 发 布 Kubernetes并 于 2016年 3月 将 其 捐 赠 给 了 CNCF。Kubernetes 对应用开发人员非常有吸引力,它减少了对基础设施的依赖,并为开发人员提供了强大的工具来编排无状态的 Docker容器。Kubernetes 项目是容器编排的核心,在于一个叫作“控制器模式”的机制中,它通过对 ETCD中的 API对象的变化进行监听,并在Controller中对这些变化进行响应,无论是 Pod 等应用对象,还是存储设备、网络等服务对象,任何一个 API对象发生变化时,Kubernetes都会调用对应的 Controller执行响应动作,实现编排动作。
2016年,原 CoreOS 工程师邓洪超和他的同事在编程过程中突然有了一个想法,作为Kubernetes项目的用户,我们能不能编写一个 Controller来定义自己所期望的编排动作呢?于是,这两位工程师将这个小项目称为 Operator,旨在通过扩展 Kubernetes原生API的方式,在 Kubernetes中添加一个新的 API对象,自定义该对象的运维动作, 就可以为Kubernetes应用提供创建、配置和管理应用生命周期能力。这个小项目一经公布, 引起了大量 Kubernetes开发者的热烈追捧,很快大量的分布式项目都通过Operator运行起来。
相比 Helm描述静态关系的编排工具,Operator 定义的是应用运行起来后整个集群的动态逻辑。得益于 Kubernetes良好的API设计范式,Operator 在保证*度的同时,还可以展现出清晰的架构和设计逻辑,开发者们可以专注于填写自己的业务逻辑,只需很小的开发量即可完成一个复杂的分布式系统的运维工作。
虽然 Operator一经面世就受到热烈追捧, 但是它的发展并不是一帆风顺的。Operator的诞生使得 Kubernetes项目的负责人 Google团队极为不适应,对于他们来说,Controller应该是隐藏在Kubernetes内部实现的核心机制,即使开放了,也应该按照 Kubernetes现有 API规范成为ControllerManager管理下的一部分,Google不希望失去 Kubernetes生态系统的主导权。随着 Kubernetes项目的发起人之一 BrendanBurns加入RedHat,Google团队和RedHad在社区推广UAS(UserAggregatedAPIServer),它允许用户编写一个自定义的 APIServer,在这里面添加自定义 API,就可以与原生的APIServer绑定,部署在一起统一提供服务。并且RedHat和 Google还建议废弃 TPR,也就是 Operator 依赖的第三方接口资源,Operator面临被关闭的风险。
在这种困境下,CoreOS公司在 GitHub 上发布了一个帖子,让社区的开发者发声,挽救 TPR和 Operator,由于 Operator的用户太多,在来自社区的压力下,Google和 RedHat最终选择了让步,Operator从绝境中重生。后来 Kubernetes使用 CRD替代了 TPR,这两种机制除了名称,其他方面并没有什么变化。
2018年,RedHad完成了对 CoreOS公司的收购,并推出了 Operator框架,进一步完善了 Operator相关工具,使 Operator的地位得到了稳固。