Ansibleで互換性を維持するためのoptionを無効にしたら、20%早くなった
日本語での記事を探しても出てこなかったので書いてみます。
やったこと
-
Ansibleのバージョンを2.9.16以上にする。
-
ansible.cfgで Ansible 2.5以前との互換性維持のオプションを無効にする
[defaults]
# default: True
inject_fact_as_vars = False
- Ansibleのtaskなどで使われている古い記法のfactを修正する(
ansible_*-->ansible_facts.*)
ansible_os_distributionなどのfactをansible_facts.os_distributionへ
詳細
パフォーマンスが落ちる原因
まず前提として、Ansibleは使用メモリが増えるほど、単純なタスクでも処理が遅くなります。
どのくらいオーバーヘッドがあるかというと、このIssue の環境では、単純な sleep 1 に最大26秒かかっています。
どのように利用メモリを削減すれば良いか
Disable fact gathering
8 ways to speed up your Ansible playbooksでも紹介されているように、gather factを無効にできれば良いのですが
実際に処理の中で ansible_* といったfactを利用している場合は適用できませんでした。
そこで、Ansibleのfact周りの互換性維持のオプションを変更することにしました。
Ansible2.5から、factの名前空間が変更に
Ansible 2.5: Traveling space and time にもあるように、Ansible2.5で ansible_* から ansible_facts.* に名前空間が変更になりました。
これはかなり大きな破壊的変更ですので、デフォルトでは ansible_facts.* に追加された変数を ansible_* として コピーするオプションが有効 になっています。
つまり、単純にfactによるメモリ利用が2倍になってしまっているわけです。
この互換性維持を目的とした変数のコピーを制御するオプションが inject_fact_as_vars です。
このオプションを無効にすることで、 ansible_facts.* のみにfactが保存されるようになります。
ansible.cfg
[defaults]
# default: True
inject_fact_as_vars = False
あとはこの状態ですべてのPlaybookが実行できるように、 git grep ansible_ などで検索して、ひとつずつ修正しました。
その他ハマったこと
Ansible 2.9.11を使っていたときに、このオプションを無効にしたところ、一部のmodule(set_factやinclude_vars)が正常に動作しない状態でした。
このバグについてはAnsible 2.9.16で修正されていたようなので、バージョンアップを行って解決しました。
Discussion