本文目录导读:

在脚本中进行灾备切换的验证非常关键,因为如果切换脚本本身有缺陷,不仅无法完成切换,还可能造成数据丢失或业务中断。
下面从验证维度和具体方法两个层面,为你拆解如何验证灾备切换脚本。
核心验证维度
验证灾备切换脚本是否合格,需要覆盖以下四个核心领域:
-
功能正确性
- 切换:脚本能否顺利将VIP、DNS、数据库、应用服务从主节点切换到备节点?
- 回切:切换后,脚本能否在指定条件下,顺利将业务切回主节点?
- 异常处理:脚本是否处理了各种可能的中断(如网络超时、权限不足、磁盘空间满)?
-
原子性与幂等性
- 原子性:脚本要么全部成功,要么全部失败,不会停留在中间状态(只切换了前两个步骤,第三个步骤失败)。
- 幂等性:脚本可以重复执行多次,不会产生副作用(重复执行不会导致VIP绑定到多个节点)。
-
数据一致性
- 切换前:确保主备数据同步完全一致(如数据库日志应用完毕)。
- 切换后:验证备节点数据是否完整可用,且无脏数据。
-
执行效率与健壮性
- 超时控制:脚本中的每个操作都应有超时机制,防止因某一步卡死导致整个切换失败。
- 日志与通知:脚本应输出详细的执行日志,并在关键节点发送告警/通知。
具体验证方法(分阶段进行)
建议按照从简单到复杂、从单元到整体的顺序进行验证。
单元测试(离线验证)
不依赖真实环境,只测试脚本的逻辑片段。
- 方法:
- 将脚本中的核心函数(如
check_health、floating_ip_modify、read_config)独立出来。 - 对函数输入各种边界值(空参数、非法IP、超长字符串)。
- 使用Mock技术模拟远程命令、API调用,验证脚本的异常处理分支是否正常。
- 将脚本中的核心函数(如
- 示例:
- 测试
check_ssh_connectivity函数:当SSH连接超时时,脚本是否会重试?重试次数是否正确?最终返回false还是抛出异常?
- 测试
集成测试(沙箱/测试环境)
在完全隔离的测试环境(最好是与生产环境网络、配置完全一致的副本)中执行。
- 方法:
- 冷启动验证:在测试环境从零开始部署主、备节点,执行切换脚本。
- 监控脚本输出:实时观察脚本输出的日志,检查每一步的状态。
- 状态检查点:在每次切换后,手动检查以下项:
- VIP是否漂移到备节点IP?
- DNS解析是否指向备节点IP?
- 数据库连接是否正常?
- 应用能否正常启动?
- 故障注入:在脚本执行过程中,人为制造故障:
- 切断网络连接。
- 模拟磁盘空间满。
- 停止关键服务(如数据库)。
- 模拟SSH密钥失效。
- 示例:
- 执行切换脚本到第5步(停止主库),此时手动
kill掉主库进程,观察脚本能否正确识别并转到备库接管流程。
- 执行切换脚本到第5步(停止主库),此时手动
压力与并发测试(稳定性验证)
模拟真实故障时的并发压力。
- 方法:
- 使用压测工具(如
ab、wrk、JMeter)持续向主节点发送请求。 - 在压测进行到一半时,触发切换脚本。
- 检查指标:
- 切换时间:从脚本执行到业务恢复的时间(RTO,恢复时间目标)。
- 丢包率:切换过程中,有多少请求失败或超时。
- 数据一致性:切换后,检查数据库是否丢失了最后几秒的事务。
- 使用压测工具(如
- 示例:
录制生产环境的流量,在测试环境重放,在流量高峰期执行切换,验证服务中断时间是否在SLA(服务水平协议)范围内(< 30秒)。
回切与循环验证(可逆性验证)
灾备不仅要能切过去,更要能切回来。
- 方法:
- 编写回切脚本,并采用与切换脚本相同的方法进行验证。
- 循环测试:执行
切换 -> 回切 -> 再切换 -> 再回切循环5-10次,每次循环后,手工验证数据一致性和业务可用性。
- 痛点:
很多脚本只在第一次切换好使,第二次切换后状态就乱了(配置文件被修改,但下次没重置)。
自动化验证框架(最佳实践)
手动验证效率低,建议编写一个验证脚本来自动验证切换脚本。
# 伪代码示例:验证切换脚本的框架
import subprocess
import time
import logging
logger = logging.getLogger("DisasterRecovery_Validator")
def run_switchover(script_path):
"""执行切换脚本并返回结果"""
logger.info(f"正在执行切换脚本: {script_path}")
result = subprocess.run(
[script_path, "--mode", "switchover"],
capture_output=True,
text=True,
timeout=300 # 设置5分钟超时
)
if result.returncode != 0:
logger.error(f"脚本执行失败: {result.stderr}")
return False
logger.info(f"脚本输出: {result.stdout}")
return True
def verify_vip(target_ip):
"""验证VIP是否生效"""
# 使用ping或arping检查VIP是否在目标机器上
output = subprocess.run(...)
# 解析输出逻辑
if "from " + target_ip in output:
return True
return False
def verify_database_connection(host, port, user, password):
"""验证数据库连接"""
import pymysql
try:
conn = pymysql.connect(host=host, port=port, user=user, password=password, timeout=5)
# 执行一条查询,确认可读写
cursor = conn.cursor()
cursor.execute("SELECT 1")
conn.close()
return True
except Exception as e:
logger.error(f"数据库连接失败: {e}")
return False
def verify_application_health(url):
"""验证应用健康检查接口"""
import requests
try:
response = requests.get(url, timeout=5)
if response.status_code == 200 and response.json().get("status") == "healthy":
return True
except Exception as e:
logger.error(f"健康检查失败: {e}")
return False
def main():
# 1. 初始状态检查
assert verify_vip("10.0.0.1") # 假设VIP在主节点
# 2. 执行切换
assert run_switchover("/opt/scripts/dr_switch.sh")
# 3. 验证切换后状态
time.sleep(2) # 给服务一些时间恢复
assert verify_vip("10.0.0.100") # VIP现在应该在备节点
assert verify_database_connection("10.0.0.100", 3306, "appuser", "pass")
assert verify_application_health("http://10.0.0.100:8080/health")
# 4. 执行回切
assert run_switchover("/opt/scripts/dr_switch.sh", mode="failback")
# 5. 验证回切后状态
time.sleep(2)
assert verify_vip("10.0.0.1")
assert verify_database_connection("10.0.0.1", 3306, "appuser", "pass")
assert verify_application_health("http://10.0.0.1:8080/health")
logger.info("所有灾备切换脚本验证通过!")
if __name__ == "__main__":
main()
常见问题与检查清单
在验证过程中,你一定会遇到以下问题,请重点检查:
- SSH/密钥问题:
- 脚本运行账户的SSH免密登录是否配置正确且针对所有节点?
StrictHostKeyChecking是否设置为no(或使用已知主机文件)?
- 权限问题:
- 执行脚本的用户是否有
sudo权限?是否需要NOPASSWD? - 脚本中是否有针对特定路径(如
/var/log、/opt/app)的写入权限?
- 执行脚本的用户是否有
- 依赖包/命令缺失:
- 备节点是否安装了所有脚本依赖的命令(如
jq、awk、mysql-client)?
- 备节点是否安装了所有脚本依赖的命令(如
- 网络隔离:
- 如果VIP跨网段,是否需要静态ARP配置?
- 防火墙规则是否允许VIP在节点间漂移?
- 日志不可见:
- 脚本是否将错误输出到
stderr?你的验证脚本是否捕获了stderr?
- 脚本是否将错误输出到
- 不要仅仅在“一切正常”时验证,好的验证必须包含故障注入。
- 自动化验证比手动点击更可靠、可重复。
- 循环测试才能发现幂等性问题。
- 最终验证标准是:脚本执行后,你的监控系统(如Prometheus、Zabbix)是否显示所有指标恢复正常? 这是最客观的验证。