2. Operator SDK 入门:安装、配置与核心架构
Operator SDK 是构建 Kubernetes Operator 的官方脚手架工具,它封装了 controller-runtime、client-go 等底层库,提供项目初始化、代码生成、测试与打包等全生命周期能力。本章将带你完成 SDK 的安装与配置,初始化第一个 Operator 项目,并深入理解其核心——Reconcile 循环。
2.1 Operator SDK 的安装与配置
Operator SDK 支持 macOS、Linux 和 Windows(WSL2)环境。推荐使用 Homebrew(macOS)或直接下载二进制(Linux)进行安装。
2.1.1 安装方式对比
| 平台 | 安装命令 / 方式 | 版本验证 |
|---|---|---|
| macOS (Homebrew) | brew install operator-sdk |
operator-sdk version |
| Linux (二进制) | |
operator-sdk version |
| Windows (WSL2) | 在 WSL2 Ubuntu 中执行 Linux 二进制安装步骤 | operator-sdk version |
版本建议: 本课程基于 Operator SDK v1.36.x 版本。安装前请确保 Go 版本 ≥ 1.21,并已配置好
$GOPATH 和 $PATH。
2.1.2 环境依赖检查
- Go 语言环境:
go version确认版本 ≥ 1.21。 - Kubernetes 集群: 可使用 kind、minikube 或远程集群,
kubectl cluster-info确认连接正常。 - Docker / Podman: 用于构建 Operator 镜像,
docker version确认运行中。
2.2 项目初始化
使用 operator-sdk init 命令创建 Operator 项目骨架。以下以创建一个名为 memcached-operator 的项目为例,管理 Memcached 集群。
2.2.1 初始化命令
mkdir -p $HOME/projects/memcached-operator
cd $HOME/projects/memcached-operator
operator-sdk init --domain=example.com --repo=github.com/example/memcached-operator
--domain:自定义资源的 API 组后缀,例如cache.example.com。--repo:Go module 路径,用于依赖管理。
2.2.2 初始化后的项目结构
| 文件/目录 | 作用 |
|---|---|
main.go |
Operator 入口,启动 Manager 并注册控制器 |
controllers/ |
存放 Reconcile 逻辑的控制器代码 |
api/ |
自定义资源(CRD)的 Go 类型定义 |
config/ |
Kubernetes 清单文件(RBAC、CRD、Deployment 等) |
Dockerfile |
构建 Operator 容器镜像 |
Makefile |
常用任务(构建、测试、部署)的快捷命令 |
go.mod / go.sum |
Go 模块依赖 |
关键点: 初始化后不要急于修改代码,先理解骨架结构。后续添加 API 和控制器时,SDK 会自动生成大量样板代码。
2.3 理解 Operator 的基本架构:Reconcile 循环
Operator 的核心是一个事件驱动的控制循环,称为 Reconcile 循环。它持续监听集群中自定义资源(CR)实例的变化,并将实际状态调整为期望状态。
2.3.1 Reconcile 循环的工作流程
- 事件触发: CR 被创建、更新或删除时,Informer 将事件入队。
- Reconcile 请求: controller-runtime 从队列中取出请求,调用用户实现的
Reconcile方法。 - 读取当前状态: 通过 Kubernetes API 读取 CR 实例及关联资源(如 Pod、Service)。
- 对比期望状态: 根据 CR 的 Spec 字段计算期望状态。
- 执行调和操作: 创建、更新或删除资源,使实际状态趋近期望状态。
- 更新状态: 将调和结果写入 CR 的 Status 字段。
- 返回结果: 返回
ctrl.Result{}(成功)或error(重试)。
2.3.2 Reconcile 方法签名
每个控制器必须实现 Reconcile 方法,其标准签名如下:
import (
"context"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// 1. 获取 CR 实例
var memcached cachev1.Memcached
if err := r.Get(ctx, req.NamespacedName, &memcached); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// 2. 调和逻辑:确保 Deployment 副本数等于 CR 的 Spec.Size
// ...
// 3. 更新 CR 状态
memcached.Status.ReadyReplicas = currentReplicas
if err := r.Status().Update(ctx, &memcached); err != nil {
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
常见误区: Reconcile 方法必须是幂等的——多次调用应产生相同结果。不要在 Reconcile 中依赖外部状态或执行非幂等操作(如自增 ID)。
2.3.3 控制器与 Manager 的关系
Manager 是 Operator 的“大脑”,负责管理多个控制器、Webhook 和缓存。每个控制器注册到 Manager 后,由 Manager 统一启动和协调。
2.4 本章小结
- Operator SDK 通过
init命令快速生成项目骨架,包含main.go、controllers/、api/等核心目录。 - Reconcile 循环是 Operator 的“心脏”,遵循“事件 → 读取 → 对比 → 调和 → 更新”的闭环。
- Manager 统一管理多个控制器和共享组件,确保资源访问的一致性和效率。
- Reconcile 方法必须幂等,避免副作用;返回
ctrl.Result{Requeue: true}可实现定时重试。
下一步实践: 在本地使用
operator-sdk init 创建一个空项目,浏览生成的文件结构,并尝试在 main.go 中找到 Manager 的初始化代码。这是理解 Operator 启动流程的最佳起点。