TT Lab
开始
学习 学习路径 课程

Ansible 实战

构建内部集合并以锁定版本的方式分发

在 TT Lab 中继续学习

目标

亲手走一遍这一整圈:把多个 role 打包成一个 collection 并附上版本,安装构建出来的压缩包并用 FQCN 调用,再用固定文件锁定安装版本。

为什么重要

role 是复用单元,而 collection 是分发单元。团队一多,问题就从“这个 role 怎么用”转为“现在那台服务器上跑的 role 是哪个版本”。collection 为回答这个问题引入了三样东西:把来源写进名称(FQCN)、给压缩包附上版本(SemVer)、把要安装的版本写进文件(requirements.yml)。没有这三样,就由搜索路径的顺序决定执行什么,而这个顺序不是由人,而是由环境决定的。再加上 role 参数规范,错误的值在 task 运行之前就会被拦下——这是把供别人使用的代码发出去时,比文档更该先具备的东西。本实验在没有互联网的情况下,只用本地压缩包走完这一整圈。

步骤

  1. 用 ansible-galaxy collection init 在 /root/ans/coll/src 下创建 acme.platform collection 的骨架。然后创建 /root/ans/inventory/hosts.ini,写入 web1、web2、db1 的 inventory(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root)。
  2. 把 /root/ans/coll/src/acme/platform/galaxy.yml 的 version 设为 1.2.0,description、authors、repository 填上内部的值,license 写 MIT,tags 中放入 infrastructure 和 linux。并在同一个 collection 的 meta/runtime.yml 中用范围写法写上 requires_ansible。
  3. 在 collection 内的 roles/motd/ 中创建 role。在 defaults/main.yml 中放 motd_banner(默认 acme-platform)、motd_owner(默认 platform)、motd_path(默认 /root/ans/coll/out/motd.txt),tasks/main.yml 用一个有名称的 task,向 motd_path 写入 banner=<motd_banner> 和 owner=<motd_owner> 两行。模块要用 FQCN 来调用。
  4. 创建 roles/motd/meta/argument_specs.yml,在 main 入口中写 short_description 和三个参数。三个都是 type: str 并且要有 description,motd_owner 用 choices 只允许 platform 和 sre 两个值。
  5. 构建 collection,生成 /root/ans/coll/dist/acme-platform-1.2.0.tar.gz,并确认压缩包里有 MANIFEST.json、FILES.json 和 role 文件。
  6. 把做好的压缩包安装到 /root/ans/coll/collections,确认在该路径下 acme.platform 显示为 1.2.0,并确认能用 ansible-doc 查询到 acme.platform.motd role 的参数。
  7. 创建 /root/ans/coll/use.yml,用 FQCN 调用 acme.platform.motd role,把 motd_banner 设为 acme-platform in production,把 motd_owner 设为 sre。以 inventory 中的 web1 为目标运行,留下 /root/ans/coll/out/motd.txt。
  8. 把源码 galaxy.yml 的版本升到 1.3.0 重新构建(压缩包就有两个了),在 /root/ans/coll/requirements.yml 中以 type: file 固定 1.2.0 压缩包,并用该文件安装。然后把安装好的版本用一行留到 /root/ans/coll/out/pinned.txt。

参考

创建 collection 骨架

用 ansible-galaxy collection init 在 /root/ans/coll/src 下创建 acme.platform collection 的骨架。然后创建 /root/ans/inventory/hosts.ini,写入 web1、web2、db1 的 inventory(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root)。

collection 名称要以 <네임스페이스>.<이름>(占位符依次为命名空间、名称)这样整体一块给出。创建位置用 --init-path 指定,骨架会在其下按命名空间/名称两层生成。

填写 galaxy.yml 并钉死最低 ansible 版本

把 /root/ans/coll/src/acme/platform/galaxy.yml 的 version 设为 1.2.0,description、authors、repository 填上内部的值,license 写 MIT,tags 中放入 infrastructure 和 linux。并在同一个 collection 的 meta/runtime.yml 中用范围写法写上 requires_ansible。

如果骨架放入的示例文句(your name, your collection description)还在,构建虽然能成功,但不能作为发布物使用。runtime.yml 几乎全是注释,只重新写需要的键会更快。

在 collection 里放入 role

在 collection 内的 roles/motd/ 中创建 role。在 defaults/main.yml 中放 motd_banner(默认 acme-platform)、motd_owner(默认 platform)、motd_path(默认 /root/ans/coll/out/motd.txt),tasks/main.yml 用一个有名称的 task,向 motd_path 写入 banner=<motd_banner> 和 owner=<motd_owner> 两行。模块要用 FQCN 来调用。

collection 内的 role,目录约定与原来的 role 完全一样。把值写死的话 role 就无法复用,所以三个值都要用变量接收。想一次写两行,可以把多行字符串(|)作为 content 传入。

用参数规范拦住错误的值

创建 roles/motd/meta/argument_specs.yml,在 main 入口中写 short_description 和三个参数。三个都是 type: str 并且要有 description,motd_owner 用 choices 只允许 platform 和 sre 两个值。

规范不是文档,而是校验。请传入一个不在列表中的值去调用 role,亲自确认它在第一个 task 运行之前就停下。

构建压缩包并确认内容

构建 collection,生成 /root/ans/coll/dist/acme-platform-1.2.0.tar.gz,并确认压缩包里有 MANIFEST.json、FILES.json 和 role 文件。

构建要在 collection 源码目录内运行。放置结果的位置用 --output-path 指定。想看压缩包内部,不用解开,只看列表也行。

安装到本地路径并用文档确认

把做好的压缩包安装到 /root/ans/coll/collections,确认在该路径下 acme.platform 显示为 1.2.0,并确认能用 ansible-doc 查询到 acme.platform.motd role 的参数。

安装路径用 -p 给出。查询时必须让 ansible 看到那个路径,决定搜索路径的环境变量是另外的。发行版自带的 collection 已经装了几百个,所以查看列表时请指定名称。

用 FQCN 调用并运行

创建 /root/ans/coll/use.yml,用 FQCN 调用 acme.platform.motd role,把 motd_banner 设为 acme-platform in production,把 motd_owner 设为 sre。以 inventory 中的 web1 为目标运行,留下 /root/ans/coll/out/motd.txt。

调用 role 时传入的值会压过 role 的 defaults。如果提示找不到 collection,请先确认搜索路径——安装的位置和运行时查看的位置必须一致。

源码往前走,安装版本保持固定

把源码 galaxy.yml 的版本升到 1.3.0 重新构建(压缩包就有两个了),在 /root/ans/coll/requirements.yml 中以 type: file 固定 1.2.0 压缩包,并用该文件安装。然后把安装好的版本用一行留到 /root/ans/coll/out/pinned.txt。

指向本地压缩包文件时,在名称里写路径,并另外写明类型。安装好的版本不要手写,从 collection list 的输出中提取后写上。