My RSS Reader

Description about Blog Author


Ansible Core 2.17以降とRHEL8 (及びRHEL8クローン)でPlaybookが実行できない話と解決方法

同じような環境を作ったり消したりしたい場合、仮想マシンや物理マシンに環境を展開する場合はAnsibleを使っています。 10年くらいでようやく、その習慣が染みつきました*1

環境構築自体は好きなほうなので、台数が何台になっても環境のセットアップは苦ではありませんでした。 しかしある時気が付くんですよ。手動でセットアップし続けるのは時間の無駄をしているなって。

私は仕事柄、何かの環境を作っては破壊し、また作り直しと言うことをよくやります。 その都度手動でセットアップしては効率が良くないですし、いい加減Ansibleを使い始めようと重い腰を上げてはや10年。 歳もとるわけです。

AnsibleがAnsibleとAnsible Coreに別れて以降、私は主にAnsible Coreを使って必要なモジュールだけを追加して利用していました。 新しいAnsible Coreがリリースされればそれに追従して、なるべく古いバージョンを維持するような使い方はしたくないので避けてきました。 それができたのは、これまでのAnsibleが古いバージョンのPythonが導入した環境でもAnsibleが動いたためです。

これまでなんらはまるとは無かったのですが、つい最近、レガシーOSに割と新しめのAnsible Coreを使ったらいろいろはまったので、情報共有がてらブログにまとめようと思いました。

そのレガシーOSというのがRHEL8やAlmaLinux 8といった、システムPythonが3.6な環境です。その他のOSでも古いバージョンを使う場合、同じような問題に当たる可能性があります。

たとえばAnsible Playbookで次のような処理、具体的に言うとdnfコマンドで特定のパッケージをインストールするにはPython3のdnfモジュールの導入が必要です。

tasks: - name: Ensure dependencies are installed ansible.builtin.dnf: name: - wget - tar - firewalld - python3-firewall - glibc-langpack-en - glibc-locale-source state: latest

RHEL 8.10などをターゲットマシンにする場合かつ、dnfコマンドを使ってソフトウェアのインストールを実行するロジックが必要な場合、python3-dnfパッケージがインストールされているのが最低要件です。

sudo dnf install python3-dnf

インストールが終わったので早速チェックモードでPlaybookを流すと、エラーが発生しました。

% ansible-playbook -i hosts.ini install_yugabytedb.yml -C

PLAY [Install YugabyteDB on Linux] ***************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************** ok: [192.168.56.12]

TASK [Ensure dependencies are installed] ********************************************************************************************************************************************* fatal: [192.168.56.12]: FAILED! => {“changed”: false, “msg”: “Could not import the dnf python module using /usr/bin/python3.9 (3.9.20 (main, Sep 26 2024, 20:59:47) [GCC 8.5.0 20210514 (Red Hat 8.5.0-22)]). Please install `python3-dnf` package or ensure you have specified the correct ansible_python_interpreter. (attempted [’/usr/libexec/platform-python’, ‘/usr/bin/python3’, ‘/usr/bin/python’])”, “results”: []}

PLAY RECAP *************************************************************************************************************************************************************************** 192.168.56.12 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

このブログのデザインレイアウトだとちょっと見づらいので、下にエラー部分だけ抜き出してみます。

fatal: [192.168.56.12]: FAILED! => {“changed”: false, “msg”: “Could not import the dnf python module using /usr/bin/python3.9 (3.9.20 (main, Sep 26 2024, 20:59:47) [GCC 8.5.0 20210514 (Red Hat 8.5.0-22)]). Please install `python3-dnf` package or ensure you have specified the correct ansible_python_interpreter. (attempted [’/usr/libexec/platform-python’, ‘/usr/bin/python3’, ‘/usr/bin/python’])”, “results”: []}

python3-dnfはインストールされましたが、/usr/bin/python3.9を呼び出していて、そのバージョンにdnfモジュールが入っていないというエラーが出ています。 インベントリファイルにansible_python_interpreter=autoなどと書いているのが良くなかったのかもしれませんが、これまでその書き方でも問題なかったのに、何で動かなくなったのでしょうか。

原因

調べた結果、原因はAnsible Core 2.17以降で古いバージョンのPythonをサポート対象外にされていたためです。 これまではまらなかったのは、Ansibleの実行環境としても、デプロイ先のマシンの環境としても古いバージョンのOSを使ってAnsibleを動かしていなかったためでした。

手元で動かすときは普段使いのMacにpipxを入れてその環境でAnsibleを動かしていましたし、手元の環境から直接アクセスできない場合はRHELやRHELクローンならバージョン9以降を使い、Ubuntuを使う場合は普段一番新しいLTSバージョンを使ってテストするので、こういった問題ではまることは無かったんですよね。 今回動かすアプリケーションの都合で古いバージョンを使ったために、この問題にはまったわけです。

Ansibleで構成管理を自動化するには、ベースとしてPython環境が必要になります。Ansibleを実行する環境とAnsibleで自動化するターゲット環境にPythonが入っている必要があります。私が使い始めたときはまだPython2やPython3でも、なんらかのバージョンが入っていればよしなに動いてくれていましたが、次のように直近のバージョンでレガシーバージョンのPythonがサポート終了しています。つまり今後のバージョンでは古いバージョンのPythonが入っていても動かないということです。ちなみにAnsible Core 2.18ではPython 3.10がサポート終了していますので、環境によってはここでもはまると思います。

  • Ansible Core 2.17

    • Drop Python 2.7 and 3.6 support for module execution
  • Ansible Core 2.18

    • Drop Python 3.10, and add Python 3.13 for controller code
    • Drop Python 3.7, and add Python 3.13 for target code

さらに、そのOSではPython用のDNFモジュールがPython3.6向けしか提供されていないという問題もあります(RHEL 8.xだったり、AlmaLinux 8.xだったりがそれに該当)。

  • EL8のpython3-dnfはPython 3.6向け
  • EL8のplatform-pythonはPython 3.6
  • EL8ではPython3.6-Python3.12までインストールできるが、python3-dnfはPython 3.6用しかない

現実的な解決方法

回避策としてはこの方法があります。

  1. RHEL8などでは例外処理で ansible.builtin.command でdnfベタ書きにする
  2. RHEL8でansible-core 2.16がインストールできるので、Ansible実行環境をRHEL8で用意する
  3. Python仮想環境を利用して古いバージョンのansible-coreを使う
  4. pipxで複数のバージョンのansible-coreをインストールして使い分ける(筆者の推奨)

一つ目はcommandとかを使ってインストールする方法です。ただこれだと必ず「変更」ステートになるので良くないんですよね。

tasks: - name: package install with dnf ansible.builtin.command: dnf install -y wget tar

二つ目は同じバージョンのレガシーOS上でAnsible環境をセットアップする方法です。コントローラー、ターゲットとも同じバージョンのAnsibleかつPythonが使われるので、この手の問題が発生しません。

三つ目はPythonの仮想環境でAnsibleを動かす方法です。pipxを使ってAnsibleを使い始める以前は、この方法を使っていました。 システムとは隔離されたパスでAnsibleを使うのでPython3をベースに使う最近のLinuxディストリビューションにおいて、安全にPythonベースのコードを実行できます。ただ、慣れが必要です。

四つ目は最近のAnsibleのドキュメントにも書かれているpipxを使う方法です。 pipxは過去に幾つかの記事をブログに書きましたが、Pythonで書かれたCLI(コマンドラインインターフェース)ツールを安全かつ簡単にインストール・実行できるツールです。 pyenvなどでPython仮想環境を使ってモジュールをインストールして…というのは慣れるまではなかなか難しいのですが、 pipxならあまりそういう難しさは意識せずに使えるので、今回のようなAnsibleの実行環境構築にpipxを使うのはおすすめだと思います。

pipxを使ったansible-coreの共存

pipxは次のような感じで、最新もしくは特定のバージョンのansible-coreをインストールできます。

pipx install ansible-core pipx install ansible-core==2.18.6

さらに、バイナリーにサフィックスをつけてインストールできるようです。 これにより、一番新しいバージョンはそのままインストールして、環境によってバージョンを使い分けることができるようになります。

$ pipx install “ansible-core==2.16.14” –suffix “-216”

$ ansible-216 –version ansible [core 2.16.14] config file = None configured module search path = [’/Users/ytooyama/.ansible/plugins/modules’, ‘/usr/share/ansible/plugins/modules’] ansible python module location = /Users/ytooyama/.local/pipx/venvs/ansible-core-216/lib/python3.13/site-packages/ansible ansible collection location = /Users/ytooyama/.ansible/collections:/usr/share/ansible/collections executable location = /Users/ytooyama/.local/bin/ansible-216 python version = 3.13.3 (main, Apr 8 2025, 13:54:08) [Clang 17.0.0 (clang-1700.0.13.3)] (/Users/ytooyama/.local/pipx/venvs/ansible-core-216/bin/python) jinja version = 3.1.6 libyaml = True

実行してみます。指定したバージョンではエラーにならなくなったので、大丈夫そうです。

$ ansible-playbook-216 -i hosts.ini install_yugabytedb.yml -C PLAY [Install YugabyteDB on Linux] ***************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************** ok: [192.168.56.12]

TASK [Ensure dependencies are installed] ********************************************************************************************************************************************* changed: [192.168.56.12]

TASK [Create install directory] ****************************************************************************************************************************************************** changed: [192.168.56.12]

TASK [Download YugabyteDB tarball] *************************************************************************************************************************************************** changed: [192.168.56.12] …

-Cをつけてチェックモードで実行していますが、-Cオプションを外せば実際にデプロイ処理が行われます。 普段は最新版のAnsible Coreを使い、レガシー環境の利用が必要なときはこの方法で古いバージョンであるAnsible Core 2.16.14を使えば良さそうです*2

一番良いのはターゲットのOSはRHEL9以上にすることでしょうか。できるならその方が良いです。

ちなみに

この方法でインストールすると、次のような感じで全てのコマンドに-216が付与されたコマンドが使えるようになります。 Python製のCLIツールを使うとき、pipxは使いやすくてお勧めです。

% pipx list venvs are in /Users/ytooyama/.local/pipx/venvs apps are exposed on your $PATH at /Users/ytooyama/.local/bin manual pages are exposed at /Users/ytooyama/.local/share/man package ansible-core 2.18.6, installed using Python 3.13.3 - ansible - ansible-config - ansible-console - ansible-doc - ansible-galaxy - ansible-inventory - ansible-playbook - ansible-pull - ansible-test - ansible-vault package ansible-core 2.16.14 (ansible-core-216), installed using Python 3.13.3 - ansible-216 - ansible-config-216 - ansible-connection-216 - ansible-console-216 - ansible-doc-216 - ansible-galaxy-216 - ansible-inventory-216 - ansible-playbook-216 - ansible-pull-216 - ansible-test-216 - ansible-vault-216 package ansible-lint 25.4.0, installed using Python 3.13.3 - ansible-lint

見た情報:

*1:といいつつ、いまだにAnsibleのエラーの解読は苦手です

*2:いつか古いバージョンがダウンロードできなくなる可能性もあるので、できるだけ早くサポートされるバージョンに移ると良いでしょう

[source]