AAPやAWXでジョブ実行に必要なExecution Environments(EE)を作るために通常はAnsible Builderを使ってコンテナイメージをビルドするが、要件を満たせばDockerfileを直接書いて自前でビルドしても動くのでは…と思ったので確認してみた。
結論としては、以下が入っていれば最低限動作した。
- Ansible Core
- プラス必要なAnsible Collection
- Ansible Runner
- SSHクライアント
- sshpass (パスワード認証の場合)
Ansible BuilderではRHEL系コンテナしか使えない(夏にv3対応したときにいろいろ試したがRHEL系以外はダメだった)が、お試しでDebian系…もいいかと思ったけど、せっかくなのでAnsible利用時にあまり使われず(個人の感想)、イメージサイズがより小さいAlpine Linuxでビルドして確認。
Dockerfile
2024.01.08時点で公開されてるAlpine 3.19.0のイメージをベースにするなら以下の内容でビルドすればOK
(実行確認用の追加パッケージ有)
FROM alpine:3.19.0 RUN apk add ansible-core py3-jmespath py3-pip openssh-client sshpass && \ ansible-galaxy collection install community.general && \ pip install ansible-runner --break-system-packages
Alpineのパッケージでansible-core
をインストールすると、Alpine 3.19の場合はcore 2.16.1がインストールされるのでこれを利用。
(ansible
パッケージもあり、こちらを使えばオフィシャルのコレクションは多分すべて入る。pip install ansible
と同等と思われる)
Ansbile Runnerは必須だがAlpineのパッケージでは提供されないため、pip
を使用する。その際、venvを使わずシステムに直接インストールしようとするとパッケージ管理の競合対策のためエラーになるが、コンテナを使った限定された環境なので--break-system-packages
オプションを付加する。
SSHクライアントも(自動化で標準的に使用するSSHコネクションプラグインを使用するのであれば)必要。Alpineのコンテナにはデフォルトではssh
が無いため、追加インストールしないと下記エラーが発生する。
The command was not found or was not executable: ssh-agent.
また、SSH鍵認証でなく、パスワード認証を使用する場合はsshpass
も必要。無いと下記エラーになる。
"to use the 'ssh' connection type with passwords or pkcs11_provider, you must install the sshpass program"
あとは実行例としてjson_query
を試すために、APKパッケージ版jmespath
とcommunity.general
コレクションを追加している。
使ったplaybookは基本的にこんな感じ。
※ localhost
実行のため、これとあとリモートに接続に行く適当なジョブを実行
これでビルドしたイメージをAAP/AWXでそれぞれ実行環境として試したが、ジョブの実行は問題なかった。
イメージサイズ比較
※ これはビルドしただけで動作は未確認
Ansible Builderを使ってrockylinux:9.3-minimalベースに前述Dockerfile同様jmespathとcommunity.generalを入れたイメージサイズと比較。
また、Ansible Coreもpip
で入れた場合とも比較。これも若干増えた。
apk add
版: 127MBpip
版: 148MB- Ansible Builder版(rockylinux:9.3-minimalベース): 280MB
前述のパッケージ版をpip
版に置き換えたこの場合のDockerfileは以下の通り。
FROM alpine:3.19.0 RUN apk add py3-pip openssh-client sshpass && \ pip install ansible-runner ansible-core==2.16.1 jmespath --break-system-packages && \ ansible-galaxy collection install community.general
Ansible Builder用execution-environment.yml
ファイルは以下の通り。
--- version: 3 dependencies: ansible_core: package_pip: ansible-core==2.16.1 ansible_runner: package_pip: ansible-runner galaxy: collections: - community.general python: - jmespath system: - sshpass python_interpreter: python_path: /usr/bin/python3.11 images: base_image: name: docker.io/library/rockylinux:9.3-minimal options: package_manager_path: /usr/bin/microdnf # required (when use rocky/alma) additional_build_steps: prepend_base: - RUN microdnf install python3.11 -y # for alma/rocky minimal
詳しくは下記参照
--break-system-packages
オプション
何をOSのパッケージ管理(apk
)で入れて何をPythonのパッケージ管理(pip
)で入れるかは、あまりごちゃごちゃさせると文字通り競合するかもしれないので、どちらかに寄せるのが良いと思う。
この辺りは深く検証してないので都度対応かな。
で、運用とかで使える?
自己責任で(ry
公式ドキュメントで「Ansible Builderを使わない場合はこんな感じで~」的な記載を見つけられず表技か裏技かは微妙なことをしてるため、あくまで「動かしたいplaybookがあってそれが動く専用のEEのイメージを用意する」のであれば手段の一つとしてありかもしれない。特に「求めているコンテナイメージの完成形はわかっているのに、Ansible Builder(というかexecution-environment.yml
)でどう実装すればわからない場合とか。
あとはAnsible Builderを使うとイメージサイズが大きすぎて困る…みたいなときは良いかもね。
今回はsshとjmespathを追加インストールしてるけど、EEに必要なパッケージ類は実行するplaybookで使用しているモジュール・プラグイン次第なので、必要に応じて追加する。(不足していれば実行時にエラーになるので、メッセージを頼りに不足分を補う地道な作業になるはず。ってこれはAnsible Builderを使っていても変わらないと思う)
あと一つ発見だったのは、Alpineのパッケージ管理はAnsibleインストールできるしバージョンも最新にかなり近いものを追従してるという点。
根本的におかしいとか、こうすればもっといいとか、ここに公式情報あるとかあれば、ぜひ教えてください。