在 operator-framework 官网有一个页面详细阐述了自定义控制器的成熟度等级划分,可以看到大致分为5个等级:
- 实现业务的基本部署
- 实现业务的无缝升级
- 实现业务的整个生命周期管理:app 的生命周期、存储的生命周期(备份、故障恢复等)
- 深刻洞察: 监控项,告警,log 处理以及负载分析
- 自动驾驶:自动 水平,垂直伸缩,自动化配置调优,异常检测,调度调优
可以看到 helm 只能做到前两点,而 ansible 可以覆盖全部维度,而 go (operator-sdk) 可以更快的实现这些维度。
参考: sdk.operatorframework.io/docs/overvi…
1. 什么叫 operator sdk
该 sdk 是 operator 框架中的一个组件,是一个开源工具包,用于以一种高效的,自动化的,可伸缩的方式,管理 k8s 云原生应用。 这个东西叫做 Operators。
该sdk 提供了 构建,测试,打包 operators 的工具。 最初,该 SDK 可以极为便利的以 k8s api 的方式实现应用业务逻辑(伸缩,升级,备份)。随着发展,该 sdk 可以让 operator 更聪明并且拥有云服务的用户体验。最佳实践和代码模式都内涵于 Operators 之中,可以避免重复造轮子。
在开发 Operator 之前,可以在 operatorhub.io/ 搜索下是否已经有现成的方案了,打包完 Operator 之后,可以上传到 应用商店中,比如 kubeapps(4.6k star)。
该sdk 框架,基于 controller-runtime 可以让 编写 operators 更简单:
- 高级的 APIs 以及抽象 可以让编写逻辑更符合直觉
- 脚手架以及代码生成工具可以更快的生成一个项目
- 扩展插件能够覆盖常见的 Operator 用例
该 sdk 支持 helm, ansible, go 三种开发方式(workflow),当然最佳的开发方式就是 go operator。
2. go operator 的开发方式
- 基于 SDK CLI 创建一个 operator 项目
- 以 crd 的方式添加新资源的 APIs
- 定义 控制器 来 watch 和 reconcile 资源
- 借助于 SDK 以及 controller-runtime api 为新资源的 控制器编写 reconcile 逻辑
- 基于 sdk cli 来构建以及生成 operator 部署声明文件
3. 安装 Operator SDK CLI
brew install operator-sdk
export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac)
export OS=$(uname | awk '{print tolower($0)}')
export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.28.1
curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}
chmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk
4. 构建一个 demo operator 项目
参考: sdk.operatorframework.io/docs/buildi…
4.1 关于 Operator 的部署有多种方式:
4.1.1 开发环境本地部署
make install run
# 然后执行 kubectl apply
## 执行 ctrl + c 即可停止该 operator
4.1.2 基于 OLM (operator lifecycle management)
# 在 k8s集群安装该项目
operator-sdk olm install
# 安装后可以看到以下负载
olm catalog-operator-588cbf94df-nwsmj 1/1 Running 0 9m25s 10.16.0.3 rocky <none> <none>
olm olm-operator-6998c47f-ns49l 1/1 Running 0 9m25s 10.16.0.6 rocky <none> <none>
olm operatorhubio-catalog-7gd7v 1/1 Running 0 8m13s 10.16.0.7 rocky <none> <none>
olm packageserver-cf856b874-n8ljm 1/1 Running 0 8m11s 10.16.0.8 rocky <none> <none>
olm packageserver-cf856b874-wnrmw 1/1 Running 0 8m11s 10.16.0.17 rocky <none> <none>
## operator hub 用于维护以及展示 operator
## package server 用于保存 operator package
## catalog 是一个仓库(repo),保存应用定义以及 CRD。
### catalog 是 package的集合,实现将 “channel” 映射到 特定的应用定义,基于 Channel 可以实现 package 的作者为不同的用户(使用不同版本)实现不同的升级路径。
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: etcd
namespace: olm
spec:
channel: singlenamespace-alpha
name: etcd
source: operatorhubio-catalog
sourceNamespace: olm
# 用户可以订阅一个 channel,当新版本释放的时候,用户的应用就会触发升级
基于 olm 构建 operator 打包镜像,上传
make bundle IMG="example.com/memcached-operator:v0.0.1"
make bundle-build bundle-push BUNDLE_IMG="example.com/memcached-operator-bundle:v0.0.1"
# 运行 operator
operator-sdk run bundle <some-registry>/memcached-operator-bundle:v0.0.1
## 基于 kubectl apply 运行一个该 operator 维护的 crd
# 清理该 operator
operator-sdk cleanup memcached-operator
后续 构建完自己的 operator,可以结合 olm 再深入熟悉下 operator 的最佳维护方式。
5. Go Operator 教程
5.1. 关于选择 operator 的作用域
默认 init operator 就是集群范围的,你可以选择设置你的 operator 是在一(多)个 ns 内部还是整个集群:sdk.operatorframework.io/docs/buildi…
sdk.operatorframework.io/docs/buildi…
其他
- API 定义
- RBAC
- controller 控制
- reconcile loop 的编写
- 镜像构建
- operator 维护方式选择
6. webhook 准入
webhook 是一种 HTTP 回调,它会接受准入请求并处理该请求。 它通过 k8s 注册,通过 k8s 发起调用,从而在存储一个资源前确认其是否合法。有两种类型的 webhook
- Validating 类型: 只能基于请求选择允许或者拒绝
- Mutating 类型: 可以在请求的基础上,后续基于一个 patch 修改资源,使得资源的属性都是合法的。
Mutating 类型是最常用的 webhook 类型,可以尽可能的保证用户的请求最后是成功的。
创建一个 Validating 类型的 webhook
$ operator-sdk create webhook --group cache --version v1alpha1 --kind Memcached --defaulting --programmatic-validation
7. 测试
8. 高级特性
- 管理 CR status conditions:移除,去重,排序,自动管理最后更新时间,提供 help 方法用于确定conditions 的状态
- 将第三方资源添加到你的 Operator
- 监控以及可观察性
- 管理外部资源依赖:基于 Finalizer
- leader 选举
- 多架构