Ansibleの罠:--tags を指定したのに include 先のタスクが全部動いてしまう原因と対策
Ansibleで特定の処理だけを実行しようと --tags を指定した際、「タグを設定していないはずのタスクまで実行されてしまった」という経験はありませんか?
これはAnsibleの仕様である「タグの継承(Inheritance)」が関係しています。
本記事では、この挙動の仕組みと、意図しない実行を防ぐための正しい書き方を解説します。
---
1. 【起】なぜ意図しないタスクが動くのか
例えば、以下のようなメインのPlaybook(main.yml)があるとします。
# main.yml
- name: crontab関連のタスクを読み込む
ansible.builtin.include_tasks:
file: "sub.yml"
tags: crontab
この状態で、コマンドラインから ansible-playbook main.yml --tags crontab を実行すると、読み込まれる sub.yml の中に書かれたタスクは、タグ設定の有無に関わらずすべて実行対象になります。
「sub.ymlの中にある特定のタスクだけを動かしたい」と思ってタグを付けても、呼び出し側の include_tasks にタグがあると、ファイル全体がそのタグの色に染まってしまうのです。
2. 【承】挙動の正体は「タグの継承」と「never」の仕様
この挙動を理解するポイントは3つです。
① タグの継承 (Tag Inheritance)
include_tasks や block に対してタグを設定すると、その配下にあるすべてのタスクにそのタグが自動的に付与(継承)されます。
たとえ sub.yml 内のタスクが空欄であっても、Ansible内部ではすべてに tags: crontab が付いているものとして処理されます。
② apply キーワードの影響
以下のように apply を使用している場合も同様です。
- name: include sub tasks
ansible.builtin.include_tasks:
file: "sub.yml"
apply:
tags: crontab
tags: crontab
apply は「インクルードされる側の各タスクに属性を適用する」ための機能です。これを使うことで、より明示的に sub.yml 内の全タスクに crontab タグを付与することになります。
③ 特殊なタグ「never」の挙動
ちなみに、Ansibleには never という特殊なタグがあります。
・--tags 指定がない場合:tags: never が設定されているタスクは実行されません。
・--tags 指定がある場合:その指定タグを持たないタスクは実行されません。
しかし、前述の「継承」が発生している場合、内部的にすべてのタスクに指定タグが付与されてしまうため、never を付けていないタスクはすべて「実行対象」へと昇格してしまいます。
3. 【転】意図したタスクだけを実行する構成
「ファイル内の一部だけを特定のタグで動かしたい」という場合は、呼び出し元(include側)にはタグを付けず、インクルード先(子タスク側)にのみタグを付けるのが正解です。
【改善後の構成】
# main.yml (タグは付けない)
- name: sub.ymlを読み込む
ansible.builtin.include_tasks:
file: "sub.yml"
# sub.yml (個別のタスクにタグを付ける)
- name: 常に動かしたくないタスク
ansible.builtin.debug:
msg: "これは --tags crontab では動きません"
- name: crontabの設定タスク
ansible.builtin.cron:
name: "check logs"
job: "/usr/bin/check_logs"
tags: crontab
この構成であれば、--tags crontab を指定した時に、意図したタスクのみを実行させることが可能になります。
4. 【結】まとめ
Ansibleのタグは非常に便利ですが、include_tasks と組み合わせる際には「継承」という強力な仕様が働きます。
・include_tasks へのタグ付与:中身をまるごと実行したい場合に使う。
・個別タスクへのタグ付与:実行対象を細かく制御したい場合に使う。
大規模なPlaybookになればなるほど、この仕様を知らないと「予期せぬタスクの実行」による事故を招く恐れがあります。実行前には必ず --list-tasks オプションを付けて、どのタスクが対象になっているか確認する習慣をつけましょう。