foms/models/clusters.json
yumoqing fa257f36b1 feat(failover): 补全主备切换闭环 — 六步状态机 + 逆向回滚 + 健康判定器
依据现有实现补全「自动识别故障 → 人工确认切换 → 切回」运维核心闭环。
触发模式 1A+2B+3A:VIP 浮动 + 半自动 + 切前隔离原主(防脑裂)。

【表结构】
  clusters 加 vip/failover_mode;node_commands 加 command_type
  新增 switchover_steps(切换步骤级审计)

【Agent 六动作(脚本化、幂等、结构化返回)】
  fence(停MySQL+摘VIP)/unfence(恢复)/promote_master(STOP+RESET SLAVE)
  revert_promote(降回从库)/flip_sync(反转同步)/verify(可写+VIP校验)

【切换编排器 foms/failover.py】
  六步状态机:precheck→fence→promote→flip_sync→verify→converge
  失败 → 已完成步骤逆向回滚 → switchover_logs=failed
  回滚也失败 → rollback_failed + 最高级告警冒泡人工
  防脑裂不变量:fence 先于 promote,fence 失败硬中止绝不 promote

【健康判定器】
  后台循环(默认5s)扫 active 集群,心跳超时/复制异常判定
  防抖:连续 failover_threshold 次命中才判故障(防瞬时抖动误判)
  半自动:只告警(写 switchover_logs + hostwatch_events)不切,等人确认

【切回 + 回滚语义】
  trigger_switchback 反向六步;回滚用 unfence/revert_promote/反转/换回

【部署文档】
  docs/deploy-operations.md:架构/三机部署/keepalived/Agent 环境变量/
  日常运维/失败语义/防脑裂/已知限制

验证:语法全过;编排器↔Agent 六命令类型对齐;六步顺序正确;
防脑裂不变量成立(fence idx=1 < promote idx=2);注册链完整。
2026-08-26 18:33:42 +08:00

34 lines
1.9 KiB
JSON

{
"summary": [
{
"name": "clusters",
"title": "集群定义",
"primary": ["id"],
"catelog": "entity"
}
],
"fields": [
{"name": "id", "title": "集群ID", "type": "str", "length": 32, "nullable": "no"},
{"name": "name", "title": "集群名称", "type": "str", "length": 128, "nullable": "no"},
{"name": "description", "title": "集群描述", "type": "str", "length": 512},
{"name": "master_node_id", "title": "主机节点", "type": "str", "length": 32},
{"name": "standby_node_id", "title": "备机节点", "type": "str", "length": 32},
{"name": "check_interval", "title": "检测间隔(秒)", "type": "int", "nullable": "no", "default": "10"},
{"name": "failover_threshold", "title": "故障判定阈值(次)", "type": "int", "nullable": "no", "default": "3"},
{"name": "vip", "title": "VIP地址(CIDR)", "type": "str", "length": 64},
{"name": "failover_mode", "title": "触发模式", "type": "str", "length": 16, "nullable": "no", "default": "semi"},
{"name": "status", "title": "集群状态", "type": "str", "length": 32, "nullable": "no", "default": "stopped"},
{"name": "created_at", "title": "创建时间", "type": "datetime"},
{"name": "updated_at", "title": "更新时间", "type": "datetime"}
],
"indexes": [
{"name": "idx_clusters_name", "idxtype": "unique", "idxfields": ["name"]}
],
"codes": [
{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='cluster_status'"},
{"field": "failover_mode", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='failover_mode'"},
{"field": "master_node_id", "table": "nodes", "valuefield": "id", "textfield": "host"},
{"field": "standby_node_id", "table": "nodes", "valuefield": "id", "textfield": "host"}
]
}