跳转至

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 — 轻量级单机/主从 PostgreSQL
  • postgresql_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 — Clone
  • xinfra_mha — MHA
  • dm_archery — 审核
  • vault-dm — Vault
  • xinfra_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 节点):

  1. 校验制品 URL 和密钥
  2. 安装内部 APT 签名密钥和快照
  3. 安装 PostgreSQL、Python 运行时包
  4. 创建数据目录结构
  5. 创建隔离的 Patroni venv(python3 -m venv,验证 system-site-packages=false)
  6. 将白名单 OS Python 包复制到 venv
  7. 从内部 PyPI 安装 patroni==3.2.2、psycopg[binary]==3.3.4、ydiff、cdiff
  8. 验证 venv 完整性(import patroni.ctl、patronictl --help)
  9. 下载并安装 etcd 静态制品
  10. 创建 etcd systemd 单元并启动,等待 quorum
  11. 安装 pgBackRest、postgres_exporter
  12. 生成 pgBackRest SSH 密钥、授权所有节点、pin known_hosts
  13. 渲染配置文件并启动 Patroni 和 exporter

Play 2(安装 HAProxy/Keepalived):

  1. 安装 HAProxy 和 Keepalived
  2. 渲染配置(验证语法)
  3. 启动服务,等待 HAProxy 能连通 PostgreSQL primary

Play 3(创建备份):

  1. 发现当前 primary
  2. 创建 pgBackRest stanza
  3. 在两个仓库各创建一次全量备份

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 自动化配置。