Please enable Javascript to view the contents

Kubernetes 复杂有状态应用管理框架 -- Operator

 ·  ☕ 4 分钟

1. 缘起

最初,有两名 CoreOS 的员工,为了更方便部署 etcd 集群,在 etcdCluster 对象的增、删、改事件上绑定了相应的逻辑操作,借助 Kubernetes 来自动化管理 etcd 集群。

在几个月之后的 KubeCon 大会上,他们分享了这种称之为 Operator 的方案,得到社区的强烈回响。随后,大量项目宣布支持以 Operator 的方式进行运行和管理。

但来自 Google 的 Kubernetes 核心开发者并不认同 Operator。理由是,Operator 破坏了 Kubernetes 原有的设计,游离于 Controller Manager 之外,不受控制。

就在核心开发者准备放弃 Operator 之际,CoreOS 的 CTO 在社区发起征集令,收集使用这种方式的项目。由于使用的项目太多,Kubernetes 最终接纳了 Operator。

2. 原理

Operator 就是 CRD + Controller。CRD 定义用户的资源;Controller 监听 CRD 对象实例的增、删、改事件,然后执行相应的业务逻辑。

Kubernetes 中的每个资源都是一个 API 对象的集合。除了内置的资源类型,用户还可以自定义资源类型对 Kubernetes API 进行扩展。自定义资源,也可以直接使用 API 或 kubectl 进行操作。

Operator 仅依赖于 Kubernetes 申明式 API 和 Controller 的能力,实现了用户资源与具体操作的定制化关联。

2.1 CRD

Kubernetes 中的基础资源类型有 Pod、Service、Job、Deployment 等,表达能力有限。Kubernetes 提供了内建的类型 CRD(CustomResourceDefinition),用于自定义资源。
下面是一个定义资源和创建对象的例子:

1,创建新的资源类型

resourcedefinition.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # name must match the spec fields below, and be in the form: <plural>.<group>
  name: crontabs.stable.example.com
spec:
  # group name to use for REST API: /apis/<group>/<version>
  group: stable.example.com
  # version name to use for REST API: /apis/<group>/<version>
  version: v1
  # either Namespaced or Cluster
  scope: Namespaced
  names:
    # plural name to be used in the URL: /apis/<group>/<version>/<plural>
    plural: crontabs
    # singular name to be used as an alias on the CLI and for display
    singular: crontab
    # kind is normally the CamelCased singular type. Your resource manifests use this.
    kind: CronTab
    # shortNames allow shorter string to match your resource on the CLI
    shortNames:
    - ct

执行命令:

1
kubectl apply -f resourcedefinition.yaml

Kubernetes 会在 /apis/stable.example.com/v1/namespaces/*/crontabs/... 端点,新建 RESTful API。

  1. 创建自定义对象:

my-crontab.yaml

1
2
3
4
5
6
7
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image

执行命令:

1
kubectl apply -f my-crontab.yaml
  1. 查看对象:
1
kubectl get crontab

2.2 Controller

下面是 Controller 的实现逻辑:

一个 Controller 有一个或多个 Informer 来跟踪某一个资源。Informer 与 apiserver 保持通讯,一旦发现资源发生变化,立即调用 Callbacks,将对象数据放入 Workqueue 中。

Workqueue 作为 Worker 的任务队列。Worker 首先会比较 Workerqueue 中资源对象的状态与预期状态的差别,然后通过 client-go 向 apiserver 发送执行请求,直到达成预期状态。

3. 用途

Operator 项目的初衷是,开发者将运维能力固化在代码中,让运维更容易。核心在于对领域能力的实现和封装。

对于无状态应用的部署和管理,Kubernetes 得心应手。而有状态应用往往存在拓扑关系,对某些外部资源有着绑定性的依赖。虽然 Kubernetes 内置了 StatefulSet 有状态对象,但要求开发者在启动命令中添加大量领域逻辑,增加了使用难度。

Operator 的出现,为应用的动态描述提出了一套行之有效的实现规范。

Operator 将分布式应用的使用门槛降到了最低。无论一个分布式应用多么复杂,只要它为用户提供了 Operator ,那么只需要两条命令即可搞定,以 kafka 为例:

1
2
kubectl apply -f kafka-operator.yaml
kubectl apply -f kafka-cluster.yaml

Operator 的用途是管理有状态分布式应用,例如数据库、缓存、监控等。

4. 如何开发 Operator

4.1 KubeBuilder

使用 client-go 作为 Kubernetes 的客户端,用 KubeBuilder 来生成骨架代码。

KubeBuilder 封装和抽象了 controller-runtime 和 controller-tools ,用于快速构建 Operator。通过 KubeBuilder 生成 Operator 的脚手架,开发者不必关注 apiserver 通信、请求队列化等细节,只需要专注于业务逻辑的实现。

KubeBuilder 的工作流程如下:

  1. 创建一个新的工程目录
  2. 创建一个或多个资源 API CRD ,然后将字段添加到资源
  3. 在控制器中实现协调循环(reconcile loop),watch 额外的资源
  4. 在集群中运行测试(自动安装 CRD 并自动启动控制器)
  5. 更新引导集成测试测试新字段和业务逻辑
  6. 使用用户提供的 Dockerfile 构建和发布容器

4.2 Operator Framework

Operator Framework 是 CoreOS 提供的 Operator 开发框架。主要包含两个部分:

  • Operator SDK ,用于开发 Operator
  • Operator Lifecycle Manager OLM ,安装、更新和管理 Operator

Operator SDK 提供以下工作流开发 Operator:

  1. 使用 SDK 创建一个新的 Operator 项目
  2. 通过添加自定义资源(CRD)定义新的资源 API
  3. 指定使用 SDK API 来 watch 的资源
  4. 定义 Operator 的协调(reconcile)逻辑
  5. 使用 Operator SDK 构建并生成 Operator 部署清单文件

5. 参考


微信公众号
作者
微信公众号