术语
在展开之前,有几个术语值得先说清楚:
- Ansible Collection — 一个自动化打包单元,可以包含角色(Role)、模块和插件。大多数模块用 Python 编写(面向 Linux 服务器和网络设备),或者用 PowerShell 编写(面向 Windows)。
- Ansible Role — 一组预先定义好的任务,可以包含变量、模板、文件和 handler。角色既可以打包在 Collection 里,也可以独立存在。
- Config as Code (CaC) — 通过代码来定义和管理配置的做法,用自动化、复用和版本控制取代手工配置。
引言
我叫 Kristian,是 ebdruplab.semaphoreui 的作者——这是一个用代码管理 Semaphore UI 安装环境的 Ansible Collection。
起因
这个项目最初只是我加深理解 Ansible 的一种方式。在那之前,我基本上都是在用别人写好的 collection 和角色,或者把 ansible.builtin.cmd、register 和 Jinja2 模板拼起来把事情做完。
真正勾起我兴趣的,是一次需要自动化某些冷门网络设备的需求——具体来说,是验证数据库里的序列号是否设置正确。做完那个项目后,我又回到了熟悉的 PowerShell 工作,直到一份新的咨询工作把我重新拉回 Ansible。那份工作什么都涉及:从补丁管理,到协助搭建 Ansible 节点、提供最佳实践建议,再到编写安装 Red Hat Single Sign-On 的内容。
我使用 Ansible 已经七年了——从 CLI 开始,转到 Ansible Automation Platform(AAP)v2,最后又逐渐远离它。为什么?AAP 功能强大但过于笨重,是为大型企业打造的。在 OpenShift 之外部署它相当痛苦,许可成本也印证了这一点。
为什么选择 Semaphore UI
Semaphore UI 用它的简单打动了我。一个软件包、一台服务器(除非你需要企业级规模),而不是六台虚拟机通过十个端口以十种不同方式互相通信。
没错,AAP 的 execution environments 设计得很优雅。但维护它们又是另一回事。Semaphore UI 打补丁方便、运行简单,界面响应迅速且直观。它确实缺少一些高级功能,但对我的使用场景来说,它在能力与成本之间取得了恰当的平衡。
我最早是在 homelab 社区听说 Semaphore 的,当时并没太在意——直到真正上手试用。等我去 Ansible Galaxy 查看,发现还没有相应的 collection,决定就变得很容易了:这就是我的学习项目。 代码都是我自己写的吗?不是——整个过程中我借助了 AI。但项目是一点点成形的:这里半小时,那里一小时。没过多久,我就把整个 Semaphore API 转换成了 Python 模块。

可以用它做什么?
Ansible Galaxy 上有关于 ebdruplab.semaphoreui 用法的示例。这里也举几个例子:
创建和管理项目 — 把你的 Semaphore 项目定义为代码,并可重复地部署
- name: Create project with token and custom settings
ebdruplab.semaphoreui.project_create:
host: http://localhost
port: 3000
api_token: "{{ semaphore_token }}"
name: "My Project"
alert: true
alert_chat: "#alerts"
max_parallel_tasks: 5
demo: false
配置 inventory — 以编程方式管理静态和动态 inventory
- name: Create static inventory
ebdruplab.semaphoreui.project_inventory_create:
host: http://localhost
port: 3000
session_cookie: "{{ login_result.session_cookie }}"
project_id: 1
inventory:
name: "Local Static Inventory"
type: "static"
inventory: "localhost ansible_connection=local"
ssh_key_id: 42
become_key_id: 7
设置任务模板 — 无需打开界面即可创建和更新模板
- name: Create template with UI-style override flags
ebdruplab.semaphoreui.project_template_create:
host: http://localhost
port: 3000
api_token: "{{ semaphore_token }}"
project_id: 1
template:
name: "ff"
playbook: "f"
repository_id: 1
inventory_id: 1
environment_id: 1
type: ""
arguments: "[]"
task_params:
allow_override_tags: true
allow_override_limit: true
tags: ["t"]
limit: ["t"]
管理用户 — 自动创建用户并把他们分配到项目
- name: Create a new user
ebdruplab.semaphoreui.user_create:
host: http://localhost
port: 3000
session_cookie: "{{ login_result.session_cookie }}"
name: "Jane Smith"
username: "jsmith"
email: "[email protected]"
password: "supersecure123"
admin: true
alert: true
备份已有项目 — 把任意在用项目导出为 YAML,纳入版本控制
- hosts: localhost
gather_facts: false
roles:
- role: ebdruplab.semaphoreui.project_backup
vars:
project_backup_semaphore_host: "https://semaphore.example.com"
project_backup_semaphore_api_token: "{{ lookup('env', 'SEMAPHORE_TOKEN') }}"
project_backup_project_name: "My Project"
恢复或迁移 — 几秒内根据 YAML 定义重新部署完整的项目配置。
- hosts: localhost
gather_facts: false
vars_files:
- vars/project.yml
roles:
- role: ebdruplab.semaphoreui.project_deploy
Config as Code — ebdruplab.project_deploy
一个模块变成了两个,两个变成了十个。最终,这个 collection 达到了 92 个模块,覆盖项目、模板、inventory 等等。
某个时候,有用户希望有一个角色能把这些模块粘合起来。这个角色就是 ebdruplab.project_deploy——你可以精确定义一个 Semaphore UI 项目应该是什么样子,然后通过 Ansible 声明式地创建它。



一个最简项目定义看起来是这样的:
project_deploy_config:
project:
name: "My Project"
alert: false
alert_chat: ""
max_parallel_tasks: 0
demo: false
users_access:
- username: "admin"
role: "Owner"
keys:
repo_login:
name: "Git Login"
type: login_password
login_password:
login: "git-user"
password: "{{ vault_git_password }}"
repositories:
- name: "Example Repo"
git_url: "https://github.com/example/repo.git"
git_branch: "main"
key_name: "Git Login"
views:
main:
title: "Main"
position: 0
inventories:
local_inventory:
name: "Local Inventory"
type: "static"
inventory: "localhost ansible_connection=local"
environments:
default_env:
name: "Default Environment"
env:
APP_ENV: "prod"
templates:
deploy_job:
name: "Deploy"
type: "job"
repository_name: "Example Repo"
inventory_name: "Local Inventory"
environment_name: "Default Environment"
view_title: "Main"
playbook: "playbooks/site.yml"
schedules: {}
integrations: {}
文档发布在 Ansible Galaxy 上,GitHub 仓库中的 project_deploy 和 project_backup 目录下都包含 examples/ 和 test/ 文件夹,方便你上手。
Config as Code 转换器 — ebdruplab.project_backup
做完 project_deploy 之后,我又有了一个想法:那些不是通过代码创建的既有 Semaphore 项目怎么办?我做了 ebdruplab.project_backup 来解决这个问题——它读取一个既有项目,并把它导出为与 project_deploy 兼容的 YAML 变量文件。
这样就形成了闭环:无论你是从零开始,还是迁移现有环境,都可以把一切纳入版本控制。


开始使用
一条命令即可安装该 collection:
ansible-galaxy collection install ebdruplab.semaphoreui
然后查看 Ansible Galaxy 上的完整文档,或浏览 GitHub 上的示例。
如果你发现任何错误,或者有想法,请不要犹豫,直接提交 issue/feature/question:https://github.com/Ebdruplab/ansible-collection_ebdruplab/issues;平时我也常在 Semaphore UI 的 Discord 服务器里晃悠——TrimmerWolf7。
希望这个 collection 对你有用。