依据现有实现补全「自动识别故障 → 人工确认切换 → 切回」运维核心闭环。 触发模式 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);注册链完整。
7.4 KiB
7.4 KiB
FOMS 部署与运维手册
版本:2026-08-26(补全主备切换闭环后) 适用:MySQL 主从 + rsync 文件同步的双机主备,VIP 浮动(1A+2B+3A)
一、架构
管理中心 C(foms 应用 + 管理库 foms)
▲ HTTP(Bearer token)
┌────────────┴────────────┐
主机 A(master) 主机 B(standby)
· MySQL 主库 · MySQL 从库(binlog 复制)
· 业务 + keepalived · 业务 + keepalived
· foms-agent · foms-agent
└──── VIP(浮动,业务连 VIP)────┘
三个角色:
- 管理中心 C:跑 foms(核心 + dbbackup/filesync/hostwatch 模块),存配置与切换记录。
- 主机 A / 备机 B:跑业务 + MySQL + keepalived + foms-agent(守护进程)。
- VIP:业务流量入口,平时在 A,故障时漂到 B(keepalived 兜底 + FOMS 主动操作)。
二、管理中心 C 部署
cd foms
./build.sh # 建 venv、装依赖(含三模块)、生成 DDL/CRUD
建库:
mysql -uroot -p < models/mysql.ddl.sql # 核心表
mysql -uroot -p < pkgs/dbbackup/models/mysql.ddl.sql # dbbackup 表
mysql -uroot -p < pkgs/filesync/models/mysql.ddl.sql # filesync 表
mysql -uroot -p < pkgs/hostwatch/models/mysql.ddl.sql # hostwatch 表
配置数据库连接:编辑 conf/config.json 的 databases.foms(host/user/password/db)。
启动:
py3/bin/python app/foms.py # 监听 conf 里 website.port(默认 9080)
启动时 load_foms() 会自动注册切换编排器并拉起健康判定器后台任务。
三、管理中心登记拓扑(部署后必做)
在 FOMS 界面(或 API)依次创建:
- 节点(nodes):A、B 各一条,填 host、ip、ssh_port、ssh_user、role(master/standby)。
- 集群(clusters):master_node_id=A、standby_node_id=B、
vip(如192.168.1.100/24)、check_interval(检测间隔秒)、failover_threshold(连续故障次数)、failover_mode=semi。 - 复制配置(dbbackup_replications):主库/从库地址、复制账号。
- 文件同步(filesync_directories):要 rsync 的目录(source→dest)。
四、被管主机 A / B 部署
4.1 安装依赖
apt install -y mysql-server rsync keepalived ipvsadm python3
pip3 install psutil # Agent 采集系统指标需要
4.2 配置 keepalived(VIP 浮动)
A(/etc/keepalived/keepalived.conf,MASTER):
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100 # A 高优先级
advert_int 1
virtual_ipaddress { 192.168.1.100/24 }
}
B 相同,但 state BACKUP、priority 90。
keepalived 是兜底:机器全宕机时 VIP 自动漂移;"机器活、服务挂"的场景由 FOMS 主动 fence/promote 处理。
4.3 配置并启动 Agent
环境变量(A、B 各自的值不同):
export FOMS_MANAGEMENT_URL=http://<C的IP>:9080 # 管理中心地址
export FOMS_NODE_ID=<本节点在nodes表的id> # A/B 各自
export FOMS_AGENT_TOKEN=<鉴权token> # 与管理中心约定
export FOMS_HEARTBEAT_INTERVAL=10
# 切换动作专用
export FOMS_MYSQL_SERVICE=mysql # MySQL systemd 服务名
export FOMS_VIP=192.168.1.100/24 # VIP(CIDR)
export FOMS_VIP_IFACE=eth0 # VIP 所在网卡
export MYSQL_ROOT_PASSWORD=<root密码> # promote/verify 用
# 回滚降从库用(指向"对端",即本机的复制上游)
export FOMS_MASTER_HOST=<对端IP> # B 上填 A 的 IP;A 上填 B 的 IP
export FOMS_MASTER_PORT=3306
export FOMS_REPL_USER=repl
export FOMS_REPL_PASSWORD=<复制密码>
启动:
python3 foms-agent.py # 建议用 systemd 托管(见下)
systemd 单元(/etc/systemd/system/foms-agent.service):
[Unit]
Description=FOMS Agent
After=network.target
[Service]
EnvironmentFile=/etc/foms/agent.env # 上面的环境变量写这里
ExecStart=/usr/bin/python3 /opt/foms/foms-agent.py
Restart=always
[Install]
WantedBy=multi-user.target
systemctl enable --now foms-agent
4.4 Agent 需要的权限
Agent 以能执行 systemctl/ip/mysql 的用户运行(通常 root)。生产环境应收窄:
用 sudoers 白名单只允许这几条命令,而非完整 root。
五、日常运维
5.1 故障识别(自动)
健康判定器后台循环(默认 5s 扫一次):
- 判定条件:master 心跳超时(>
failover_threshold × check_interval秒)或 复制状态 error/failed。 - 防抖:连续
failover_threshold次命中才判故障(避免瞬时抖动误判)。 - 判故障 → 写
switchover_logs(status=detected, trigger=auto_detect)+ 发hostwatch_events告警。 - 半自动:只告警不切,等人确认。
5.2 故障切换(人工确认)
看到告警后,人工确认 → 触发切换:
- 界面:集群列表 → 切换按钮(
trigger_switchover) - API:
POST /api/trigger_switchover.dspy {cluster_id}
编排器异步执行六步(switchover_steps 表可查每步状态):
1. precheck 目标节点在线+心跳新鲜+复制延迟≤5s(防丢数据)
2. fence 隔离原主:停 MySQL + 摘 VIP ← 防脑裂,失败必中止
3. promote 提升新主:STOP SLAVE + RESET SLAVE ALL(原子)
4. flip_sync 反转文件同步方向
5. verify 新主可写测试 + VIP 归属检查(业务层请人工确认)
6. converge 集群主备互换 + 节点角色互换 + 状态收敛
5.3 故障维修与切回
- 修好原主 A(硬件/系统/MySQL)。
- 把 A 重新挂为 B 的从库(
CHANGE MASTER TO指向 B,START SLAVE),等复制追平。 - 确认 A 健康后,触发切回:
trigger_switchback(反向六步)。
5.4 失败与回滚语义
- 任何一步失败 → 已完成步骤逆向回滚,
switchover_logs=failed。 - 回滚也失败 →
switchover_logs=rollback_failed+ 最高级告警,人工介入。 - 回滚动作:unfence(恢复原主)、revert_promote(降回从库)、flip_sync 反转、converge 换回。
六、防脑裂三重保险
- fence 先于 promote:先停旧主 MySQL + 摘 VIP,再立新主。
- fence 失败硬中止:绝不 promote(否则双主)。
- keepalived VRRP 兜底:主机器全宕机时 VIP 自动漂移。
七、已知限制(诚实声明)
- 切换时 Agent 延迟:Agent 轮询命令,切换六步串行走完约需数十秒(运维切换通常可接受)。
- verify 只到数据层:验证"MySQL 可写 + VIP 可达",业务层是否正常需人工确认。
- 数据丢失窗口:precheck 要求复制延迟 ≤5s;fence 到 promote 之间若有未同步 binlog 会丢失(已尽量收窄)。
- 远程命令安全:命令下发目前无白名单鉴权(P1 待办),生产应收窄。
八、模块清单
| 模块 | 仓库 | 职责 |
|---|---|---|
| foms(核心) | yumoqing/foms | 集群/节点/切换编排/心跳/远程命令 |
| dbbackup | yumoqing/dbbackup | 数据库备份 + 日志同步(binlog 复制) |
| filesync | yumoqing/filesync | 运行文件同步(rsync) |
| hostwatch | yumoqing/hostwatch | 日志监控 + 日志分析 + 主机指标 |