🐷

Ansibleで互換性を維持するためのoptionを無効にしたら、20%早くなった

2022/05/19に公開

日本語での記事を探しても出てこなかったので書いてみます。

やったこと

  1. Ansibleのバージョンを2.9.16以上にする。

  2. ansible.cfg で Ansible 2.5以前との互換性維持のオプションを無効にする

[defaults]
# default: True
inject_fact_as_vars = False
  1. 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