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