7.5. 灾备与高可用设计让你的 Skills 服务永不掉线
你需要什么
- 一个可用的 Kubernetes 集群(1.27+),至少 3 个跨可用区节点
kubectl、helm与对应集群的认证配置- 云厂商 CLI 工具(如 Azure CLI、AWS CLI)用于管理有状态资源
- 你的 Skills 服务已容器化并推送至镜像仓库
- 预计时间:约 2 小时(含演练)
最终成果
你将得到一套具备生产级韧性的 Skills 服务平台:
- 无状态 Skills 自动水平扩展,单副本故障对用户无感知
- 有状态 Skills 在跨可用区故障时能完成分钟级恢复,且数据不丢
- 定义了明确的 SLI/SLO,并通过演练验证了恢复流程
这么做的目的是让商业化 Skills 平台不止“可用”,更能扛住真实世界的中断,守住客户信任与服务水平协议。
步骤一:无状态 Skills 的多副本部署——“流量分担 + 自动诊疗”
只要是纯粹的函数调用、无本地持久化的 Skills,都应设计为无状态组件。
借助 Kubernetes 原生的 Deployment + Service + Ingress,我们可以在 30 分钟内建立多副本、负载均衡与自动健康检查。
1.1 编写零配置 Deployment
创建一个 YAML 清单 skill-worker.yaml,关键配置如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: skill-worker
labels:
app: skill-worker
spec:
replicas: 3 # 至少 3 副本,分布到不同 AZ
selector:
matchLabels:
app: skill-worker
template:
metadata:
labels:
app: skill-worker
spec:
affinity:
podAntiAffinity: # 避免所有副本落在同一节点
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: skill-worker
topologyKey: kubernetes.io/hostname
containers:
- name: skill
image: your-registry/skill-executor:v1.2.0
env:
- name: STATEFUL_BACKEND_URL # 有状态技能依赖的外部存储地址
value: "https://your-cosmosdb-endpoint"
ports:
- containerPort: 8080
livenessProbe: # 进程存活检查,连续失败重启
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe: # 服务就绪检查,未就绪不加入 Service 端点
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
预期结果:部署后可见 3 个 Pod 运行,且
READY列全部为 1/1。若某 Pod 探活失败,会自动重启,且在就绪探针失败期间会被暂时移出负载均衡。
kubectl apply -f skill-worker.yaml
kubectl get pods -l app=skill-worker -o wide
1.2 暴露服务并使用负载均衡
apiVersion: v1
kind: Service
metadata:
name: skill-worker-svc
spec:
type: ClusterIP
selector:
app: skill-worker
ports:
- protocol: TCP
port: 80
targetPort: 8080
sessionAffinity: None # 无状态服务禁止会话亲和
配合 Ingress(如 NGINX Ingress Controller)将外部流量引入:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: skills-ingress
spec:
rules:
- host: skills.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: skill-worker-svc
port:
number: 80
踩坑笔记:
- 一定不要让无状态 Skills 在容器内保存 Session 或本地文件。如果技能运行时生成临时文件,请使用空目录挂载(
emptyDir)并明确其生命周期。- 确认
livenessProbe的/healthz只检查进程是否阻塞,不要链接外部依赖(如数据库),否则数据库抖动会引发连锁重启。
1.3 验证水平扩展
模拟压测的同时动态调整副本数:
# 使用 Vegeta 或 hey 产生请求
echo "GET https://skills.example.com/v1/classify" | vegeta attack -duration=30s -rate=100 | tee results.bin | vegeta report
# 动态扩容至 6 副本
kubectl scale deployment skill-worker --replicas=6
观察请求延迟与错误率应无明显上升,甚至吞吐线性增长。
步骤二:有状态 Skills 的备份与恢复——“状态快照 + 跨 AZ 故障转移”
Skills 中的记忆、对话历史、长期缓存等属于有状态部分,需要依赖托管的数据服务(如 Cosmos DB、Redis、PostgreSQL)。根据调研素材强调的“共享责任模型”,数据平面的高可用必须由客户自行设计。这里以 Azure Cosmos DB 为例,演示跨区域冗余与备份恢复。
2.1 启用多区域写入与自动故障转移
# 为现有 Cosmos DB 账户启用多区域写入
az cosmosdb update \
--name skill-state-db \
--resource-group skills-prod-rg \
--enable-multiple-write-locations true
# 添加至少一个跨区域的写入区域(例如从 East US 扩展到 West Europe)
az cosmosdb failover-priority-change \
--name skill-state-db \
--resource-group skills-prod-rg \
--failover-policies "East US=0" "West Europe=1"
# 开启服务端自动故障转移
az cosmosdb update \
--name skill-state-db \
--resource-group skills-prod-rg \
--enable-automatic-failover true
预期结果:在门户中查看 Cosmos DB 的“全球复制”页面,已有两个区域都为读写状态。任何区域发生中断,客户端 SDK 的重试策略会自动切换到可用区域(需配置 SDK 多区域选项)。
2.2 配置定期备份与快照导出
Cosmos DB 默认提供连续备份,但我们仍建议每周全量快照,并存储到异地对象存储:
# 创建定期备份策略(Azure 提供的定期备份模式)
az cosmosdb update \
--name skill-state-db \
--resource-group skills-prod-rg \
--backup-policy-type Periodic \
--backup-interval 240 \ # 备份间隔(分钟)
--backup-retention 8 # 保留时长(小时)
# 手动触发一次快照导出至跨区域 Storage Account
az cosmosdb restore \
--source-database-account skill-state-db \
--target-database-account skill-state-db-backup \
--restore-timestamp "2026-06-02T12:00:00+00:00" \
--resource-group skills-dr-rg
另外,编写一个 CronJob 来自动化导出:
apiVersion: batch/v1
kind: CronJob
metadata:
name: cosmos-backup-job
spec:
schedule: "0 2 * * 0" # 每周日凌晨2点
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: mcr.microsoft.com/azure-cli:latest
command:
- /bin/bash
- -c
- |
az cosmosdb restore \
--source-database-account skill-state-db \
--target-database-account skill-state-db-backup-$(date +%s) \
--restore-timestamp $(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--resource-group skills-dr-rg
restartPolicy: OnFailure
踩坑经验:
- 不可仅依赖自动备份:多区域写入虽能应付整个区域挂掉,但逻辑错误、误删数据仍需按时间点快照恢复。
- 确认快照恢复后的数据库连接字符串与生产隔离,避免因 DNS 冲突写回生产。演练时将备份库向一个临时 Skills 实例注入验证。
2.3 验证跨 AZ 故障转移
模拟区域故障(谨慎在生产操作,建议在演练环境):停掉主区域节点的网络接口或手动对 Cosmos DB 执行计划内区域故障转移。
# 手动触发故障转移(将 West Europe 提升为主写入)
az cosmosdb failover-priority-change \
--name skill-state-db \
--resource-group skills-prod-rg \
--failover-policies "West Europe=0" "East US=1"
观察 Skills 服务日志,连接会自动切换,记录故障转移时间(RPO ~0,RTO <1 分钟)。测试 SQL 查询是否正常。
步骤三:灾难演练与 SLI/SLO 设定——“量化可靠性,定期练兵”
有高可用架构不等于真的可靠,必须通过数据和演练验证。本章基于站点可靠性工程实践,定义服务水平指标并实施障碍注入。
3.1 定义合适的 SLI 与 SLO
| SLI(服务水平指标) | 测量方式 | SLO 目标(示例) |
|---|---|---|
| 请求成功率 | 非 5xx 响应数 / 总请求数 | ≥ 99.95%(30 天窗口) |
| P99 延迟(无状态 Skills) | 请求处理时间分布 P99 | ≤ 800 ms |
| 故障恢复时间 (RTO) | 从故障注入到服务恢复可用性的时间 | ≤ 5 分钟 |
| 数据恢复点目标 (RPO) | 故障时刻到最后一次数据快照的时间差 | ≤ 1 小时 |
将 SLO 嵌入监控与告警(Prometheus AlertManager 规则)。示例规则:
groups:
- name: skills-slo
rules:
- alert: HighErrorRate
expr: (sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))) > 0.0005
for: 5m
labels:
severity: critical
annotations:
summary: "Skills 错误率超过 SLO 阈值 0.05%"
3.2 执行灾难演练
我们采用 Chaos Mesh 模拟两种故障:Pod 随机死亡 与 网络延迟 / 分区。
# 1. Pod 杀戮实验,验证多副本自动恢复
kubectl apply -f - <<EOF
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: skill-kill-random
spec:
action: pod-kill
mode: one
selector:
namespaces:
- skills-prod
labelSelectors:
app: skill-worker
scheduler:
cron: "@every 30m"
EOF
监控恢复速度:Grafana 面板应显示 Pod 数量短暂下降后快速回升至设定副本数,且请求成功率无明显降低。
# 2. 网络延迟注入,验证超时与重试
kubectl apply -f - <<EOF
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: skill-net-delay
spec:
action: delay
mode: all
selector:
namespaces:
- skills-prod
labelSelectors:
app: skill-worker
delay:
latency: "500ms"
jitter: "100ms"
duration: "2m"
EOF
观察 P99 延迟是否超出 SLO,若超出则检查客户端超时配置和熔断策略。
注意:演练前务必通知上下游团队,启用回滚机制(如 Chaos 实验的
duration有限,自动终止)。每次演练后形成报告,附上 SLI 偏离情况和改进项。
3.3 验证完整恢复流程实战
规划一个“全栈演练”:
- 停止主区域的 Cosmos DB 写入(模拟中断)。
- 自动故障转移生效。
- 将 Skills 的 Deployment 镜像升级至新版本(验证滚动更新期间可用性)。
- 从备份恢复部分数据,并与当前状态联合验证。
跟踪关键时间戳,计算实际 RTO 和 RPO,与 SLO 对比。一次成功演练花费约 2 小时(包含准备和观察)。
回顾
我们完成了一套面向 Skills 服务的灾备与高可用方案:
- 通过 Kubernetes 多副本 + 健康检查与负载均衡,让无状态 Skills 从容应对单点故障;
- 借助 Cosmos DB 多区域写入、定期快照与 CronJob 备份,实现了有状态数据的跨 AZ 故障转移与时间点恢复;
- 定义了核心 SLI(成功率、延迟、RTO)并设定了具体 SLO,通过 Chaos Mesh 注错进行了实验验证。
整个过程从基础部署到全链路演练,大约需要 2 小时操作时间(不含阅读与规划)。
行动清单
- 标记出你现有 Skills 中 需要持久化的状态,将其迁移至多区域托管的数据库。
- 为每个无状态 Skill 编写 Kubernetes Deployment,并加入 liveness/readiness 探针。
- 设定你的第一个 SLO(如“99.9% 可用性”),并配置相应告警。
- 在非生产环境执行一次自动故障转移演练,记录 RTO 和 RPO。
- 阅读下一章——“代码审查 Skill 系统让团队效率翻倍”,思考如何将高可用设计融入该 Skill 的实现,例如将审查规则与结果持久化,并验证其恢复能力。
agent skills 入门到精通
关于 LearnKu