Intro Operator

  1. What is Operator

    我们知道容器技术的发展带来了开发流程的简化:开发者不再需要费尽心力地将应用部署到不同环境下,真正所要做的只需完成核心业务的开发然后构建应用的镜像并部署(执行docker pull和docker run)。

    但是真正上生产环境的应用很难做到这种完美的转化。我们可以想象一个复杂的分布式应用在部署时需要依据依赖关系考虑执行顺序。Kubernetes就是为了解决这类生产环境遇到的问题,已经通过deployments,stateful sets,CSI等抽象了很多复杂度。但是Kubernetes目前解决的不是很完美。这类问题的关键在于大多数有状态的复杂应用都需要定制化的逻辑和策略来管理应用在生产环境的执行。这些定制化的内容就是常说的特定领域(domain-specific)知识。比如横向扩展Redis节点和扩展Postgresql的流程肯定是不一样的,遇到的故障场景也不一样。这些特定领域知识从两类人得来:一类是运维人员(operator),一类是构建软件的专家。总之,想要运行一个复杂的应用,你不得不学习这些特定的部署/管理知识。

    而Operator就是为了解决在生产环境的Kubernetes(以下简称k8s)集群里里运行应用和在开发环境运行一样容易。Operator的官方定义如下:

    An Operator is a method of packaging, deploying and managing a Kubernetes application.

    Operator提供一种方法来构建k8s原生应用,特别针对复杂的有状态的应用程序。该应用的Operator内置运维能力并且能够依据条件自动执行。比如如下场景:

    • 处理升级场景(migration logic)
    • 处理复杂的故障恢复场景
    • 横向扩展的能力(横向扩缩容)

    所以说这特别适合复杂和有状态的服务。

    用户通过Operator请求一个应用实例,而不再需要去掌握怎么去部署和管理应用。因为Operator所封装的这些运维知识原先是需要用户或者运维人员依据运行手册(runbooks),脚本来启动应用和管理应用。

    那么Operator到底是怎么做到这一点的呢?

  2. What does an operator do

    Operator通过CRD(CustomResourceDefinition)和Controller-runtime来扩展k8s API,并通过Reconcile Loop来管理应用实例。

    CRD允许你定义自己的资源类型,而Operator通过controller-runtime来观察CR(custom resource)对象,并且依据input(spec)来更新这个对象;最后更新必要的ouput(status)。K8s API会向外暴露CRD的接口并且存储CR的状态。

    因为Operator是扩张了k8s的资源对象类型,所以用户可以通过使用kubect或者k8s API更新CR来更新和管理应用(比如我们常需的安装,升级和扩展)。并且Operator还支持使用k8s的工具在k8s集群中安装/管理Operator。所以理论上, operator能给在不同的k8s集群上完成同样的功能(Easy for hybrid cloud)。

    如果我们用一张图来展示Operator的工作流程图。那么左边是应用的定义(manifest):定义了我们的应用基本属性,这里有个例子:https://github.com/edwardstudy/memcached-operator/blob/v0.0.1/deploy/crds/cache_v1alpha1_memcached_cr.yaml

apiVersion: cache.example.com/v1alpha1  
kind: Memcached  
metadata:  
  name: example-memcached
spec:  
  # Add fields here
  size: 3

而右边是k8s的原生资源类型比如pod,configmap和外部的存储扩展(NAS)。

最后Operator就作用到中间。当manifest更新(我们可以理解为应用的一个版本),Operator会获得manifest之后触发Reconcile Loop。在这个loop里Operator会观察CR所控制的资源(pods等),然后分析当前的应用状态然后进行必要的处理来驱动CR向所需的状态演变。所以一个简单的CRD也会需要在后端有复杂的操作。Operator进行的这些操作都是通过k8s API来操作k8s对象。

高级的Operator能给完成无缝升级,故障自动响应这些复杂的任务。而Operator往往又从实现应用的安装和自服务部署能力,然后走向更加复杂的自动化。

How to use Operator

我这里依据官方文档写了一个简单的memcached-operator。

我们首先download artifacts:https://github.com/edwardstudy/memcached-operator/tree/v0.0.1

首先注册CRD:

kubectl create -f deploy/crds/cache_v1alpha1_memcached_crd.yaml  

然后准备所需的RBAC和memcached-operator:

kubectl create -f deploy/service_account.yaml  
kubectl create -f deploy/role.yaml  
kubectl create -f deploy/role_binding.yaml  
kubectl create -f deploy/operator.yaml  

最后安装memcached CR:

kubectl apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml  

然后我们能给通过kubectl来检查CR的情况,并scale memcached。

https://github.com/operator-framework/operator-sdk/blob/master/doc/user-guide.md#create-a-memcached-cr

总结

在这篇文章中,我分享了什么是Operator以及Operator怎样解决在生产环境部署和管理应用的问题。Operator实现了一种打包和管理复杂应用在k8s上运行的方法。这种方法使用k8s的CRD功能和controller-runtime机制。Operator作为controller-runtime的超集,除了完成控制循环中创建、更新CR的,还能依据具体的应用场景完成更加复杂的升级,扩展自动化。

这个实现思路,正是由于K8s松耦合的设计及其核心“控制器”模型。