构建内部集合并以锁定版本的方式分发
目标
亲手走一遍这一整圈:把多个 role 打包成一个 collection 并附上版本,安装构建出来的压缩包并用 FQCN 调用,再用固定文件锁定安装版本。
为什么重要
role 是复用单元,而 collection 是分发单元。团队一多,问题就从“这个 role 怎么用”转为“现在那台服务器上跑的 role 是哪个版本”。collection 为回答这个问题引入了三样东西:把来源写进名称(FQCN)、给压缩包附上版本(SemVer)、把要安装的版本写进文件(requirements.yml)。没有这三样,就由搜索路径的顺序决定执行什么,而这个顺序不是由人,而是由环境决定的。再加上 role 参数规范,错误的值在 task 运行之前就会被拦下——这是把供别人使用的代码发出去时,比文档更该先具备的东西。本实验在没有互联网的情况下,只用本地压缩包走完这一整圈。
步骤
- 用
ansible-galaxy collection init在/root/ans/coll/src下创建acme.platformcollection 的骨架。然后创建/root/ans/inventory/hosts.ini,写入 web1、web2、db1 的 inventory(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root)。 - 把
/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。 - 在 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 来调用。 - 创建
roles/motd/meta/argument_specs.yml,在main入口中写short_description和三个参数。三个都是type: str并且要有description,motd_owner用choices只允许platform和sre两个值。 - 构建 collection,生成
/root/ans/coll/dist/acme-platform-1.2.0.tar.gz,并确认压缩包里有MANIFEST.json、FILES.json和 role 文件。 - 把做好的压缩包安装到
/root/ans/coll/collections,确认在该路径下acme.platform显示为 1.2.0,并确认能用ansible-doc查询到acme.platform.motdrole 的参数。 - 创建
/root/ans/coll/use.yml,用 FQCN 调用acme.platform.motdrole,把motd_banner设为acme-platform in production,把motd_owner设为sre。以 inventory 中的web1为目标运行,留下/root/ans/coll/out/motd.txt。 - 把源码
galaxy.yml的版本升到1.3.0重新构建(压缩包就有两个了),在/root/ans/coll/requirements.yml中以type: file固定1.2.0压缩包,并用该文件安装。然后把安装好的版本用一行留到/root/ans/coll/out/pinned.txt。
参考
- 这个 Pod 没有互联网。从 Galaxy 下载,以及 galaxy.yml 中 dependencies 的自动解析,在这个环境中无法重现,所以从实验中去掉了。init、build、本地压缩包 install 都能正常工作。
- 发行版自带的 collection 已经装了几百个。查看列表时,请像
ansible-galaxy collection list acme.platform -p <경로>(占位符为路径)这样把名称和路径一起给出。 - 用
-p安装时会出现“可能是 pip 管理的位置”的警告。安装是正常的。 - 常见错误:装好了却在运行时不给搜索路径。安装的位置和运行时查看的位置必须一致。
- 常见错误:把 galaxy.yml 的 version 写成两段。构建当场就会拒绝。
- Collections Guide · Collection structure · Distributing collections · Installing collections
创建 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 的输出中提取后写上。