四、 大数据通用Operator设计与实践
上文讲述了operator实现的复杂性。不过,我们发现,越是这样复杂的应用,越是会有一些共通性:因为这些复杂应用基本都是分布式应用,只是在某些状态或部署顺序上的有些特殊需求。于是,我们针对这个现状,开发了一款通用的大数据Operator。
这个通用Operator的架构设计如下:
与市面上常见的golang编写的operator不同的是,我们鼓励用户不编写代码,而是直接用yaml来描述控制逻辑,按照感知/决策/执行三大环节来进行控制器的逻辑分解和编排设计。同时,因为有这几个环节抽象的辅助,用户在设计operator的时候能够更有目的性,对于复杂场景,不引入过多的复杂逻辑流,尽量用无状态的方式解决问题。
同时,我们还借鉴了前端框架React中的VirtualDOM的设计,在云原生场景下,引入了VirtualResource这样的一个概念。VirtualResource能够将云原生对象资源映射进行Operator的内存数据库中,让控制器能够用SQL语法快速查询和操作这些资源对象,简化Reconcile(调和)场景的逻辑复杂性。对照React框架中生命周期的概念,VirtualResource也存在生命周期的概念,用户能够控制在资源变化的不同阶段,追加一些自定义的运维描述动作。
我们在大量使用helm的情况下,发现golang template语法在进行模板渲染的时候,还是不够灵活。于是我们把整体架构栈切换到python,采用jinja2进行控制器的语法渲染,同时我们也保留helm在渲染框架中,用户能够无缝切换两种渲染引擎。
这个通用Operator的控制器将原本需要golang编写的控制层逻辑,简化成使用cmd(指令)+yaml(资源)的方式进行描述。控制器的描述示例如下:通过helm将vvp这个应用的所有yaml下发,监听service的状态变化,同步更新ingress资源的状态。
default: def: crd.yaml deploy: - cmd: helm chart: vvp/vvp values: vvp/values.yaml maintain: - watch: category: ResourceDidChange kind: Service apiVersion: v1 action: - cmd: kube-patch file: ingressUpdate.yaml
|
五、 总结
对于承载组件(Component)这个概念而言,CRD+Operator可以说是最为复杂的,但是又是最万能的,如果Helm或者Kustomize无法满足需求,Operator基本上是唯一的选择。另一方面来说,CRD+Operator一般又会和Helm/Kustomize相辅相成一起出现,最难搞的事情通过Operator与apiserver交互解决,剩下的胶水粘合,各种YAML拼接之类的交给Helm/Kustomize搞定。
同时,我们也可以看出,CRD+Operator是云原生演进时期的方案,特别适合原本非k8s的软件架构来适配k8s环境。那些原本就在k8s云原生架构下出现的软件,会逐渐淡化Operator这个概念:所有的工作负载都有对应的资源定义(CRD),他们都有能力和k8s apiserver交互。
对于承载SREWorks中的应用(Application)这个概念而言,Operator是不合适的,无他,太复杂了。一般来说,Operator只要管好自己这个独立功能在K8S中的生命周期就已经足够了。从目前的社区方向来看,Operator不会作为一整个业务场景应用解决方案去裸提供,而是与Helm/Kustomize/KubeVela/AppManager等集成并作为一个整体(组件or应用)对外发布。