2017年12月25日月曜日

Ansible: include の代わりに使う import_xxx, include_yyy とは


このエントリーをはてなブックマークに追加


この記事は Ansible Advent Calendar 2017 の一部です。

ここ数年、Advent Calendar の季節くらいしか記事を書かなくなってしまいました。もうちょっとアウトプットしたいのですが、色々手を出しすぎてなかなか時間が取れないのが悩みです。

さて、Ansible 2.4 をお使いの方は、以下のような警告をみたことがある方もいると思います。

[DEPRECATION WARNING]: The use of 'include' for tasks has been deprecated. Use 'import_tasks' for static inclusions or 'include_tasks' for dynamic inclusions. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: include is kept for backwards compatibility but usage is discouraged. The module documentation details page may explain more about this rationale.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

この警告は「include が廃止されるので別の方法に切り替えてね」というメッセージです。
include は Playbook や Task の再利用において重要な機能であるため、多くの方が include は当たり前の様に使っていると思います。

今回はこの変更点に触れていきたいと思います。


include モジュールは 2.8 で廃止予定

これはモジュールの解説ページにも記載されていますが、include は2.8をめどに完全に削除される予定になっています。
http://docs.ansible.com/ansible/latest/include_module.html

* include は実際にはモジュールではなく Ansible 本体の機能です。モジュールっぽく取り扱った方が説明が平易なため、ここでは include モジュールと表現していきます。


では代わりに何を使うかというと、

|-----------------+-----------------------------------+---------|
| module          | description                       | version |
|-----------------+-----------------------------------+---------|
| import_playbook | import a playbook.                |     2.4 |
| import_role     | Import a role into a play         |     2.4 |
| include_role    | Load and execute a role           |     2.2 |
| import_tasks    | import a task list.               |     2.4 |
| include_tasks   | dynamically include a task list.  |     2.4 |
|-----------------+-----------------------------------+---------|

になります。これらの違いは後に説明します。


どのような問題が include モジュールにはあったのか?

include モジュールは他のPlaybookやTaskを呼び出すことができますが、呼び出されるコンテキストによって挙動が変わるように実装されていました。特に2.0以降で include には Dynamic と Static という考え方も追加され、更にそれを特定条件で抑制したり有効にしたりと include の挙動が複雑化していました。

Dynamic と Static については去年のAnsible Advent Calendar 2016 「AnsibleのDynamic IncludeとStatic Include」で解説されています。

その結果、特に include のネストが深くなった際に予期せぬ動作が発生してしまうケースが報告されるようになりました(2.3で顕在化)。そのため、複雑化した include の動作を分解して、利用者が状況に応じて Dynamic と Static を使い分けるようにしよう、と今回の変更が行われたというのが経緯になります。


include_xxx, import_yyy の違い

こちらに詳しい説明があります。
https://docs.ansible.com/ansible/2.4/playbooks_reuse.html
https://docs.ansible.com/ansible/2.4/playbooks_reuse_includes.html

また、挙動の詳細に関しては先のブログでも例題付きで解説されていますので、ここではポイントのみを解説します。

import_yyy モジュール
Static
Playbookの読み込み時に一緒にimport先が読み込まれます(先読み)

include_xxx モジュール
Dynamic
Playbookの実行時に include 箇所まで処理が来た時にinclude先が読み込まれます(後読み)

role に関しては2.3より前では常に Static でしたが、2.3で追加された include_role でタスク内から Dynamic に呼び出す事が可能になっています。


具体的にどう使い分けるのか?

今までは include がいい感じに判断してくれていたので、あまり意識する必要はありませんでしたが、今後は幾つかのケースにおいては利用者がきっちりと使い分ける必要がでてきます。ここではその使い分けを意識するケースを紹介していきます。


■ループ系の処理と組み合わせる場合は include_yyy (Dynamic) しか使えない
おそらくこれが一番大きな点になります。
これらのループ処理と一緒に使う場合は、include_yyy しか使えません。
http://docs.ansible.com/ansible/latest/playbooks_loops.html


■変数化したファイル名を指定する場合には include_yyy (Dynamic) しか使えない
import_xxx はPlaybookの実行前に読み込みが行われるので変数の値は使えません。
これは先読み(Static)、後読み(Dynamic)の違いのわかりやすいケースです。


■include_yyy した先のタグやタスクを取得することができない
例えば、import_xxx した場合は --list-tag で import_xxx の先のタグを表示し、指定することができますが、include_yyy ではできません。
これも先読み(Static)、後読み(Dynamic)の違いのわかりやすいケースです。


■nofify で include_yyy (Dynamic) の handler を認識できない。
Dynamicに指定されたファイルは実行時まで読み込まれないので「ハンドラーがない」とエラーになります。


まとめ

これから新しいPlaybookを書く場合には「includeは使わない」という事を覚えておけばあまり問題にならないと思います。import_xxx/include_yyy の使い方を間違えるとだいたいはエラーになるからです。

厄介なのは新旧のPlaybookが混在し include/import_xxx/include_yyy が入り乱れている場合です。
改修が難しい場合には、Ansibleのバージョンを固定して切り離した環境として使い捨てにしてしまうの1つの手です。
Ansible は利用者の増加に伴い、急速に機能・モジュールの拡充が進んでいます。バージョン固定すると新しいモジュールも使えなくなってしまうので、このあたりはバランスをどう取るかが課題です。

もし、今後のバージョンアップを含めてAnsibleを末永く使っていこうと計画している場合は、これを機にCI環境を整備して、Playbookの鮮度を保っていくという取り組みも有効です。


Ansible は目の前の作業を自動化するにはおそらく最も簡単な方法の一つです。ぜひ作業を自動化して得られた時間で、より自動化を活用するための「仕組み」も一緒に考えてみてください。

それでは皆様、来年もよい自動化を。