本文是对 Kubernetes 的核心概念,声明式API和编程范式的理解笔记。整理回答了”什么是声明式API“、”Kubernetes 编程范式是什么“这样的问题,然后简单记录了对更快更好造出 CRD 及其 Controller的 Operator 的理解。
有了这些 API ,就可以向这些 API 发送请求来操作 Kubernetes 了。
首先借用磊哥的一句话:从“使用 Kubernetes 部署代码”,到“使用 Kubernetes 编写代码”的蜕变过程,正是你从一个 Kubernetes 用户,到 Kubernetes 玩家的晋级之路。
“使用 Kubernetes 编写代码”,就要遵循 Kubernetes 所提供的编程范式来进行开发。这个编程范式有2个过程:
(1)为 Kubernetes 添加自定义 API 对象。
(2)为自定义的 API 对象添加控制逻辑。
添加一个 Kubernetes 风格的 API 资源类型得益于一个全新的 API 插件机制:CRD。CRD 的全称是 Custom Resource Definition。它指的就是,允许用户在 Kubernetes 中添加一个跟 Pod、Node 类似的、新的 API 资源类型,即:自定义 API 资源。从而就可以达到通过标准的 kubectl create 和 get 操作,来管理自定义 API 对象的目的。
CRD(Custom Resource Definition)就是我们来提供一个 Definition,然后让 Kubernetes 认识其中定义的 CR(Custom Resource)。举个例子:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: networks.samplecrd.k8s.io
spec:
group: samplecrd.k8s.io
version: v1
names:
kind: Network
plural: networks
scope: Namespaced
解释:这个 CRD 中,主要看 spec 字段,指定了“group: samplecrd.k8s.io”“version: v1”这样的 API 信息,也指定了这个 CR 的资源类型叫作 Network,复数(plural)是 networks。scope 是 Namespaced,代表定义的这个 Network 是一个属于 Namespace 的对象,类似于 Pod。
这样,就定义了 networks.samplecrd.k8s.io 这个 CR(Custom Resource),也就是/apis/samplecrd.k8s.io/v1/networks 这样一个自定义API对象了。
apiVersion: samplecrd.k8s.io/v1
kind: Network
metadata:
name: example-network
spec:
cidr: "192.168.0.0/16"
gateway: "192.168.0.1"
解释: API 资源类型是 Network;API 组是samplecrd.k8s.io;API 版本是 v1。另外,可以看到这里还有“cidr”(网段),“gateway”(网关)这些关于对象描述的字段需要做些代码工作来让 Kubernetes“认识”了。
这样这个自定义的 API 对象有了,还需要为这个 API 对象添加“控制逻辑”,Kubernetes 才能根据 Network API 对象的“增、删、改”操作,在真实环境中做出相应的响应。也就是下一节内容。
Kubernetes 所定义的 API 对象都是“声明式 API”,CRD 定义的 CR自然也不例外。“声明式 API”并不像“命令式 API”那样有着明显的执行逻辑,声明式 API 在于维护一个所声明的状态。这就使得基于声明式 API 的业务功能实现,往往需要通过控制器模式来“监视”API 对象的变化,然后以此来决定实际要执行的具体工作。
所以,我们需要开发一个“自定义控制器”来为 CRD 执行控制逻辑。
解释一下自定义控制器的工作原理,这张经典的图就可以了:
控制器其实可以分为2部分来看:左边的 Informer,右面的”控制循环“,中间通过一个工作队列来进行协同。
Informer 主要用来与APIServer 进行数据同步。就是一个自带缓存和索引机制,可以触发 Handler 的客户端库。这个本地缓存在 Kubernetes 中一般被称为 Store,索引一般被称为 Index。Informer 使用了 Reflector 包,它是一个可以通过 ListAndWatch 机制获取并监视 API 对象变化的客户端封装。Reflector 和 Informer 之间,用到了一个“增量先进先出队列”进行协同。
”控制循环“部分是一个“无限循环”的任务,每一个循环周期执行的正是我们真正关心的业务逻辑,通过对比“期望状态”和“实际状态”的差异,不断完成调协(Reconcile)。
另外,这套流程不仅可以用在自定义 API 资源上,也完全可以用在 Kubernetes 原生的默认 API 对象上。在自定义控制器里面,可以通过对自定义 API 对象和默认 API 对象进行协同,从而实现更加复杂的编排功能。
Kubernetes 编程范式就是:CRD + 自定义控制器。
(CRD 用来创建自定义的 API 对象,自定义控制器来添加相应 API 的请求控制逻辑)
Operator 是 Kubernetes 编程范式的聪明利用,为“有状态应用”设计 CRD 及其 Controller。在 Kubernetes 生态中,Operator 是一个相对更加灵活和编程友好的管理“有状态应用”的解决方案。
- 原理:
Operator 的工作原理实际上是利用了 Kubernetes 的自定义 API 资源(CRD),来描述我们想要部署的“有状态应用”;然后在自定义控制器里,根据自定义 API 对象的变化,来完成具体的部署和运维工作。
- 开发:
kubebuilder与operator-sdk :是目前开发operator两种常用的SDK,或者叫 framework,不管是哪种方式只是规范了步骤和一些必要的元素,生成相应的模板。都是为了更快更好造出 CRD 及其 Controller ,实现 Operator 来更好管理 Kubernetes 有状态应用。
参考:
《深入剖析Kubernetes | 极客时间》张磊,容器编排和Kubernetes作业管理 23 24 25 27