跳到主要内容

执行实例级故障切换 Failover

Failover 是把一个受保护实例从源集群切换到目标集群的核心操作。它会创建 DisasterOperation,由 operator 按步骤执行。

Testudo V2 当前采用 Pilot Light(长明火)模式:备集群持续保留 standby 资源,工作负载默认保持 replicas=0,切换时再拉起目标侧工作负载。完整流程见 容灾切换流程

本页使用真实控制台操作的实例 docs-walkthrough-20260511。该实例先进入 Protected,随后执行 Failover。第一次按“执行最后一次同步”触发时,FinalSync 超过前端固定的 3 分钟超时,Operator 自动补偿后恢复为 Protected;第二次不执行最终同步的快速切换成功进入 Active;最后执行“反向保护”回到 Protected

切换前检查

  • 实例状态为 Protected
  • 最近一次 DataSync 和 ResourceSync 成功。
  • 目标集群 standby 资源存在。
  • 目标集群业务依赖、镜像、Secret、网络和入口已准备。
  • 团队已确认流量切换窗口。

进入实例详情页的 实例操作 标签。拓扑图展示当前主集群、备集群和备份存储。

保护中实例操作拓扑

模块说明:

  • 主集群:当前承载业务的 primary cluster。
  • 备集群:当前 standby cluster。
  • 备份存储:DataSync/ResourceSync 使用的存储仓库。
  • 容灾切换ProtectedPaused 状态可点击,创建 operationType=failoverDisasterOperation
  • 容灾回退:实例进入 Active 后可用,创建 operationType=undo
  • 反向保护:实例进入 Active 后可用,创建 operationType=reprotect,在当前新主方向重新建立保护。
  • 暂停/启动操作:对 DataSync 和 ResourceSync 执行 pause/resume。

执行步骤

Failover 通常包含:

  1. PreCheck:检查实例、集群、仓库和同步状态。
  2. PauseSchedules:暂停周期同步,避免并发变更。
  3. FinalSync:执行最后一次数据和资源同步。
  4. ScaleDownSource:按策略缩容源端。
  5. ScaleUpTarget:恢复目标侧副本数。
  6. CheckReplicas:检查目标侧工作负载状态。
  7. SwitchRoles:切换实例角色关系。

实际步骤来自 DisasterOperation.status.steps。本次接口返回的步骤顺序为:

PreCheck -> PauseSchedules -> FinalSync -> ScaleDownSource -> ScaleUpTarget -> CheckReplicas -> SwitchRoles

确认切换参数

点击 容灾切换 后会出现确认框。

容灾切换确认框

确认框有三个参数:

UI 选项写入接口字段说明
源集群缩0config.skipScaleDownSource勾选后,前端传 false,表示执行源端缩容;不勾选时传 true,表示跳过源端缩容。
执行最后一次同步config.skipFinalSync勾选后,前端传 false,表示执行最终同步;不勾选时传 true,表示跳过最终同步。
跳过容器就绪验证config.skipPodReadyCheck当前前端代码同样做了取反,文档以接口字段为准;实际请求结果可在 DisasterOperation.spec.skipPodReadyCheck 中确认。

这三个字段的接口由以下代码链路确认:

  • 前端:InstanceOperation.vue 调用 POST /instances/:name/actions
  • Server:读取 config.skipFinalSyncconfig.skipScaleDownSourceconfig.skipPodReadyCheck 并创建 DisasterOperation
  • Operator:按 DisasterOperation.spec 控制是否执行 FinalSync、ScaleDownSource 和 Pod ready 检查。

提交切换

示例中第一次勾选 源集群缩0执行最后一次同步

容灾切换选项

提交后实例进入 故障切换中,操作按钮被禁用,拓扑图展示正在执行。

容灾切换执行中

API

POST /apis/disasterinstances.testudo.softcdata.com/v1/instances/:name/actions
{
"operation": "failover",
"config": {
"timeoutMinutes": 3,
"skipScaleDownSource": false,
"skipFinalSync": false,
"skipPodReadyCheck": true
}
}

成功响应是异步受理,不代表切换已经完成:

{
"data": {
"operationID": "failover-docs-walkthrough-20260511-1778492672918796991",
"status": "Processing"
}
}

观察操作

kubectl -n disaster-system get disasteroperation -l testudo.softcdata.com/instance=docs-walkthrough-20260511
kubectl -n disaster-system describe disasteroperation failover-docs-walkthrough-20260511-1778492672918796991

也可以看详情接口:

GET /apis/disasterinstances.testudo.softcdata.com/v1/instances/:name/operations/:operationName

超时补偿示例

第一次切换执行最终同步时,FinalSync 超过 3 分钟超时。Operator 将该次 DisasterOperation 标记为 Failed,并自动补偿恢复实例为 Protected

自动补偿的完整分流逻辑见 容灾切换失败自动补偿机制

接口返回的关键字段:

{
"state": "Failed",
"reason": "StepFailed",
"currentStep": "FinalSync",
"message": "故障切换在步骤 FinalSync 失败后已自动补偿,实例已恢复为 Protected",
"autoCancel": {
"triggered": true,
"status": "Succeeded",
"triggerStep": "FinalSync"
}
}

这类情况通常说明最终同步时间超过当前操作超时配置。处理方式:

  • 检查 DataSync/ResourceSync、AppBackup/AppRestore、Velero Backup/Restore 事件。
  • 对生产切换窗口,按实际数据量配置更合理的操作超时。
  • 如果业务允许,可跳过最终同步,使用最近一次成功同步点执行快速切换。

快速切换成功

第二次切换不勾选 源集群缩0执行最后一次同步,前端请求会跳过源端缩容和最终同步。该次操作快速完成,实例进入 Active,界面展示为 未保护,主备角色变为:

{
"fsmState": "Active",
"primaryCluster": "cluster-ip171-1774332463",
"secondaryCluster": "ip170-test-001",
"availableOperations": ["reprotect", "undo"]
}

切换后 Active 状态

列表页也会显示该实例为 未保护,操作列从“暂停”变为“启用”。

切换后实例列表

切换后验证

kubectl --context <target-cluster> -n dr-pvc-src-170 get deploy,sts,pod,svc,pvc
kubectl --context <source-cluster> -n dr-pvc-src-170 get deploy,sts

确认目标侧应用可用后,再进行 DNS、网关或外部流量切换。Testudo 不直接替代全局流量管理。

反向保护

Failover 成功后,详情页可执行 反向保护,在当前新主集群到原主集群的方向重新建立保护。

反向保护前的操作按钮

示例中反向保护成功后,实例回到 Protected,但主备方向已经变为:

{
"fsmState": "Protected",
"primaryCluster": "cluster-ip171-1774332463",
"secondaryCluster": "ip170-test-001"
}

反向保护后回到保护中

历史记录会保留成功切换、失败补偿和反向保护操作,便于审计。

容灾操作历史