XINFRA Ansible 自动化报告¶
生成日期:2026-08-27 | 基于源码深度分析
一、整体结构¶
graph TD
Root["ansible/"] --> MF["gather-host-facts.yml"]
Root --> GF["group_vars/all.yml"]
Root --> PG["postgresql-deploy.yml"]
Root --> PG_R["postgresql-rollback.yml"]
Root --> Tasks["tasks/cleanup-controller-ssh-key.yml"]
Root --> Tpl["templates/postgresql-instance.conf.j2"]
Root --> MySQL["mysql/"]
Root --> PGHA["postgresql_ha/"]
MySQL --> M_Deploy["deploy.yml"]
MySQL --> M_Pre["precheck.yml"]
MySQL --> M_Fail["failover.yml"]
MySQL --> M_Roll["rollback.yml"]
MySQL --> M_Conf["config-apply.yml"]
MySQL --> M_Vars["vars/ / tasks/ / templates/ / files/"]
PGHA --> P_Deploy["deploy.yml"]
PGHA --> P_Pre["preflight.yml"]
PGHA --> P_Accept["final_acceptance.yml"]
PGHA --> P_Switch["control-switchover.yml"]
PGHA --> P_Restart["control-restart.yml"]
PGHA --> P_Clean["cleanup.yml"]
style Root fill:#e1f5fe
style MySQL fill:#fff3e0
style PGHA fill:#e8f5e9
💡 三套自动化体系
mysql/— MySQL 原生交付(11 个 Playbook),覆盖部署/回滚/故障切换/巡检/配置变更等postgresql-deploy.yml— 轻量级单机/主从 PostgreSQL 交付postgresql_ha/— 生产级 PostgreSQL HA 集群(Patroni + etcd + HAProxy + Keepalived + pgBackRest)
角色划分:
mysql/— 完整的 MySQL 原生交付生命周期postgresql-deploy.yml/postgresql-rollback.yml— 轻量级单机/主从 PostgreSQLpostgresql_ha/— 生产级 PostgreSQL HA 集群(Patroni + etcd + HAProxy + Keepalived + pgBackRest)tasks/+templates/+group_vars/+files/— 跨服务共享资源
二、MySQL 自动化 (mysql/)¶
2.1 Playbook 清单¶
| Playbook | 职责 |
|---|---|
deploy.yml |
唯一部署入口:回调(precheck) → 参数校验 → MHA 制品安装 → 回调(install) → MySQL 二进制安装 → 回调(configure) → 账号配置 → 复制配置 → MHA 配置 → 回调(healthcheck) → TCP 端口检查 → 回调(register) |
precheck.yml |
只读预检查:Python 脚本检查磁盘空间、内存、端口、制品可用性、目录冲突,输出结构化 JSON |
rollback.yml |
回滚:停止 MHA Manager → 清理 SSH 授权 → 删除 MHA 工作目录 → 停止实例 → 删除配置/二进制/数据/运行时目录 |
failover.yml |
两阶段切换:(1) 普通 primary_replica 主从切换(无 MHA)(2) MHA 模式切换(masterha_master_switch) |
decommission.yml |
下线:校验参数 → 检查状态 → 停止 MHA Manager → 先停从库 → 再停主库(先设 read_only)→ 写下线标记 |
inspect.yml |
实例巡检:检查 service 状态、配置、安装目录、数据目录、端口,输出 running/stopped/moved/deleted/unknown |
config-apply.yml |
动态配置变更:写入 my.cnf 片段、重启实例(逐台从库后主库)、执行 SQL、轮换 root 密码 |
mha-check.yml |
MHA 验收:渲染配置 → 执行 masterha_check_repl → 安装/启动 Manager 服务 |
purge.yml |
安全销毁:校验下线标记 → 确认服务停止 → 删除数据/程序/配置 → 验证删除 |
rejoin.yml |
旧主重加入:备份旧数据 → Clone 接收 → 新 server_uuid → GTID 复制 → 校验一致性 |
restore.yml |
恢复已下线实例:校验下线标记 → 启动实例 → 验证 UUID 和数据可读 |
💡 Deploy 流水线
deploy.yml 是 MySQL 唯一部署入口,通过回调机制(callback.yml)向 AWX 上报进度。每个阶段都有独立回调,支持前端实时追踪任务状态。
2.2 公共变量 (vars/delivery.yml)¶
核心变量:
| 变量名 | 默认值 | 说明 |
|---|---|---|
mysql_instance |
instance_name |
实例名 |
mysql_version_value |
8.0 |
MySQL 版本 |
mysql_port_value |
13306 |
SQL 端口(池范围 13306-13999) |
mysql_gr_port_value |
SQL 端口+10000 | GR 组通信端口 |
mysql_data_disk |
/data |
数据盘挂载点 |
mysql_memory_mb_value |
4096 |
内存配额(MB) |
mysql_storage_gb_value |
50 |
存储配额(GB) |
ha_mode_value |
none |
高可用模式(none/mha) |
failover_mode_value |
manual |
切换模式(manual/automatic) |
目录布局:
{data_disk}/mysql-delivery/{instance}/
├── data/ # 数据目录
├── logs/ # 日志目录
├── logs/binlog/ # Binlog 目录
├── logs/redo/ # Redo 日志目录
└── tmp/ # 临时目录
/opt/mysql-delivery/{instance}/current → /opt/mysql/{version} (symlink)
/run/mysql-delivery-{instance}/ # 运行时目录
账号体系(7 个内置账号):
xinfra_repl— 复制xinfra_clone— Clonexinfra_mha— MHAdm_archery— 审核vault-dm— Vaultxinfra_restore— 恢复xinfra_config— 参数管理
二进制制品目录(mysql_binary_catalog):
8.0— full_version=8.0.46,含 SHA256 校验和下载地址8.4— full_version=8.4.8,含 SHA256 校验和下载地址
2.3 Tasks 详情¶
tasks/validate.yml — 参数校验¶
- 拓扑合法性(standalone/primary_replica)
- MHA 模式要求 MySQL 8.0 + 至少 2 副本 + 主机数匹配
- 密码长度 >= 16、实例名格式、版本在 catalog 内
- 操作系统要求 Ubuntu 24.04+ x86_64
- 端口 13306-13999、内存 2-64G、存储 20-2000G
- 探测端口占用、检查可用内存和磁盘空间
tasks/install.yml — 安装流程¶
- 可选配置内部 APT 源
- 安装依赖包(aria2, ca-certificates, libaio1t64, libatomic1, libncurses6 等)
- 创建
mysql系统用户 - 原子缓存并安装 MySQL generic binary(aria2 多线程下载、SHA256 校验、flock 并发锁)
- 通过 symlink 选择实例版本
- 安装
xinfra-mysql-start启动器 - 创建实例目录结构
- 计算
server_id(端口+节点序号)、内存档位(max_connections 梯度表)、redo 容量 - 渲染
mysql-instance.cnf.j2 - 初始化数据目录(
mysqld --initialize-insecure) - 安装 systemd 模板单元并启动
tasks/accounts.yml — 账号配置¶
- 等待 socket 可用
- 初始化 root 密码(
SET SESSION sql_log_bin=0,避免 GTID 污染) - 安装 Clone 插件(MHA 模式)
- 创建远程 root、Vault、复制/Clone/MHA、恢复、配置、Archery 账号
- 使用临时文件存储凭据(
mktemp+chmod 600+trap),避免命令行泄露
tasks/replication.yml — 复制配置¶
- MHA 模式下执行 MySQL Clone(从主库全量克隆,throttle=1 串行)
- Clone 后重新生成 server_uuid(删除
auto.cnf重启) - 配置 GTID 复制(
CHANGE REPLICATION SOURCE TO ... SOURCE_AUTO_POSITION=1) - 校验复制线程(IO/SQL Running: Yes)
- 校验 GTID 收敛(无 errant GTID、无 missing GTID)
tasks/mha-artifacts.yml — MHA 制品安装¶
- 下载 mha4mysql-node 和 mha4mysql-manager deb 包(SHA256 校验)
- 所有节点安装 node,最后一个副本节点安装 manager
- 校验 Perl 模块
tasks/mha.yml — MHA 配置¶
- 生成集群独立 SSH 密钥(ed25519)
- 授权 Manager 公钥到所有节点(
restrict前缀) - 校验免密 SSH
tasks/callback.yml — 进度回调¶
- POST 请求到
delivery_callback_url,携带 Bearer token、stage、status、message、awx_job_id
2.4 Templates¶
mysql-instance.cnf.j2 — MySQL 实例配置¶
关键配置段:
- 字符集: utf8mb4 / utf8mb4_general_ci / +08:00 / lower_case_table_names=1
- 日志: error.log、slow-query-log、long_query_time
- Binlog: ROW 格式、sync_binlog=1、max_binlog_size、expire_logs_seconds=604800
- 复制: gtid-mode=ON、enforce-gtid-consistency=ON、relay-log、read-only/super-read-only(从库)
- InnoDB: buffer_pool=55% 内存、O_DIRECT、flush_log_at_trx_commit=1、io_capacity=2000
- Redo: innodb-redo-log-capacity(按内存档位:128M/256M/512M/1G)
- Group Replication(mgr_3 拓扑): plugin-load-add、group_name、local-address、group-seeds、single-primary-mode
mysql-mha.cnf.j2 — MHA Manager 配置¶
[server default]:user/password、manager_workdir、ssh_options(指定密钥和 known_hosts)、repl_user/password、ping_interval=5、report_script(自动模式)[serverN]:每个节点的 hostname、port、candidate_master、no_master
mysql-mha-manager.service.j2 — MHA Manager systemd 单元¶
- ExecStartPre:
masterha_check_repl --conf=... - ExecStart:
masterha_manager --conf=... --remove_dead_master_conf - Restart=on-failure, RestartSec=10s, StartLimitBurst=5
xinfra-mha-report.j2 — MHA 故障转移回调脚本¶
- 解析
--orig_master_host、--new_master_host参数 - 构建 JSON payload,curl POST 到回调 URL,retry 5 次
2.5 Files¶
mysql-delivery@.service — systemd 模板单元¶
- Type=exec, User=mysql, Group=mysql
- ExecStart:
/usr/local/libexec/xinfra-mysql-start %i - Restart=on-failure, RestartSec=5s, TimeoutStartSec=120s
- LimitNOFILE=65535, OOMScoreAdjust=-200
xinfra-mysql-start — 启动器脚本¶
- 优先使用
/opt/mysql-delivery/{instance}/current/bin/mysqld - 回退到
/usr/sbin/mysqld(兼容 APT 安装的存量实例)
三、PostgreSQL HA (postgresql_ha/)¶
3.1 HA 架构设计¶
拓扑:3 节点共置
graph TD
VIP["VIP (Keepalived)"] --> HA["HAProxy:5432 (读写分离)"]
HA --> N1["Node 1\nPG+Patroni\ndetcd+pgBR\nHAProxy+Keepalived"]
HA --> N2["Node 2\nPG+Patroni\ndetcd+pgBR\nHAProxy+Keepalived"]
HA --> N3["Node 3\nPG+Patroni\ndetcd+pgBR\nHAProxy+Keepalived"]
N1 -.->|"etcd quorum"| N2
N2 -.->|"etcd quorum"| N3
N3 -.->|"etcd quorum"| N1
style VIP fill:#fff3e0
style HA fill:#e1f5fe
style N1 fill:#e8f5e9
style N2 fill:#e8f5e9
style N3 fill:#e8f5e9
服务依赖链:
graph LR
ETCd["etcd"] --> Patroni["Patroni"]
Patroni --> Exporter["postgres-exporter"]
HAProxy["HAProxy"] -.->|"健康检查 /primary"| Patroni
Keepalived["Keepalived"] -.->|"VRRP 心跳"| HAProxy
style ETCd fill:#e1f5fe
style Patroni fill:#e8f5e9
💡 HA 架构要点
- DCS: 独立 etcd 3 节点集群(非系统 etcd),用于 Patroni 分布式协调
- VIP: Keepalived unicast 模式在 3 个 HAProxy 之间漂移,nopreempt 避免脑裂
- 读写分离: HAProxy 通过 Patroni REST API
/primary健康检查路由到主库 - 备份冗余: pgBackRest 双仓库(repo1/repo2 分布在不同节点)
关键设计:
- DCS:独立 etcd 3 节点集群(非系统 etcd)
- VIP:通过 Keepalived unicast 模式在 3 个 HAProxy 之间漂移
- HAProxy 通过 Patroni REST API
/primary健康检查路由到主库 - pgBackRest 双仓库:repo1 在第一个节点、repo2 在第二个节点
3.2 Playbook 清单¶
| Playbook | 职责 |
|---|---|
preflight.yml |
静态预检:校验操作身份哈希、平台密钥、CPU/内存/磁盘容量、端口空闲、Keepalived 接口/unicast peer/L2 可达性、VIP 未被占用、制品仓库可达性 |
deploy.yml |
端到端部署(3 个 play):安装组件 → 配置 HAProxy/Keepalived → 创建 pgBackRest 备份 |
final_acceptance.yml |
静态验收:Patroni 健康、集群成员(3 running + 1 primary)、etcd 健康、同步复制、HAProxy 端点、VIP 所有权、创建 Archery 账号 |
control-switchover.yml |
计划切换:读取 Patroni 集群 → 解析 sync standby → patronictl switchover → 验证收敛 |
control-restart.yml |
重启/滚动重启:单节点重启(leader 自动先切换)或滚动重启(serial:1) |
control-acceptance.yml |
轻量验收:Patroni 健康、集群成员收敛、pg_isready、etcd 健康、HAProxy/Keepalived 状态 |
cleanup.yml |
清理:停止服务 → 删除单元/配置/数据 → 验证端口和进程清除 |
3.3 关键变量¶
| 变量名 | 默认值 | 说明 |
|---|---|---|
postgresql_version |
17 |
PostgreSQL 版本 |
postgresql_port |
15432 |
PostgreSQL 端口 |
patroni_rest_port |
8008 |
Patroni REST API 端口 |
haproxy_service_port |
5432 |
HAProxy 监听端口 |
vip_address |
- | VIP 地址 |
vip_prefix_length |
- | VIP 前缀长度 |
vip_interface |
- | VIP 网络接口 |
synchronous_mode |
true |
同步复制开关 |
synchronous_mode_strict |
true |
严格同步复制 |
3.4 deploy.yml 核心流程¶
Play 1(所有 postgresql 节点):
- 校验制品 URL 和密钥
- 安装内部 APT 签名密钥和快照
- 安装 PostgreSQL、Python 运行时包
- 创建数据目录结构
- 创建隔离的 Patroni venv(
python3 -m venv,验证 system-site-packages=false) - 将白名单 OS Python 包复制到 venv
- 从内部 PyPI 安装 patroni==3.2.2、psycopg[binary]==3.3.4、ydiff、cdiff
- 验证 venv 完整性(
import patroni.ctl、patronictl --help) - 下载并安装 etcd 静态制品
- 创建 etcd systemd 单元并启动,等待 quorum
- 安装 pgBackRest、postgres_exporter
- 生成 pgBackRest SSH 密钥、授权所有节点、pin known_hosts
- 渲染配置文件并启动 Patroni 和 exporter
Play 2(安装 HAProxy/Keepalived):
- 安装 HAProxy 和 Keepalived
- 渲染配置(验证语法)
- 启动服务,等待 HAProxy 能连通 PostgreSQL primary
Play 3(创建备份):
- 发现当前 primary
- 创建 pgBackRest stanza
- 在两个仓库各创建一次全量备份
3.5 Templates¶
patroni.yml.j2 — Patroni 配置¶
- scope/namespace/name
- restapi:监听
ansible_host:patroni_rest_port - etcd3:hosts 列表、http 协议
- bootstrap.dcs:ttl=30、loop_wait=10、retry_timeout=10、maximum_lag_on_failover=1048576
- synchronous_mode / synchronous_mode_strict
- PostgreSQL 参数:max_connections、shared_buffers=1GB、wal_level=replica、max_wal_senders=10、synchronous_commit=on、archive_mode=on(pgbackrest archive-push)
- initdb:UTF8、data-checksums
- pg_hba:peer 本地、scram-sha-256 远程
- create_replica_methods: basebackup (checkpoint: fast)
haproxy.cfg.j2 — HAProxy 配置¶
- TCP 模式
- frontend:
0.0.0.0:{haproxy_service_port} - backend:
patroni_primary,使用option httpchk GET /primary(Patroni REST API 健康检查)
keepalived.conf.j2 — Keepalived 配置¶
- VRRP 实例
VI_PGHA,state=BACKUP,nopreempt - 单播模式(unicast_src_ip + unicast_peer)
- 健康检查脚本:
check-xinfra-haproxy.sh - auth_pass 由集群 UUID SHA1 派生
pgbackrest.conf.j2 — pgBackRest 配置¶
- 双仓库:repo1 在第一个节点、repo2 在第二个节点
- retention-full=2
- stanza 名 = 集群名
四、通用共享资源¶
4.1 group_vars/all.yml — SSH 密钥管理¶
xinfra_ssh_private_key_scope: "{{ task_id | ... }}_{{ job_id | ... }}"
xinfra_ssh_private_key_path: "/tmp/xinfra-ssh-{{ machine_id }}-{{ scope }}.pem"
xinfra_ssh_private_key_file: "{{ lookup('pipe', 'umask 077 && ... base64 ... mv ...') }}"
ansible_ssh_private_key_file: "{{ xinfra_ssh_private_key_file }}"
变量优先级:xinfra_runtime_task_id > xinfra_runtime_inventory_id > manual
4.2 tasks/cleanup-controller-ssh-key.yml¶
遍历 ansible_play_hosts_all,删除每个主机的临时 SSH 私钥文件。用于所有 playbook 的 post_tasks 段。
4.3 templates/postgresql-instance.conf.j2 — 单机/主从 PostgreSQL 配置¶
- listen_addresses = '*'
- shared_buffers = 25% 内存、effective_cache_size = 70% 内存
- wal_level=replica、max_wal_senders、max_replication_slots、wal_keep_size=256MB
- primary/replica 条件分支:replica 时填写主库连接信息和 replication slot
4.4 files/postgresql-xinfra@.service — systemd 模板单元¶
- Type=notify, User=postgres, Group=postgres
- 通过环境变量
POSTGRESQL_VERSION、POSTGRESQL_DATA_DIR、POSTGRESQL_CONFIG_FILE、POSTGRESQL_HBA_FILE启动 postgres
五、脚本工具链 (scripts/)¶
| 脚本 | 职责 |
|---|---|
build-publish-mha-packages.sh |
MHA deb 包修补与发布:修复 MySQL 8.x 版本解析正则、更新版本号和依赖、重新打包上传 |
publish-harbor.sh |
Docker 镜像构建推送:docker buildx build --platform linux/amd64,标签 git short hash |
publish-postgresql-python-runtime-closure.sh |
构建不可变 APT 快照:收集运行时包、SHA256 校验、生成 Packages 索引、GPG 签名、上传 Nexus |
validate-postgresql-python-runtime-closure.sh |
校验 APT 快照幂等性:两次独立演练对比 URI 和 SHA256 |
run-server-postgresql-local.sh |
本地启动 Go 后端:从配置文件加载环境变量、自动从 K8s secret 获取 AWX 密码 |
setup-postgresql-awx.sh |
单机 PostgreSQL AWX 环境初始化:创建 Project、Inventory、Credential Type、Job Template |
setup-postgresql-ha-e2e-awx.sh |
PGHA E2E AWX 工作流初始化:publish 模式创建全套资源、check 模式深度验证 |
tests/setup-postgresql-ha-e2e-awx-test.sh |
AWX 设置脚本的 mock 测试 |
ci/integration.sh |
CI 集成冒烟测试:启动后端、轮询端点、运行集成测试 |
六、设计亮点¶
💡 原子安装
aria2 多线程下载 + SHA256 校验 + flock 并发锁,保证二进制安装的原子性和幂等性。
💡 凭据安全
临时文件存储(mktemp + chmod 600 + trap),避免命令行泄露;SSH 密钥 ed25519 + restrict 前缀。
💡 GTID 复制
全流程 GTID 模式,Clone 后自动重新生成 server_uuid,校验 errant/missing GTID。
💡 MHA 集成
自动化 MHA 制品安装、配置、验收、故障转移回调。
💡 PG HA 全栈
Patroni + etcd + HAProxy + Keepalived + pgBackRest,VIP 漂移 + 读写分离 + 双仓库备份。
💡 不可变 APT 快照
内部 PyPI + APT 仓库,GPG 签名,幂等性校验。
💡 AWX 集成
完整的 Project/Inventory/Template/Workflow 自动化配置。