1
2
3
4
5
作者:李晓辉

微信联系:Lxh_Chat

联系邮箱: 939958092@qq.com

开发自己的 Ansible 内容集合而不是使用官方集合,可以在以下场景中带来许多好处:

  1. 满足特定需求:官方 Ansible 集合可能无法完全满足特定业务需求。自己开发集合可以针对这些需求量身定制,从而提高工作效率和效果。

  2. 灵活性和可控性:开发自己的集合能够保证对代码和功能的完全控制。这意味着可以自由地进行修改、扩展和维护,而不需要依赖第三方更新和修复。

  3. 避免冗余和冲突:官方集合可能包含许多不必要的功能,导致冗余和潜在的冲突。开发自己的集合可以精简代码,减少依赖,从而提高系统的稳定性和性能。

  4. 提升安全性:官方集合可能存在已知的安全漏洞和风险。通过自己开发,可以更及时地修复安全问题,并且更严格地控制访问权限,保护系统安全。

  5. 增强团队技能:开发和维护自己的 Ansible 集合,可以提升团队成员的技能和经验,增强团队在自动化和配置管理领域的能力。

Ansible 2.8 及更早版本不⽀持集合

为集合选择命名空间

命名空间其实就是集合名称的第一个部分,就像 amazon.aws 这个集合中的 amazon。要是你打算在 galaxy 这种公共平台上发布集合,最好还是用自己的用户名来做命名空间。这样一来,名字就不会撞车,独一无二!就像给自己的项目贴上专属标签一样,简单明了,还特别有范儿。

比如我的名字,我是李晓辉,所以我自己起一个集合名为lixiaohui,我开发的功能就可以用lixiaohui.XXX

选择命名空间的时候要多花点心思:

  • 如果你打算把集合发布到 Ansible Galaxy,那就直接用你的 Ansible Galaxy 用户名作为命名空间吧,这样最方便。

  • 要是发布到私有自动化中心的话,就请平台管理员帮你创建命名空间。不过,如果你的账户权限够高的话,你也可以自己创建。

  • 如果你是红帽的合作伙伴,并且要把集合发布到自动化中心,那就用红帽分配给你公司专用的命名空间。

这样一来,就能确保你的命名空间专属、唯一,同时也很省心。

创建集合目录结构

使用 ansible-galaxy collection init 命令可以为你的新集合创建目录结构。只需在命令后面添加集合的名称(包括命名空间)作为参数就好了。这一步会帮你快速搭建好集合的基本框架,省去了手动创建文件夹和文件的麻烦。

比如说,你的命名空间是 my_namespace,集合名称是 my_collection,那么命令就会像这样:

1
ansible-galaxy collection init my_namespace.my_collection

创建的结构看起来就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
my_namespace/
└── my_collection/
├── README.md
├── docs/
│ └── README.md
├── galaxy.yml
├── plugins/
│ ├── README.md
│ ├── action/
│ ├── become/
│ ├── cache/
│ ├── callback/
│ ├── cliconf/
│ ├── connection/
│ ├── filter/
│ ├── httpapi/
│ ├── inventory/
│ ├── lookup/
│ ├── modules/
│ ├── netconf/
│ ├── shell/
│ ├── strategy/
│ ├── terminal/
│ ├── test/
│ └── vars/
├── roles/
│ └── example_role/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ ├── defaults/
│ │ └── main.yml
│ ├── vars/
│ │ └── main.yml
│ ├── files/
│ ├── templates/
│ ├── meta/
│ │ └── main.yml
│ └── README.md
└── tests/
└── unit/

添加内容到集合

是不是感觉好多好长啊?如果你的集合中不需要某些文件和目录,比如没有角色的话,就可以删除 roles/ 目录。这不仅可以让你的集合结构更简洁,还能避免不必要的文件混淆视听。

就像整理房间一样,保持整洁、只保留必要的东西,会让你在使用和维护集合时更加得心应手。如果不需要某个目录或文件,大胆地删掉吧!

plugins/ 目录下,把你开发的模块、插件和过滤器各就各位。比如:

  • 对于模块,创建 plugins/modules/ 子目录,然后把模块的 Python 脚本放进去。

  • 对于清单插件,就创建并使用 plugins/inventory/ 子目录。

如果你已经有现成的角色,可以把它们的目录结构挪到 roles/ 目录里。如果需要为集合新建角色,只需在 roles/ 目录中运行这个命令:

1
2
3
4
5
6
7
8
9
10
11
# 创建集合的目录结构
ansible-galaxy collection init my_namespace.my_collection

# 进入 roles 目录
cd my_namespace/my_collection/roles

# 初始化一个新角色
ansible-galaxy role init <角色名称>

# 切换回集合目录
cd ..

更新集合元数据

galaxy.yml 文件里,是 Ansible 构建和发布集合的“说明书”。这个文件就像是集合的信息库,包括了各种参数的说明。以下是个完整的 galaxy.yml 文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---
namespace: mynamespace
name: mycollection
version: 1.0.0
readme: README.md
authors:
- your name <example@domain.com>
description: Ansible modules to manage my company's custom software
license:
- GPL-3.0-or-later

repository: https://git.example.com/training/my-collection

# The URL to any online docs
documentation: https://git.example.com/training/my-collection/tree/main/docs

# The URL to the homepage of the collection/project
homepage: https://git.example.com/training/my-collection

# The URL to the collection issue tracker
issues: https://git.example.com/training/my-collection/issues

dependencies:
community.general: '>=1.0.0'
ansible.posix: '>=1.0.0'

声明集合依赖项

集合依赖

有些集合需要其他集合的支持才能正常工作。比如,一个新的集合里的角色可能会用到其他集合的模块。在 galaxy.yml 文件里,我们可以使用 dependencies 参数来声明这些必要的集合。

比如说,下面这个例子里,我们列出了 community.generalansible.posix 作为必需的集合:

1
2
3
dependencies:
community.general: ">=1.0.0"
ansible.posix: ">=1.0.0"

Python 依赖

想象一下有一个集合,里面包含了一些插件、模块或者过滤器,得依赖其他 Python 库才能运行。为了让它们跑得飞快,你得确保在执行环境里已经装好这些 Python 包哦!就像 amazon.aws 集合依赖 boto 库来让你使用 Amazon Web 服务 SDK。为了方便管理这些依赖,我们通常会在集合的根目录下弄一个 requirements.txt 文件,在里面一行行列出需要的包。比如,amazon.aws 集合的 requirements.txt 内容大概就是这样。如果你不管包的具体版本,版本号那部分也可以不写,挺自由的!

1
2
3
botocore>=1.18.0
boto3>=1.15.0
boto>=2.49.0

软件包依赖

如果你的集合还需要一些系统级的软件包,比如 ansible.posix 集合需要安装 rsync RPM 软件包,那你就可以在集合的根目录下创建一个 bindep.txt 文件。在这个文件里,每行列出一个 RPM 包的名字。比如,ansible.posix 集合的 bindep.txt 内容可以是这样:

1
rsync

如果你只想在特定平台(比如 CentOS 8 或 RHEL 8)上安装 rsync,你可以在 bindep.txt 文件里使用条件表达式来指定平台。像这样:

1
rsync [platform:centos-8 platform:rhel-8]

bindep 工具就像是一个多平台软件包管理助手,专门用来处理 bindep.txt 文件的。它能帮你在多个 Linux 发行版之间搞定不同的软件包名称。因为每个发行版可能会给同一个软件起不同的名字,bindep 就能通过平台指令来确保每个平台都安装正确的软件包。

比如,前面提到的 [platform:centos-8 platform:rhel-8],它告诉 bindep 只有在 CentOS 8 或 RHEL 8 上才安装某个包。还有一种指令叫做 [platform:rpm],它适用于所有使用 RPM 包管理系统的 Linux 发行版(比如 CentOS、RHEL、Fedora 等),让你不用担心具体的发行版名字。

举个例子,假如你有一个 bindep.txt,这么写:

1
2
rsync [platform:centos-8 platform:rhel-8]
git [platform:rpm]

当你或自动化控制器运行 ansible-galaxy collection install 命令来安装集合时,会帮你自动安装你在 galaxy.yml 文件里声明的其他集合。不过有个小点,它不会处理你在 requirements.txt 里列出的 Python 软件包,也不会搞定 bindep.txt 里列出的系统级软件包。换句话说,ansible-galaxy 只是安装 Ansible 集合本身,别的依赖包得靠其他工具来帮忙。

如果你想让所有这些依赖包一并处理,那就得用 ansible-builder 命令。它会聪明地使用 requirements.txtbindep.txt 来确保所有依赖都被处理好,然后为你创建一个完整的自动化执行环境。

简单来说,ansible-galaxy 安装集合,ansible-builder 则负责把整个环境配置齐全!

你可以在 meta/runtime.yml 文件里为集合定义一些额外的元数据。如果你的集合需要特定版本的 Ansible,那就可以在这个文件里添加 requires_ansible 参数来指定版本。

比如,如果你的集合只适用于 Ansible 2.10 或更高版本,你可以在 runtime.yml 文件里这样写:

1
2
---
requires_ansible: "2.10"

ansible-galaxy collection init 命令虽然会帮你初始化大部分文件和目录结构,但它不会自动创建 meta/ 目录。这个目录是专门用来存放元数据文件的,比如 runtime.yml。所以,如果你需要这个目录并且想在其中放置像 runtime.yml 这样的文件,你得手动创建它。

如果你打算把集合发布到 Ansible Galaxy、Ansible 自动化中心或私有自动化中心,那可得注意了!meta/runtime.yml 文件和 requires_ansible 参数是必需的,否则这些平台在验证你的集合时会拒绝它。

换句话说,没有这个文件或者没有指定 requires_ansible 参数,你的集合就无法通过这些平台的验证流程,最终也就不能成功发布。

构建集合

如果你准备好了集合并且想要打包发布,接下来就需要在集合目录中运行 ansible-galaxy collection build 命令。这条命令会将你的集合打包成 .tar.gz 文件,准备好提交到 Ansible Galaxy 或其他自动化中心。

简单来说,操作步骤就是:

  1. 进入集合目录
    确保你已经在你的集合根目录下。

  2. 运行打包命令
    在终端输入以下命令:

1
ansible-galaxy collection build
  1. 检查生成的包
    执行完后,你会看到一个 .tar.gz 文件,这就是打包好的集合,可以上传到 Ansible Galaxy 或其他地方了。

验证和测试集合

当你将集合发布到 Ansible Galaxy、自动化中心或私有自动化中心时,这些平台会自动运行一些测试,确保你的集合符合平台的标准和最佳实践。例如,私有自动化中心会使用 ansible-lint 工具来验证集合是否符合 Ansible 团队设立的标准。

这些平台不仅会运行测试,还会将测试报告与集合一起发布,让你和其他人可以查看结果。测试报告通常会包含集合的质量评估,帮助你发现潜在问题,保持代码质量。

举个例子,假设你发布了一个名为 mynamespace.mycollection 的集合,平台可能会生成一个导入日志,像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
Importing with galaxy-importer 0.4.4
Getting doc strings via ansible-doc
Finding content inside collection
Loading role myrole
Linting role myrole via ansible-lint...

roles/myrole/tasks/main.yml:3:
- fqcn-builtins: Use FQCN for builtin actions.
- risky-file-permissions: File permissions unset or incorrect.

CHANGELOG.rst file not found at top level of collection.
Collection loading complete
Done

可以验证集合是否正确

1
[student@workstation ~]$ ansible-navigator lint xxx.tar.gz -m stdout

建议你将 .tar.gz 文件安装到测试系统上,开发一个 Playbook 来验证集合是否按预期工作。这样可以确保你发布的集合在实际使用中没有问题!

发布集合

Web发布

如果你要将集合上传到私有自动化中心,步骤如下:

  1. 前往 Collections > Namespaces 页面。
  2. 选择你的命名空间。
  3. 点击 Upload collection 按钮,然后提供你的 .tar.gz 文件。

上传后,管理员 需要对集合进行审核和批准,才能让用户使用。如果你的用户帐户具有审核权限,你可以按照以下步骤操作:

  1. 前往 Collections > Approval 页面。
  2. 查看显示了 ansible-lint 验证结果的导入日志。
  3. 根据验证结果,决定是批准还是拒绝该集合。

通过这个流程,确保集合符合组织内的质量标准,只有通过审核的集合才能供用户使用!

命令行发布

除了通过私有自动化中心的 Web UI 上传集合存档文件外,你还可以使用 ansible-galaxy 命令来发布集合。

首先,你需要更新 Ansible 的配置文件,以便通过命令行将集合发布到私有自动化中心。你需要在 ansible.cfg 配置文件中添加一个类似下面的设置:

1
2
3
4
5
6
[galaxy]
server_list = inbound_mynamespace

[galaxy_server.inbound_mynamespace]
url = https://hub.lab.example.com/api/galaxy/content/inbound-mynamespace/
token = <put your token here>
  1. [galaxy] 部分
  • server_list = inbound_mynamespace:这里定义了要使用的服务器列表。在这个例子中,指定了一个名为 inbound_mynamespace 的服务器。这个服务器是你私有自动化中心的名称,稍后会在 [galaxy_server] 部分提供具体的配置。
  1. [galaxy_server.inbound_mynamespace] 部分
  • 这一部分配置了名为 inbound_mynamespace 的服务器的详细信息。格式为 [galaxy_server.<server_name>],其中 <server_name> 与上面定义的 server_list 中的名称匹配。
  1. url 设置
  • url = https://hub.lab.example.com/api/galaxy/content/inbound-mynamespace/:这个 URL 是指向你私有自动化中心的 API 路径。Ansible 将通过这个 URL 上传集合,确保你将集合发布到正确的服务器。
  1. token 设置
  • token = <put your token here>:这里是一个身份验证令牌,用于验证你是否有权限将集合发布到私有自动化中心。你需要替换 <put your token here> 为你实际的 API 令牌。
  1. 使用方式
  • 在配置完成后,使用 ansible-galaxy collection publish 命令来发布集合时,Ansible 会根据这些配置与指定的服务器进行交互,上传集合到私有自动化中心。

如何通过私有自动化中心的 Web UI 配置和获取 API 令牌?

  1. 查看命名空间的入站 URL
  • 首先,前往 Collections > Namespaces
  • 然后,点击你需要的命名空间旁边的 View collections 链接。
  • 在此页面中,点击 CLI configuration 选项卡。
    • 你将看到该命名空间的入站 URL,通常是私有自动化中心的地址,格式如 https://your-automation-center-url.com/api/galaxy/content/your-namespace/
  1. 获取 API 令牌
  • 在 Web UI 中,前往 Collections > API token management
  • 点击 Load token 按钮,这将显示你的身份验证令牌。
    • 请复制该令牌,它将用于验证你发布集合的权限。
  1. 更新配置文件中的 token 行
  • 在获取到 API 令牌后,前往你的 ansible.cfg 配置文件。
  • 更新配置文件中的 token 行,将 <put your token here> 替换为你刚刚获取的 API 令牌。

要将你的集合发布到 Ansible Galaxy 或私有自动化中心,你需要运行 ansible-galaxy collection publish 命令。以下是详细步骤和注意事项:

1
[student@workstation ~]$ ansible-galaxy collection publish mynamespace-mycollection-2.0.0.tar.gz
  • 当你运行 ansible-galaxy collection publish 命令时,系统会显示与集合上传相关的消息。
  • 如果发布成功,你将在命令输出中看到类似于“Collection loading complete”和“Done”的消息,这意味着集合已成功上传。
  • 发布后,私有自动化中心的 Web UI 会显示导入日志,这些日志内容与命令行输出非常相似。日志中可能会包含以下信息:
    • 验证结果(如 ansible-lint 检查)
    • 警告(例如缺少 CHANGELOG.rst 文件)
    • 成功消息(如 Collection loading complete

更新集合

每当你修改了集合,记得更新一下 galaxy.yml 文件中的 version 参数哦!如果你不更新版本号,分发平台可能会拒绝你的集合,因为它们需要确保每个版本的集合都是唯一的。

具体步骤如下:

  1. 修改集合时,打开 galaxy.yml 文件。

  2. 更新其中的 version 参数,比如:

1
version: "1.1.0"
  1. 创建新的 .tar.gz 存档,重新发布新版本。
1
ansible-galaxy collection build

确保版本号每次都更新,保持集合的版本管理清晰明了!这样,分发平台才能顺利接受并发布你的更新版本。