术语

在展开之前,有几个术语值得先说清楚:

  • 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_deployproject_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 对你有用。

You might also like