LabHub
学习 学习路径 课程

Ansible 实战

做出可复用的 role

在 LabHub 中继续学习

目标

把 playbook 片段整理为 role,形成可复用的单元,并用不同参数多次调用同一个 role。

为什么重要

role 的本质不是“拆分代码”,而是**“预先约定规范,使其无需额外配置即可复用”**。放在 templates/ 中的文件无需写完整路径即可找到,handlers/main.yml 中的 handler 也无需注册便可使用。借助这些约定,即使是别人编写的 role,也能推断其结构。真正决定可复用性的,是对 defaultsvars 的选择——如果把用户需要修改的值放入 vars,它会因优先级过高而无法从外部覆盖,最终这个 role 只能被复制、修改并再次分叉。当 role 超过两个时,为变量名加上 role 名称前缀的习惯也会开始体现价值。

步骤

  1. /root/ans/roles/roles/webapp 下创建 tasksdefaultshandlerstemplatesmeta 目录以及 tasks/main.yml
  2. /root/ans/roles/roles/webapp/defaults/main.yml 中定义 webapp_port: 8080webapp_root: /root/ans/roles/artifacts
  3. /root/ans/roles/roles/webapp/tasks/main.yml 中加入至少两个有名称的 task,执行后应创建 /root/ans/roles/artifacts 目录。
  4. 创建 /root/ans/roles/roles/webapp/templates/webapp.conf.j2,并将其渲染到 /root/ans/roles/artifacts/webapp.conf。结果中必须有 port = 8080 行,且模板必须引用 webapp_port 变量。
  5. /root/ans/roles/roles/webapp/handlers/main.yml 中定义 restart webapp handler,并从 /root/ans/roles/roles/webapp/tasks/main.yml 的 task 中通过 notify 调用它。handler 要创建 /root/ans/roles/artifacts/restart.marker
  6. 创建 /root/ans/roles/roles/baseline role(入口为 /root/ans/roles/roles/baseline/tasks/main.yml),让它留下 /root/ans/roles/artifacts/baseline.stamp,并在 /root/ans/roles/roles/webapp/meta/main.ymldependencies 中声明该依赖。
  7. /root/ans/roles/site.yml 中调用 webapp role 两次:一次使用默认值(webapp.conf,port 8080),另一次使用 webapp_port: 9443 创建 /root/ans/roles/artifacts/staging.conf。不得复制 role 目录。
  8. 将第二次运行 playbook 的输出保存到 /root/ans/roles/out/run2.txt,将 ansible-lint 结果保存到 /root/ans/roles/out/lint.txt。第二次运行必须为 changed=0,且不得触发 handler。

参考

创建 role 骨架目录

/root/ans/roles/roles/webapp 下创建 tasksdefaultshandlerstemplatesmeta 目录以及 tasks/main.yml

ansible-galaxy role init 会生成标准结构。所需目录为 tasks/defaults/handlers/templates/meta。

定义两个默认值

/root/ans/roles/roles/webapp/defaults/main.yml 中定义 webapp_port: 8080webapp_root: /root/ans/roles/artifacts

预期可被覆盖的值应放在 defaults 中,并为名称加上 role 名称前缀。

编写并运行 role task

/root/ans/roles/roles/webapp/tasks/main.yml 中加入至少两个有名称的 task,执行后应创建 /root/ans/roles/artifacts 目录。

tasks/main.yml 是入口。至少要有两个 task,并且每个都必须有名称。

用 role 模板生成配置文件

创建 /root/ans/roles/roles/webapp/templates/webapp.conf.j2,并将其渲染到 /root/ans/roles/artifacts/webapp.conf。结果中必须有 port = 8080 行,且模板必须引用 webapp_port 变量。

templates/ 中的文件只写文件名即可找到。不要硬编码端口值,应使用变量。

定义并触发 role handler

/root/ans/roles/roles/webapp/handlers/main.yml 中定义 restart webapp handler,并从 /root/ans/roles/roles/webapp/tasks/main.yml 的 task 中通过 notify 调用它。handler 要创建 /root/ans/roles/artifacts/restart.marker

handlers/main.yml 中的 handler 会自动注册。运行后请留下标记文件。

声明依赖 role 并使其先运行

创建 /root/ans/roles/roles/baseline role(入口为 /root/ans/roles/roles/baseline/tasks/main.yml),让它留下 /root/ans/roles/artifacts/baseline.stamp,并在 /root/ans/roles/roles/webapp/meta/main.ymldependencies 中声明该依赖。

单独创建 baseline role,并写入 meta/main.yml 的 dependencies。依赖 role 会先运行。

用不同参数调用同一 role 两次

/root/ans/roles/site.yml 中调用 webapp role 两次:一次使用默认值(webapp.conf,port 8080),另一次使用 webapp_port: 9443 创建 /root/ans/roles/artifacts/staging.conf。不得复制 role 目录。

可以在 play 的 roles 段中将变量与 role 名称一起传入。不得复制 role。

验证重跑幂等性并通过 lint

将第二次运行 playbook 的输出保存到 /root/ans/roles/out/run2.txt,将 ansible-lint 结果保存到 /root/ans/roles/out/lint.txt。第二次运行必须为 changed=0,且不得触发 handler。

第二次运行应为 changed=0,handler 也应保持静默。还要保存 ansible-lint 结果。