9.1. 有状态服务 Operator:PostgreSQL、Kafka 与 Redis
StatefulSet 只保证「有稳定名字和 PVC 的 Pod」,但数据库真正难的是主从切换、备份恢复、版本升级、扩缩容和故障自愈。Operator 把这些运维知识写成控制器,让「一个 CR 创建一个高可用集群」成为可能。
- 层级:
L3 · 平台
- 难度:
进阶
- 预计:
50 分钟
- 前置:
StatefulSet、PVC、CRD/Operator 基础
9.1.1. Operator 在做什么
Operator = CRD + 控制器 + 领域知识。你提交一个 Cluster 或 Kafka 对象,控制器负责:
创建 StatefulSet、Service、PVC、ConfigMap、Secret;
初始化集群、配置复制与仲裁;
处理主从切换、成员变更、滚动升级;
执行备份、恢复、快照与版本迁移;
暴露状态与事件,供监控和告警使用。
Operator |
管理对象 |
典型能力 |
|---|---|---|
CloudNativePG |
PostgreSQL |
主备、PITR、备份到 S3、故障切换 |
Strimzi |
Kafka |
KRaft/ZooKeeper、Topic、User、镜像 |
Vitess |
MySQL 分片 |
分库分表、在线扩缩容 |
Redis Operator |
Redis |
哨兵/集群、主从切换 |
Elastic/OpenSearch Operator |
搜索集群 |
节点角色、快照、升级 |
9.1.2. CloudNativePG 最小实验
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm install cnpg cnpg/cloudnative-pg -n cnpg-system --create-namespace
kubectl -n cnpg-system get pods
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: demo-pg
namespace: default
spec:
instances: 3
storage:
size: 5Gi
bootstrap:
initdb:
database: app
owner: app
backup:
barmanObjectStore:
destinationPath: s3://demo-pg-backup/
s3Credentials:
accessKeyId:
name: backup-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: backup-creds
key: SECRET_ACCESS_KEY
kubectl apply -f pg-cluster.yaml
kubectl get cluster demo-pg -w
kubectl get pods -l cnpg.io/cluster=demo-pg
kubectl get secrets demo-pg-app -o jsonpath='{.data.password}' | base64 -d
CloudNativePG 会创建一个主实例和两个备实例,并生成 demo-pg-rw(读写)、demo-pg-ro(只读)Service。应用应连接 -rw,不要把主实例地址写死。
9.1.3. 故障切换与备份
kubectl cnpg status demo-pg
kubectl cnpg promote demo-pg demo-pg-2
kubectl cnpg backup demo-pg
故障切换:主实例不可用时,Operator 依据仲裁提升一个备实例;应用通过
-rwService 自动跟随。PITR:基于基础备份 + WAL 归档恢复到某个时间点;必须提前配置对象存储和保留策略。
升级:先升级 Operator,再修改
imageName;Operator 按顺序重启实例,保持仲裁。
不要只验证「Pod 变成 Running」。真正的验收是:杀掉主实例后应用能自动重连,备份能恢复到一个新集群。
9.1.4. Strimzi/Kafka 的差异
Kafka 的难点在 KRaft/ZooKeeper 仲裁、分区副本、Topic 配置与磁盘。Strimzi 用 Kafka、KafkaTopic、KafkaUser 等 CR 管理,升级时要关注 inter.broker.protocol.version 与滚动顺序。
kubectl apply -f https://strimzi.io/install/latest?namespace=kafka
kubectl -n kafka get pods
生产环境至少 3 个 broker,副本因子 3,min.insync.replicas=2;磁盘用本地 NVMe 或高性能云盘,不要用 NFS。
9.1.5. 验证清单
Operator 与 CRD 已安装,控制器 Pod 健康。
集群 CR 进入
Ready,实例数与期望一致。读写/只读 Service 可连接,应用使用
-rw而非 Pod IP。手动删除主实例后,故障切换在可接受时间内完成。
备份成功,并能恢复到新集群或指定时间点。
升级路径已演练,回滚方案明确。
9.1.6. 排错表
现象 |
原因 |
处理 |
|---|---|---|
CR 一直 |
存储类不满足 / 镜像拉取失败 |
|
主实例反复重启 |
资源不足 / PVC 满 |
查 events、扩容 PVC、调 resources |
应用连不上 |
Service 未就绪 / 网络策略 |
|
备份失败 |
S3 凭证/桶权限/网络 |
查 |
升级卡住 |
副本不健康 / 版本不兼容 |
先修复副本,再继续滚动 |
9.1.7. 进阶挑战
用 CloudNativePG 创建一个 3 实例集群,杀掉主实例并观察应用重连。
配置 S3 备份与 PITR,恢复到一个 5 分钟前的时间点。
用 Strimzi 创建 3 broker Kafka,生产/消费一个 Topic。
给 Operator 管理的集群加 NetworkPolicy,只允许应用命名空间访问。
9.1.8. 小结
Operator 把数据库运维知识编码进控制器,但不会替你做容量规划与演练。
有状态服务的验收标准是故障切换、备份恢复、升级回滚,而不是 Pod Running。
优先使用成熟 Operator;自研 Operator 只覆盖组织特有的运维逻辑。
数据服务要独立节点池/存储类,避免和在线业务抢资源。