《1》动手写一个operator

背景

前几天学了一下go,准备拿一个项目练练手,刚好了解到operator,想写一个管理定时任务的operator,这个定时任务主要是定时滚动更新deployment。举个例子:我创建一个cr资源,绑定了某个deployment A,当匹配到cron表达式,那么就定时滚动更新A deployment下面所有的pod。 (优雅的更新)

项目前提要求

  1. 会go
  2. 懂k8s
  3. 听过operator
  4. 见过operator-sdk

啥是crd

学习operator,首先你要知道什么是crd(CustomResourceDefinition),可以去官网看看。

想知道最简单的crd例子,可以看之前的博客:CRD

我个人理解,operator就是通过自定义的cr资源去管理符合条件的pod,类似deployment.

可以看看当前你集群中有哪些crd资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ kubectl get crd
NAME CREATED AT
alertmanagers.monitoring.coreos.com 2019-10-12T10:07:13Z
applications.app.k8s.io 2020-05-21T15:22:07Z
csidrivers.csi.storage.k8s.io 2019-10-11T08:25:46Z
csinodeinfos.csi.storage.k8s.io 2019-10-11T08:25:46Z
horizontalnodeautoscalers.autoscaling.cce.io 2020-02-13T04:16:57Z
network-attachment-definitions.k8s.cni.cncf.io 2019-10-11T08:25:07Z
permissions.rbac.cce.io 2019-10-11T08:25:10Z
podmonitors.monitoring.coreos.com 2019-10-12T10:07:18Z
prometheuses.monitoring.coreos.com 2019-10-12T10:07:24Z
prometheusrules.monitoring.coreos.com 2019-10-12T10:07:29Z
servicemonitors.monitoring.coreos.com 2019-10-12T10:07:35Z
syncvolumes.csms.storage 2020-03-10T04:46:34Z

operator工作原理

Operator 实际上作为kubernetes自定义扩展资源注册到controller-manager,通过list and watch的方式监听对应资源的变化,然后在周期内的各个环节做相应的协调处理。所谓的处理就是operator实现由状态的应用的核心部分,当然不同应用其处理的方式也不同

代码生成器介绍

operator中核心controller的代码都已经被封装好了,我们只需要写具体的逻辑即可。

即:你不用关心controller如何监听这个资源,不用关心去读取队列消息等等,只需要写当你获取到这个资源变化的事件信息,你应该做什么,或者应该响应什么。

那么接下来就是介绍operator-sdk了,他就很好的帮你实现了上述的功能,自动生成一套代码,你往里面插入数据就行了。

项目介绍

打算:目前我们集群中部分业务会出现内存或者显存溢出的问题,所以想针对这些异常pod做一些定时重启(滚动更新一下)的动作。

想法:deployment配置上特定的annotation,比如mtsre.meitu.com/eru: "true",自定义controller监听到这个key,我就为这个deployment创建一个cr资源,这个cr资源可以配置定时任务表达式,最终会按照这个定时任务表达式去定时的更新deployment。更新deployment这个操作可以通过修改spec.template pod的annotation来实现。

创建项目

项目名称,我定为优雅的滚动更新(Elegant rolling updates),简称ERU.

通过operator-sdk生成代码模板:

1
$ operator-sdk new eru-operator

operator-sdk的安装可以直接看官方文档:安装operator-sdk
我这里安装的版本是0.15.2.

创建api

1
$ operator-sdk add api --api-version=mtsre.meitu.com/v1 --kind=Eru

创建controller

1
$ operator-sdk add controller --api-version=mtsre.meitu.com/v1 --kind=Eru

看看默认的代码结构

png1

运行试试

要想运行项目,我们首先要在我们的集群中部署一下我们的role,rolebinding,crd等资源。
在deploy目录里有这几个文件,我们分别依次部署一下:

1
2
3
4
$ kubectl apply -f role.yaml 
$ kubectl apply -f role_binding.yaml
$ kubectl apply -f service_account.yaml
$ kubectl apply -f crds/mtsre.meitu.com_erus_crd.yaml

部署好之后,我们在项目的跟目录下直接运行:

1
$ operator-sdk run --local  --namespace your-namespace-name

这时你就可以看到输出,默认的代码是监听这个namespace下pod的变化。