てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] ansible-core 2.17.0 で Linux ディストリビューションに基づくインタープリター検出機能がなくなった

はじめに

Ansible では、マネージドノード(自動化対象)が Linux の場合は、マネージドノード側の Python を利用します。どの Python インタープリターを利用するかは、設定項目 INTERPRETER_PYTHON (変数だと ansible_python_interpreter)で指定できます。

明示的に指定しない場合に備えて、自動検出する仕組みが複数ああります。このうち INTERPRETER_PYTHON_DISTRO_MAP による検出が、ansible-core 2.17.0 でなくなりました。

(そもそも)Python インタープリター自動検出の仕組み

Python インタープリターを明示的に指定しない場合は、Ansible 2.8 で導入された Interpreter Discovery (参考)という機能により、自動的に検出されます。

Interpreter Discovery では、ansible-core 2.16 までは以下の順序で検出処理が行われていました。

  1. INTERPRETER_PYTHON_DISTRO_MAP による検出
  2. INTERPRETER_PYTHON_FALLBACK による検出 (1で決まらない場合)

ansible-core 2.17.0 で INTERPRETER_PYTHON_DISTRO_MAP の廃止

ansible-core 2.17.0 では、前述の 2つの検出の仕組みのうち、1 の INTERPRETER_PYTHON_DISTRO_MAP による検出が廃止されました。

ansible-core 2.17.0 の Changelog では以下のように記載されています(関連PR)。

Interpreter Discovery - Remove hardcoded references to specific python interpreters to use for certain distro versions, and modify logic for python3 to become the default.

そもそも、明示的にインタープリターを指定していれば関係のない話ですが、この検出に頼っていた場合に困るケースがあります。

困るケースを検証

RHEL 8 を minimal でインストールした場合は、/usr/libexec/platform-python のみです、pythonpython3 コマンドのパスも通っていません。ansible-core 2.17.0 でこのサーバーを対象に実行した場合、最終的に Python インタープリターが見つからないエラーになってしまいます。

これを実際に試しています。

検出された Python インタープリターが分かりやすく表示されるため、ad-hoc コマンド(ansible コマンド)で ansible.builtin.ping モジュールを利用する、というシンプルな方法で検証します。

%  ansible -i inventory.ini rhel84 -m ping 
[WARNING]: No python interpreters found for host rhel84 (tried ['python3.12',
'python3.11', 'python3.10', 'python3.9', 'python3.8', 'python3.7',
'/usr/bin/python3', 'python3'])
rhel84 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "module_stderr": "Shared connection to 192.168.1.99 closed.\r\n",
    "module_stdout": "/bin/sh: /usr/bin/python3: No such file or directory\r\n",
    "msg": "The module failed to execute correctly, you probably need to set the interpreter.\nSee stdout/stderr for the exact error",
    "rc": 127
}

/bin/sh: /usr/bin/python3: No such file or directory というエラーが表示されました。

INTERPRETER_PYTHON_DISTRO_MAP による検出もなく、INTERPRETER_PYTHON_FALLBACK によるフォールバックでも見つからなかったという現象です。

(tried ['python3.12','python3.11', 'python3.10', 'python3.9', 'python3.8', 'python3.7','/usr/bin/python3', 'python3'])

でフォールバックを試みたリストが示されています。

そもそも ansible-core 2.17 系はマネージドノード側は Python 3.7 以上のサポートです。そのため、仮に Python 3.6 である /usr/libexec/platform-python が見つかったり明示指定してもエラーになります(参考)。

そのため、対策方針としては、マネージドノード側に別途 Python 3.7 以上をインストールして作成した環境のパスを INTERPRETER_PYTHON で明示的に指定するのが良いです。

(仮に Python 3.6 がサポート対象だとしても /usr/libexec/platform-python 以外の環境を別途作ったほうが環境がきれいに保てると思います)

参考 ansible-core 2.16 系の場合

比較のために ansible-core 2.16 系で同じ対象に実行した結果を載せておきます。これは正常です。

INTERPRETER_PYTHON_DISTRO_MAP により、/usr/libexec/platform-python が見つかっています。

% ansible -i inventory.ini rhel84 -m ping                                                                     
rhel84 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

おわりに

ansible-core では 2.17.0 では、マネージドノードで Python 2 のサポートがなくなったり、Python 3系のサポートも 3.7 に引き上がったりしました。

自動検出の仕組みの一部廃止との組み合わせによって、内容含め、Python インタープリター周りのつまずきが出てくるかもしれません。

利用する ansible のバージョンとサポートする Python バージョンを確認しつつ、INTERPRETER_PYTHON で明示的にインタープリターのパスを指定するのが良いかなと思います。

関連

tekunabe.hatenablog.jp

tekunabe.hatenablog.jp