灾备与应急预案(Runbook)
概述
本文档描述了井云服务中心后端系统的灾难恢复策略、应急预案和故障处理流程,确保系统在各种故障情况下能够快速恢复服务。
灾备架构
灾备层级设计
主数据中心(北京):
- 负载均衡器
- 应用集群
- 主数据库
- Redis 集群
- RabbitMQ 集群
灾备数据中心(上海):
- 负载均衡器
- 应用集群
- 备份数据库
- Redis 集群
- RabbitMQ 集群
备份存储:
- 对象存储 (S3)
- 磁带库
数据同 步关系:
- 主数据中心 → 灾备数据中心:数据同步
- 主数据库 → 备份数据库:主从复制
- Redis 集群 → Redis 集群:数据同步
- RabbitMQ 集群 → RabbitMQ 集群:镜像队列
- 主数据库/备份数据库 → 对象存储 → 磁带库:备份存储
灾备策略
1. 数据备份策略
- 实时备份:数据库主从复制,RPO < 1 分钟
- 增量备份:每小时增量备份,保留 7 天
- 全量备份:每日全量备份,保留 30 天
- 异地备份:异地对象存储备份,保留 1 年
- 离线备份:磁带库备份,保留 7 年
2. 应用灾备策略
- 应用部署:两地三中心部署,自动故障切换
- 负载均衡:全局负载均衡,智能流量调度
- 服务发现:跨数据中心服务注册与发现
- 配置同步:配置中心跨数据中心同步
3. 网络灾备策略
- 多线路接入:多运营商网络接入
- DNS 切换:智能 DNS 故障切换
- CDN 加速:全球 CDN 节点分发
- 专线连接:数据中心间专线连接
应急预案
1. 服务不可用应急预案
故障现象
- 用户无法访问系统
- API 请求超时
- 服务健康检查失败
- 监控告警:服务不可用
故障等级
- P0 - 全站不可用:所有服务均不可用
- P1 - 核心服务不可用:认证、支付等核心服务不可用
- P2 - 部分服务不可用:非核心服务不可用
- P3 - 服务性能下降:服务响应缓慢
应急处理流程
P0 级故障处理
# 1. 立即响应(5分钟内)
# 检查服务状态
kubectl get pods -n jingyun
kubectl get services -n jingyun
# 检查负载均衡器
kubectl get ingress -n jingyun
curl -I https://api.jingyun.design/health
# 2. 快速诊断(10分钟内)
# 检查系统资源
top
free -h
df -h
# 检查网络连接
ping 8.8.8.8
nslookup api.jingyun.design
# 检查数据库连接
pg_isready -h localhost -p 5432
redis-cli ping
# 3. 应急恢复(30分钟内)
# 重启服务
kubectl rollout restart deployment/user-service -n jingyun
kubectl rollout restart deployment/auth-service -n jingyun
# 扩容服务
kubectl scale deployment/user-service --replicas=10 -n jingyun
# 切换到灾备环境
# 更新 DNS 指向灾备数据中心
# 更新负载均衡器配置
P1 级故障处理
# 1. 服务检查(5分钟内)
# 检查具体服务状态
kubectl logs -f deployment/auth-service -n jingyun --tail=100
# 检查服务依赖
curl http://auth-service:9000/health
curl http://user-service:9000/health
# 2. 问题定位(15分钟内)
# 检查配置
kubectl get configmap -n jingyun
kubectl get secret -n jingyun
# 检查数据库
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "SELECT 1;"
# 3. 服务恢复(1小时内)
# 单独重启故障服务
kubectl rollout restart deployment/auth-service -n jingyun
# 恢复数据库连接
kubectl rollout restart deployment/postgres -n jingyun
# 恢复缓存连接
kubectl rollout restart deployment/redis -n jingyun
P2 级故障处理
# 1. 确认影响范围(15分钟内)
# 检查受影响的服务
kubectl get pods -n jingyun -l app=agent-service
# 检查错误日志
kubectl logs deployment/agent-service -n jingyun --tail=200 | grep ERROR
# 2. 问题分析(30分钟内)
# 检查服务指标
curl http://agent-service:9000/metrics
# 检查资源使用
kubectl top pods -n jingyun
# 3. 服务恢复(2小时内)
# 重启受影响服务
kubectl rollout restart deployment/agent-service -n jingyun
# 调整资源配额
kubectl patch deployment agent-service -n jingyun -p '{"spec":{"template":{"spec":{"containers":[{"name":"agent-service","resources":{"limits":{"memory":"1Gi","cpu":"500m"}}}]}}}}'
验证测试
# 1. 健康检查验证
curl https://api.jingyun.design/health
curl https://api.jingyun.design/auth/health
curl https://api.jingyun.design/user/health
# 2. 功能测试验证
# 用户登录测试
curl -X POST https://api.jingyun.design/auth/wechat/login \
-H "Content-Type: application/json" \
-d '{"code":"test_code"}'
# 数据查询测试
curl -X GET https://api.jingyun.design/user/profile \
-H "Authorization: Bearer test_token"
# 3. 性能测试验证
# 压力测试
ab -n 1000 -c 10 https://api.jingyun.design/health
# 延迟测试
curl -w "@curl-format.txt" -o /dev/null -s https://api.jingyun.design/health
2. 数据库异常应急预案
故障现象
- 数据库连接失败
- 查询超时
- 数据不一致
- 主从同步异常
应急处理流程
连接故障处理
# 1. 检查数据库状态
kubectl exec -it postgres-0 -n jingyun -- pg_isready
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "SELECT version();"
# 2. 检查连接池
kubectl logs deployment/user-service -n jingyun | grep "database connection"
# 3. 检查网络连接
kubectl exec -it postgres-0 -n jingyun -- netstat -tlnp | grep 5432
# 4. 应急恢复
# 重启数据库
kubectl rollout restart deployment/postgres -n jingyun
# 扩容数据库
kubectl scale deployment/postgres --replicas=2 -n jingyun
# 切换到从库
kubectl patch configmap app-config -n jingyun -p '{"data":{"database_host":"postgres-read"}}'
数据不一致处理
# 1. 数据一致性检查
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "
SELECT
schemaname,
tablename,
attname,
n_distinct,
correlation
FROM pg_stats
WHERE schemaname = 'public';
"
# 2. 主从同步检查
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "
SELECT * FROM pg_stat_replication;
"
# 3. 数据修复
# 停止应用写入
kubectl scale deployment/user-service --replicas=0 -n jingyun
# 手动数据同步
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "
-- 修复不一致的数据
UPDATE users SET nickname = COALESCE(nickname, '') WHERE nickname IS NULL;
"
# 重启应用服务
kubectl scale deployment/user-service --replicas=3 -n jingyun
性能问题处理
# 1. 性能诊断
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "
SELECT
query,
calls,
total_time,
mean_time,
rows
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
"
# 2. 索引优化
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "
-- 重建索引
REINDEX INDEX CONCURRENTLY idx_users_phone;
"
# 3. 配置调优
kubectl exec -it postgres-0 -n jingyun -- psql -U akita -d jingyun -c "
-- 调整配置参数
ALTER SYSTEM SET shared_buffers = '256MB';
ALTER SYSTEM SET work_mem = '4MB';
SELECT pg_reload_conf();
"
3. 缓存服务异常应急预案
故障现象
- Redis 连接失败
- 缓存穿透
- 缓存雪崩
- 内存使用过高
应急处理流程
连接故障处理
# 1. 检查 Redis 状态
kubectl exec -it redis-0 -n jingyun -- redis-cli ping
kubectl exec -it redis-0 -n jingyun -- redis-cli info server
# 2. 检查连接池
kubectl logs deployment/user-service -n jingyun | grep "redis connection"
# 3. 应急恢复
# 重启 Redis
kubectl rollout restart deployment/redis -n jingyun
# 扩容 Redis 集群
kubectl scale deployment/redis --replicas=6 -n jingyun
# 启用降级模式
kubectl patch configmap app-config -n jingyun -p '{"data":{"cache_enabled":"false"}}'
缓存雪崩处理
# 1. 检查缓存状态
kubectl exec -it redis-0 -n jingyun -- redis-cli info memory
kubectl exec -it redis-0 -n jingyun -- redis-cli info stats
# 2. 缓存预热
kubectl exec -it redis-0 -n jingyun -- redis-cli eval "
for i=1,1000 do
redis.call('SET', 'key:' .. i, 'value:' .. i)
redis.call('EXPIRE', 'key:' .. i, 3600)
end
return 'OK'
" 0
# 3. 配置优化
kubectl exec -it redis-0 -n jingyun -- redis-cli config set maxmemory-policy allkeys-lru
kubectl exec -it redis-0 -n jingyun -- redis-cli config set timeout 300
4. 消息队列异常应急预案
故障现象
- RabbitMQ 连接失败
- 消息堆积
- 队列阻塞
- 消息丢失
应急处理流程
连接故障处理
# 1. 检查 RabbitMQ 状态
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl status
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl list_queues
# 2. 检查连接状态
kubectl logs deployment/user-service -n jingyun | grep "rabbitmq"
# 3. 应急恢复
# 重启 RabbitMQ
kubectl rollout restart deployment/rabbitmq -n jingyun
# 重建队列
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl delete_queue user_events
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl declare_queue user_events durable true
消息堆积处理
# 1. 检查队列状态
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl list_queues name messages
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl list_consumers
# 2. 扩容消费者
kubectl scale deployment/user-service --replicas=10 -n jingyun
# 3. 清理过期消息
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl purge_queue user_events
# 4. 调整队列配置
kubectl exec -it rabbitmq-0 -n jingyun -- rabbitmqctl set_policy TTL ".*" '{"message-ttl":60000}' --apply-to queues
5. 网络异常应急预案
故障现象
- 网络连接超时
- DNS 解析失败
- 负载均衡异常
- 带宽拥塞
应急处理流程
DNS 解析故障
# 1. 检查 DNS 解析
nslookup api.jingyun.design
dig api.jingyun.design
# 2. 检查本地 DNS
kubectl exec -it dnsutils -n jingyun -- nslookup api.jingyun.design
# 3. 应急恢复
# 切换到备用 DNS
kubectl patch configmap coredns -n kube-system -p '{"data":{"Corefile":".:53 {\n errors\n health {\n lameduck 5s\n }\n ready\n kubernetes cluster.local in-addr.arpa ip6.arpa {\n pods insecure\n fallthrough in-addr.arpa ip6.arpa\n }\n prometheus :9153\n forward . 8.8.8.8 1.1.1.1 {\n max_concurrent 1000\n }\n cache 30\n loop\n reload\n loadbalance\n}\n"}}'
# 清理 DNS 缓存
kubectl rollout restart deployment/coredns -n kube-system
负载均衡异常
# 1. 检查负载均衡器状态
kubectl get ingress -n jingyun
kubectl describe ingress jingyun-ingress -n jingyun
# 2. 检查后端服务
kubectl get endpoints -n jingyun
kubectl describe endpoints user-service -n jingyun
# 3. 应急恢复
# 重建 ingress
kubectl delete ingress jingyun-ingress -n jingyun
kubectl apply -f ingress/jingyun-ingress.yaml
# 切换到备用负载均衡器
kubectl patch ingress jingyun-ingress -n jingyun -p '{"spec":{"ingressClassName":"nginx-backup"}}'
灾难恢复
1. 数据中心级灾难恢复
灾难场景
- 主数据中心完全不可用
- 自然灾害导致设施损坏
- 大规模电力故障
- 网络完全中断
恢复流程
阶段一:灾难确认(30分钟内)
# 1. 确认灾难范围
# 检查主数据中心状态
ping 10.0.1.1
ssh admin@primary-dc "uptime"
# 检查网络连接
traceroute 8.8.8.8
mtr 8.8.8.8
# 2. 启动应急响应
# 通知应急团队
# 启动灾难恢复预案
# 建立应急指挥中心
阶段二:灾备切换(2小时内)
# 1. DNS 切换
# 更新 DNS 记录指向灾备数据中心
nsupdate -k /etc/ddns.key <<EOF
server ns1.jingyun.design
zone jingyun.design
update delete api.jingyun.design A
update add api.jingyun.design 60 A 10.0.2.10
send
EOF
# 2. 负载均衡切换
# 更新全局负载均衡器配置
# 将流量切换到灾备数据中心
# 3. 数据库切换
# 提升灾备数据库为主库
kubectl exec -it postgres-backup-0 -n jingyun -- pg_ctl promote
# 更新应用配置
kubectl patch configmap app-config -n jingyun -p '{"data":{"database_host":"postgres-backup"}}'
# 4. 应用启动
# 启动灾备环境应用
kubectl scale deployment/user-service --replicas=5 -n jingyun-backup
kubectl scale deployment/auth-service --replicas=5 -n jingyun-backup
阶段三:服务验证(1小时内)
# 1. 健康检查
curl https://api.jingyun.design/health
# 2. 功能测试
# 用户登录测试
# 数据查询测试
# 支付流程测试
# 3. 性能测试
# 压力测试
# 延迟测试
# 吞吐量测试
阶段四:服务恢复(持续)
# 1. 监控服务状态
# 检查所有服务指标
# 监控错误率和延迟
# 验证数据一致性
# 2. 用户通知
# 发送服务恢复通知
# 更新服务状态页面
# 客户服务准备
# 3. 性能优化
# 根据负载调整资源
# 优化数据库配置
# 调整缓存策略
2. 数据恢复
数据备份验证
# 1. 验证备份完整性
# 检查全量备份
pg_verifybackup /backup/20251227/full
# 检查增量备份
pg_verifybackup /backup/20251227/inc
# 2. 验证备份时间点
# 查看备份时间戳
ls -la /backup/20251227/
# 查看备份日志
cat /backup/20251227/backup.log
数据恢复操作
# 1. 停止应用服务
kubectl scale deployment/user-service --replicas=0 -n jingyun
kubectl scale deployment/auth-service --replicas=0 -n jingyun
# 2. 恢复数据库
# 恢复全量备份
pg_ctl stop -D /var/lib/postgresql/data
rm -rf /var/lib/postgresql/data/*
pg_basebackup -h backup-server -D /var/lib/postgresql/data -U replication -v -P -W
# 恢复到指定时间点
pg_ctl start -D /var/lib/postgresql/data
psql -U akita -d jingyun -c "SELECT pg_wal_replay_resume();"
# 3. 验证数据一致性
# 检查表结构
psql -U akita -d jingyun -c "\dt"
# 检查数据行数
psql -U akita -d jingyun -c "SELECT COUNT(*) FROM users;"
# 4. 重启应用服务
kubectl scale deployment/user-service --replicas=3 -n jingyun
kubectl scale deployment/auth-service --replicas=3 -n jingyun
故障预防
1. 系统监控预防
监控指标设置
# 关键指标监控
system_metrics:
- name: cpu_usage
threshold: 80
action: scale_up
- name: memory_usage
threshold: 85
action: scale_up
- name: disk_usage
threshold: 90
action: cleanup
- name: error_rate
threshold: 5
action: alert
自动化扩容
# HPA 配置
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: user-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: user-service
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
2. 数据备份预防
自动化备份
#!/bin/bash
# backup.sh
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backup/$DATE"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 数据库备份
pg_dump -h localhost -U akita -d jingyun | gzip > $BACKUP_DIR/jingyun.sql.gz
# Redis 备份
redis-cli --rdb $BACKUP_DIR/redis.rdb
# 上传到对 象存储
aws s3 sync $BACKUP_DIR s3://jingyun-backup/$DATE/
# 清理旧备份
find /backup -type d -mtime +30 -exec rm -rf {} \;
# 发送备份通知
curl -X POST https://api.slack.com/webhooks/backup \
-H "Content-Type: application/json" \
-d "{\"text\":\"Backup completed: $DATE\"}"
备份验证
#!/bin/bash
# verify_backup.sh
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backup/$DATE"
# 验证数据库备份
gunzip -c $BACKUP_DIR/jingyun.sql.gz | head -20
# 验证 Redis 备份
redis-cli --rdb -c $BACKUP_DIR/redis.rdb
# 验证对象存储
aws s3 ls s3://jingyun-backup/$DATE/
# 发送验证结果
if [ $? -eq 0 ]; then
curl -X POST https://api.slack.com/webhooks/backup \
-H "Content-Type: application/json" \
-d "{\"text\":\"Backup verification passed: $DATE\"}"
else
curl -X POST https://api.slack.com/webhooks/backup \
-H "Content-Type: application/json" \
-d "{\"text\":\"Backup verification failed: $DATE\"}"
fi
3. 安全预防
安全扫描
#!/bin/bash
# security_scan.sh
# 容器安全扫描
trivy image jingyun/user-service:latest
# 网络安全扫描
nmap -sS -O api.jingyun.design
# 漏洞扫描
nessus -q -x scan_config.xml api.jingyun.design
# 发送扫描报告
curl -X POST https://api.slack.com/webhooks/security \
-H "Content-Type: application/json" \
-d "{\"text\":\"Security scan completed: $(date)\"}"
访问控制
#!/bin/bash
# access_control.sh
# 检查异常登录
last -n 100 | grep -v "reboot"
# 检查失败登录
grep "Failed password" /var/log/auth.log | tail -20
# 检查端口扫描
grep "port scan" /var/log/secure | tail -20
# 自动封禁 IP
fail2ban-client status sshd
培训与演练
1. 应急响应培训
培训内容
- 系统架构和组件
- 监控工具使用
- 故障诊断方法
- 应急处理流程
- 沟通协调机制
培训计划
- 新员工培训:入职后 1 周内完成
- 定期培训:每季度一次
- 专项培训:新系统上线前
- 演练培训:每次演练后
2. 故障演练
演练类型
- 服务故障演练:单个服务故障
- 网络故障演练:网络连接中断
- 数据故障演练:数据库异常
- 灾难恢复演练:数据中心故障
演练计划
- 月度演练:服务故障演练
- 季度演练:网络故障演练
- 半年度演练:数据故障演练
- 年度演练:灾难恢复演练
演练评估
# 演练评估指标
evaluation_metrics:
- name: response_time
target: "< 5 minutes"
- name: recovery_time
target: "< 30 minutes"
- name: data_loss
target: "< 1 minute"
- name: communication
target: "clear and timely"
3. 文档维护
文档更新
- 故障记录:每次故障后更新
- 预案优化:根据演练结果优化
- 流程改进:根据实际情况改进
- 技术更新:系统升级后更新
文档审查
- 月度审查:检查文档完整性
- 季度审查:检查文档准确性
- 年度审查:全面审查和更新
联系信息
应急联系人
一线响应团队
- 运维负责人:张三,电话:13800138000
- 开发负责人:李四,电话:13800138001
- DBA:王五,电话:13800138002
二线支持团队
- 架构师:赵六,电话:13800138003
- 安全专家:钱七,电话:13800138004
- 网络工程师:孙八 ,电话:13800138005
管理层
- 技术总监:周九,电话:13800138006
- 产品总监:吴十,电话:13800138007
外部服务商
云服务商
- AWS:400-810-6666
- 阿里云:95187
- 腾讯云:95716
网络服务商
- 电信:10000
- 联通:10010
- 移动:10086
安全服务商
- 绿盟科技:400-818-7000
- 启明星辰:400-810-7777
- 深信服:400-630-2123