饮墨

子安饮墨馀三斗,留与卿儿作赋来

用 Ansible Semaphore 替代 AWX/Tower:3 步搭建轻量 Ansible Web 管理平台,告别命令行裸跑

Ansible 好用,但团队规模一上来,谁跑了什么 Playbook、改了哪台机器、上次部署是啥时候——全靠口头交接和 history | grep ansible。AWX(Tower 开源版)太重,光部署就要 K8s + PostgreSQL + Redis。Semaphore 只需要一个二进制 + SQLite,5 分钟就能给 Ansible 加上 Web UI、权限管控、执行历史和 Webhook 触发。


痛点:Ansible 裸跑的 3 个致命问题

团队 5 个人共用一台跳板机跑 Ansible:

  1. 无审计 — 谁在凌晨 3 点跑了 site.yml 把生产数据库配置覆盖了?history 被清了,无从追溯
  2. 无权限隔离 — 实习生和架构师共享同一个 inventory,一个 --limit 忘加就是全量推送
  3. 无调度 — 定时巡检靠 crontab + 脚本,失败了没人知道

AWX 能解决这些,但它自身就是一套分布式系统:PostgreSQL、Redis、3 个容器、K8s Operator。一个管理工具比被管理的服务还复杂,本末倒置。


方案:Semaphore — Ansible 的轻量 Web 控制台

Semaphore(GitHub 10k+ star)是一个开源的 Ansible UI,核心特性:

特性 Semaphore AWX
部署复杂度 单二进制 / Docker 单容器 K8s + PostgreSQL + Redis
资源占用 128MB RAM 起 4GB RAM 起
执行历史 ✅ 完整日志
权限管控 ✅ 项目级 RBAC ✅ 更细粒度
Webhook/API 触发
定时任务 ✅ cron 表达式
学习曲线 10 分钟上手 1-2 天

适用场景:中小团队(2-20 人)、不需要多租户、够用就好。


实操:3 步部署 Semaphore

第 1 步:Docker Compose 一键部署

创建 docker-compose.yml

version: "3.8"
services:
  semaphore:
    image: semaphoreui/semaphore:v2.10.22
    container_name: semaphore
    ports:
      - "3000:3000"
    environment:
      SEMAPHORE_DB_DIALECT: bolt    # 用 BoltDB,免装数据库
      SEMAPHORE_ADMIN_PASSWORD: "YourStr0ngP@ss"
      SEMAPHORE_ADMIN_NAME: "admin"
      SEMAPHORE_ADMIN_EMAIL: "admin@example.com"
      SEMAPHORE_ADMIN: "admin"
      SEMAPHORE_ACCESS_KEY_ENCRYPTION: "your-32-char-encryption-key!!"  # 必须 32 位
    volumes:
      - ./data:/var/lib/semaphore
      - ./playbooks:/opt/playbooks   # 挂载你的 Playbook 仓库
      - ~/.ssh:/home/semaphore/.ssh:ro  # SSH 密钥(只读)
    restart: unless-stopped

启动:

docker compose up -d
# 检查状态
docker logs semaphore | tail -5
# 输出: Listening on 0.0.0.0:3000

浏览器访问 http://<your-ip>:3000,用 admin 账号登录。

第 2 步:配置项目 + Inventory + 密钥

在 Web UI 中按顺序操作:

# 1. 创建 Key Store — 添加 SSH 私钥
#    类型: SSH Key,粘贴你的私钥内容

# 2. 创建 Inventory — 指定主机清单
#    类型: File,路径指向容器内文件 /opt/playbooks/inventory/production.ini
#    或者选 Static,直接粘贴 INI 格式内容:
[webservers]
10.0.1.10 ansible_user=deploy
10.0.1.11 ansible_user=deploy

[dbservers]
10.0.2.20 ansible_user=deploy

# 3. 创建 Repository — 关联 Playbook 来源
#    类型: Local,路径: /opt/playbooks
#    或 Git,填入仓库 URL + Deploy Key

# 4. 创建 Task Template — 定义可执行任务
#    Playbook 文件名: deploy-app.yml
#    关联 Inventory + Key + Repository

第 3 步:配置 Webhook 触发 + 定时任务

CI/CD 集成 — GitHub Actions 触发部署:

在 Task Template 设置中开启 Webhook,拿到 URL:

# 在 GitHub Actions workflow 中添加:
- name: Trigger Ansible Deploy
  run: |
    curl -X POST \
      "https://semaphore.example.com/api/project/1/tasks" \
      -H "Authorization: Bearer ${{ secrets.SEMAPHORE_TOKEN }}" \
      -H "Content-Type: application/json" \
      -d '{"template_id": 1}'

定时巡检 — cron 表达式:

在 Task Template 中设置 Schedule:

# 每天早上 8 点执行巡检 Playbook
0 8 * * *

执行历史自动保留,失败会在 UI 标红,支持配置邮件/Telegram 通知。


3 个常见坑

坑 1:SSH 连接超时,容器内无法访问目标机器

# 症状:Task 报 "unreachable"
# 原因:容器网络隔离,无法直达目标 IP
# 解决:使用 host 网络模式
services:
  semaphore:
    network_mode: host    # 直接用宿主机网络
    ports: []             # host 模式不需要端口映射

坑 2:Playbook 路径找不到

# 症状:Task 报 "Could not find playbook"
# 原因:Repository 路径和 Template 中 Playbook Filename 不匹配
# 解决:Template 里填的是相对于 Repository 根目录的路径
# 如果 Repo 路径是 /opt/playbooks,Playbook 在 /opt/playbooks/roles/deploy.yml
# 那么 Template 填:roles/deploy.yml

坑 3:升级后数据丢失

# 症状:Docker 重建容器后历史任务全没了
# 原因:BoltDB 文件在容器内,没挂载 volume
# 解决:确保 /var/lib/semaphore 挂载到宿主机
# 生产环境建议切换到 MySQL/PostgreSQL:
SEMAPHORE_DB_DIALECT: mysql
SEMAPHORE_DB_HOST: 127.0.0.1
SEMAPHORE_DB_PORT: 3306
SEMAPHORE_DB_NAME: semaphore
SEMAPHORE_DB_USER: semaphore
SEMAPHORE_DB_PASS: "db-password"

总结

维度 效果
部署时间 5 分钟(Docker 单容器)
资源开销 128MB RAM + 50MB 磁盘
解决问题 审计追溯、权限隔离、定时调度
适用团队 2-20 人中小运维团队

Semaphore 不是 AWX 的完全替代——它没有多租户、工作流编排等高级功能。但对于绝大多数中小团队,能看到谁在什么时间跑了什么、能控制谁能跑什么、失败了能收到通知——这三件事就够了。

与其花两天部署 AWX 然后再花一周学它的概念模型,不如 5 分钟起一个 Semaphore,把精力留给真正的自动化逻辑。

您还没有登录,请登录后发表评论。