如何通过指定 tags 在一个 role 中引入另一个 role?
apply: tags 会给引入的 role 内的任务追加标签,不能按任务原有的标签筛选任务。
要按 certificates 内部原有的标签执行任务,应移除 apply: tags,给 include_role 入口设置相应标签,再通过命令行 --tags 选择。如果不传 --tags 时也只想执行 CA 和 wildcard 任务,可以用 tasks_from 指定一个只包含这些任务的入口文件。
为什么所有任务都会匹配 ca
原配置中,两处 tags 的作用不同:
- name: Copy CA certificates to prevent MITM issues
ansible.builtin.include_role:
name: certificates
apply:
tags:
- ca
- wildcards
tags:
- ca
外层的 tags: ca 控制是否选中这条 include_role 任务。apply.tags 给 role 内的任务追加 ca、wildcards 标签,不会检查任务原来的标签是否在这个列表中。include_role 参数说明
按题目中的静态导入结构,追加标签后,各组任务的有效标签如下:
| 任务组 | 原有标签 | 追加后的标签 |
|---|---|---|
| 根 CA 证书 | ca | ca, wildcards |
| 普通密钥与证书 | certs | certs, ca, wildcards |
| wildcard 证书 | wildcard | wildcard, ca, wildcards |
| IDM 证书 | idm, never | idm, never, ca, wildcards |
这些任务都带有 ca,因此执行 -t ca 时都会匹配。
示例中的 wildcards 与 role 内定义的 wildcard 是两个不同的标签,拼写需要统一。
为什么带有 never 的任务也会执行
never 表示默认跳过,但显式选择任务上的其他标签,仍可让它执行。IDM 任务继承 ca 后,就能被 --tags ca 选中。特殊标签规则
这两种运行情况需要分开看:
- 使用
-t ca时,原配置给 IDM 任务追加了ca,所以它会执行。 - 不传
-t时,如果没有其他标签配置、标签继承或always标签的影响,普通的apply.tags: [ca, wildcards]不会让never任务执行。
如果不传 -t 时也出现了这个问题,应先确认看到的是任务文件被解析、加载,还是其中的任务确实执行了。文件被加载不代表所有任务都会执行。同时检查 ansible.cfg、ANSIBLE_RUN_TAGS 和上层标签设置。
按命令行标签选择:移除 apply.tags
将 os-base/tasks/main.yml 中的引入改为:
- name: Include certificate tasks
ansible.builtin.include_role:
name: certificates
tags:
- ca
- wildcard
保留 certificates/tasks/main.yml 中各个 import_tasks 原有的标签,然后运行:
# 只选择 CA 任务
ansible-playbook playbooks/os-base.yml -e t=node1 --tags ca
# 选择 CA 和 wildcard 任务
ansible-playbook playbooks/os-base.yml -e t=node1 --tags ca,wildcard
动态 include_role 的外层标签只标记引入任务本身,不会自动传给内部任务。运行时先按标签选中入口,再按内部任务各自的标签决定是否执行。动态引入的标签规则
这里需要给入口同时添加 ca 和 wildcard。如果入口只有 ca,单独运行 --tags wildcard 时,入口会被跳过,内部的 wildcard 任务也无法执行。
也可以将入口设为:
- name: Include certificate tasks
ansible.builtin.include_role:
name: certificates
tags:
- always
这样,后续增加内部标签时通常无需修改入口。不过,使用其他标签运行时,这个入口也会被处理,内部任务仍按运行时标签筛选。
不传 --tags 时,这两种写法都会按默认规则运行 certificates 的普通任务,包括 certs,不会将默认执行范围限制为 CA 和 wildcard。
默认也只运行指定部分:使用 tasks_from
如果完整执行 os-base 时只需要 CA 和 wildcard,可以为 certificates 增加一个专用任务入口。
创建 roles/certificates/tasks/os_base.yml:
- name: Install root CA certificates
ansible.builtin.import_tasks:
file: _deploy_ca_certs.yml
tags:
- ca
- name: Install wildcard pair
ansible.builtin.import_tasks:
file: _deploy_wildcard.yml
tags:
- wildcard
在 roles/os-base/tasks/main.yml 中指定这个入口:
- name: Include certificates required by os-base
ansible.builtin.include_role:
name: certificates
tasks_from: os_base
tags:
- ca
- wildcard
tasks_from 指定从 role 的 tasks/ 目录加载哪个文件,替代默认的 main.yml。tasks_from 参数说明
使用这份配置后,可以这样运行:
# 完整执行 os-base,证书部分只包含专用入口中的任务
ansible-playbook playbooks/os-base.yml -e t=node1
# 只选择 CA 任务
ansible-playbook playbooks/os-base.yml -e t=node1 --tags ca
# 选择 CA 和 wildcard 任务
ansible-playbook playbooks/os-base.yml -e t=node1 --tags ca,wildcard
这会绕过 certificates/tasks/main.yml。如果摘要、初始化等任务是证书部署的前置步骤,也需要将它们加入专用入口。
摘要标签和排查时的注意事项
ansible_run_tags 表示本次运行选择的标签,不是当前任务持有的标签。未指定 --tags 且没有其他运行标签配置时,它通常是 ["all"];传入 --tags ca 时则是 ["ca"]。apply.tags 不会修改它。特殊变量说明
always_block 只是文件名,不会自动赋予任务 always 行为。如果希望按标签运行时也显示摘要,可以给这个静态导入显式添加标签:
- name: Import summary tasks
ansible.builtin.import_role:
name: commons
tasks_from: always_block
tags:
- always
该任务仍需位于实际加载的入口中,且未被 --skip-tags 排除。
排查时还需注意:
--tags对整个 playbook 生效,其他 role 中带有ca的任务也可能执行。如果需要独立选择,应使用更具体的标签名。- 检查上层 play、block 或 role 是否给所有子任务统一追加了
ca。如果有,移除这里的apply.tags后仍可能出现相同结果。 --list-tasks和--list-tags无法完整展示动态引入内部的任务与标签,不能仅凭列表判断实际执行范围。预览功能的限制
备注:内容仅供参考。
