はじめに
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 までは以下の順序で検出処理が行われていました。
INTERPRETER_PYTHON_DISTRO_MAP
による検出- OS ディストリビューションとバージョンと Python インタープリターの対応表に基づく
- ansible 2.16.7 の場合はこちら
- たとえば RHEL 8 であれば
/usr/libexec/platform-python
- たとえば RHEL 8 であれば
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
のみです、python
や python3
コマンドのパスも通っていません。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
で明示的にインタープリターのパスを指定するのが良いかなと思います。