跳到主要内容

灾备与应急预案(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

最佳实践

1. 预防为主

  • 建立完善的监控体系
  • 定期进行系统巡检
  • 及时处理潜在问题
  • 持续优化系统架构

2. 快速响应

  • 建立明确的响应流程
  • 设置合理的告警阈值
  • 准备充分的应急资源
  • 保持有效的沟通机制

3. 持续改进

  • 定期进行故障复盘
  • 根据经验优化预案
  • 持续更新技术方案
  • 加强团队技能培训

4. 文档完善

  • 保持文档的及时更新
  • 确保文档的准确性
  • 提供详细的操作步骤
  • 建立文档的审查机制