はじめに
Automation Automates 2023 Japan での AAP のロードマップの話の中で、「Containerized AAP」という言葉がありました。その後、AAP 2.4 内で「Technical Preview」という扱いで提供が始まりました。
どんな感じか気になりつつ、試せていなかったので試してみました。
デプロイそのもののほか、postinstall 処理(ライセンス自動適用、プロジェクトの設定投入)も試ました。インストール処理の中身や、自動起動、ポート開放などの仕組みにいて気になったこともあったため、ついでに調査しました。
手順については、公式ドキュメントや、先人のブログを参考にさせていただきました。ありがとうございます!
- コンテナ化されたAAPのContainerized Ansible Automation Platform (tech preview)を試してみた(AAP 2.4) - zaki work log
- コンテナー化された Ansible Automation Platform のインストールガイド | Red Hat Product Documentation
なお、将来的に Containerized AAP が GA になった場合、現在から大小さまざまな変更が入ると思います。本記事はあくまでも AAP 2.4 時点で Technical Preview のものを Technical Preview として扱い、一時的な環境で試してみるだけです。なので、GA になったらあまり意味がない内容になります。
まとめ
長いので先にポイントをまとておきます。
- podman でデプロイする方式、ルートレス
- デプロイ後にライセンスの適用や設定投入もできる
- 各コンテナはユーザーレベルの systemd 経由で起動
■ 環境・要件
今回は以下の環境、要件です。
- 環境
- RHEL 9.4 (minimal)
- サブスクリプション適用済み
- ホスト名設定済み
- パスワード入力で
sudo
できる非 root ユーザーを利用(今回はadmin
) - podman 4.9.4-rhel (インストール Playbook 実行中にインストールされる)
- オンライン版インストーラー(バンドル版ではないほう)
ansible-automation-platform-containerized-setup-bundle-2.4-2-x86_64.tar.gz
- 最終更新日は
2024-01-16
- 主なコレクション(インストーラーに同梱)
ansible.containerized_installer
1.3.3ansible.controller
4.5.0infra.controller_configuration
2.6.0
- 要件
- Autmation Controller のみデプロイ(実際は Automation Hub や EDA Controller もデプロイ可能)
- 作業マシン自身にデプロイ
- ライセンス適用も自動化
- Automation Controller の事後設定も自動化(postinstall)
- Autmation Controller のみデプロイ(実際は Automation Hub や EDA Controller もデプロイ可能)
■ インストール手順
私の環境、要件でインストールした手順です。
準備
パッケージを一通りアップデートします。
$ sudo dnf update '*' -y ...(略)... $ cat /etc/redhat-release Red Hat Enterprise Linux release 9.4 (Plow)
リポジトリのリストを表示し、ドキュメントに記載の appstream
と baseos
があることを確認します。
$ dnf repolist Not root, Subscription Management repositories not updated repo id repo name rhel-9-for-x86_64-appstream-rpms Red Hat Enterprise Linux 9 for x86_64 - AppStream (RPMs) rhel-9-for-x86_64-baseos-rpms Red Hat Enterprise Linux 9 for x86_64 - BaseOS (RPMs)
デプロイ対象マシンのホスト名を名前解決可能な状態にしておきます。
今回は今作業している(インストーラーを実行する)マシン自身をデプロイ対象としますので、作業マシンのホスト名 rhel9-aap24c
を 192.168.1.139
で名前解決できるようにしました。
何が起こるか見たかったこともあり、ドキュメントとは異なり /etc/hosts
で設定しました。あくまで検証目的であり、公式ドキュメントに載っている方法ではありません。
ansible-core のインストール
イントールに必要な ansible-core などをインストールします。
$ sudo dnf install -y ansible-core wget git rsync ...(略)... Complete!
これまであった、VM に RPM でインストールする方式では、インストールスクリプトの insstall.sh
の処理の中で、(なければ)ansible がインストールされ、具体的な処理が書かれた Playbook を実行するという流れでした。
一方で、Containerized AAP の場合は、Playbook を直接実行するかたちなので予め ansible-core のインストールが必要です。
他に指定されている wget
や git
などは、Playbook が依存しているからなのだと思います。git
でいうと、postinstall のための定義ファイルを git clone する時に使うようです。
なお、ここまで作業しても podman
はインストールされていません。
$ podman bash: podman: command not found $ rpm -qa | grep podman $
インストーラーのダウンロード
ダウンロードページ(要ログイン)にブラウザでアクセスして、Tech Preview: Ansible Automation Platform 2.4 Containerized Setup
をダウンロードします。
今回はバンドル版を利用しないので、末尾に Bundle
が付かないほうです。最終更新日は 2024-01-16
となっていました。
ダウンロードした ansible-automation-platform-containerized-setup-2.4-2.tar.gz
を作業マシンにコピーしておきます。
作業マシンで解凍して、作成されたディレクトリに移動します。
$ tar xzf ansible-automation-platform-containerized-setup-2.4-2.tar.gz
$ cd ansible-automation-platform-containerized-setup-2.4-2
解凍した直下のファイル、ディレクトリは以下のとおりです。
ファイル・ディレクトリ名 | 説明 |
---|---|
collections ディレクトリ |
インストーラーに同梱しているコレクションの親ディレクトリ。イントール用の Playbook がこの配下の ansible.containerized_installer コレクション内にある。後述の ansible.cfg の collections_path がこのディレクトリを指している。 |
ansible.cfg |
collections_path 等の設定 |
inventory |
インストール上のホスト、設定の定義 |
README.md |
インストール上の設定の変数の説明 |
inventory (インストール設定ファイル)の編集
これまでと同様、インストール上のさまざまな設定を inventory
ファイルに指定します。普段と同じように、パスワード類は暗号化するなどしてセキュリティを高めることもできます。
rhel9-aap24c
は作業マシン兼インストール先マシンです。
[automationcontroller] # Aumation Controller のデプロイ先を指定 # 実際は作業マシン自身 # https の待ち受けポートを 443 に指定(デフォルト8443) rhel9-aap24c ansible_connection=local nginx_https_port=443 [database] # DB も同じホストのコンテナとしてデプロイする rhel9-aap24c ansible_connection=local [all:vars] # DB の認証情報 postgresql_admin_username=postgres postgresql_admin_password=<DBパスワード> # オンライン版インストーラーの場合 registry.redhat.io からイメージを pull するので必要な認証情報を指定 registry_username=<Red Hat アカウントのユーザー名> registry_password=<Red Hat アカウントのパスワード> # Automation Controller の Web UI admin パスワード controller_admin_password=<Automation Controller adminパスワード> # Automation Controller から DB への接続情報 controller_pg_host=rhel9-aap24c controller_pg_password=<DBパスワード> # デプロイ後に設定流し込み処理(postinstall)をする # postinstall の有効化(デフォルトは無効) controller_postinstall=true # マニフェストファイルのパス controller_license_file=/home/admin/cac/manifest_sakana-trial-5nodes_20240913T050813Z.zip # 設定流し込みに利用する定義ファイルを格納したディレクトリ controller_postinstall_dir=/home/admin/cac # 状況確認感覚のチューニング(トラブルシューティングで後述) controller_postinstall_async_delay=2
automationeda
や automationhub
グループはグループ定義自体をしない形にしてみました。この影響で、後述の Playbook 実行時に警告が表示されます。気になる場合は、グループに定義は残しつつ所属ホストなしにするとよいと思います。
README.md
にさまざまな変数の説明があります。上記の inventory
で利用している変数のうち、いくつか以下で説明します。
デプロイ処理関連
Automation Controller の https の待ち受けポートとして nginx_https_port
変数で 443
を指定しています。これは、妥当性はさておき、一般ユーザーでデプロイしたらどうなるんだろうという好奇心で試したものです。実際はこれでいけました。インストール処理の中でカーネルパラメーター net.ipv4.ip_unprivileged_port_start
が調整されるためです。
postintall 関連の設定
controller_postinstall
と true
に指定して、postinstall(デプロイ後の設定流し込み)機能を有効化していました。
controller_license_file
は適用したいマニフェストファイルのパスです。今回はトライアルライセンスから作成しました。試した限りマニフェストファイルの適用だけであれば controller_postinstall
はデフォルトの false
のままでも大丈夫でした。一方、controller_postinstall
を true
とした場合は、controller_license_file
の指定がセットで必要になります。
設定に利用する変数ファイル群が git 上にある場合は、hub_postinstall_repo_url
で指定します。
今回は、変数ファイルを作業マシンに直接配置したので、controller_postinstall_dir
のみの指定です。ここで指定したディレクトリ配下にある *.yml
や *.yaml
ファイルを一式読み込みます。拡張子以外のファイル名は何でもよいです。今回は、controller.yml
というファイル名で以下の内容のモノを作成して、controller_postinstall_dir
で指定したディレクトリ配下に置きました。
--- controller_projects: - name: My Project organization: Default scm_type: git scm_url: https://github.com/akira6592/tower-sample-nw scm_branch: main scm_delete_on_update: false scm_update_on_launch: true scm_clean: true
今回はとにかく動くことを確認したかったので、プロジェクトを1つ作成するのみとしました。postinstall の機能自体は非常に興味深いので別途深掘りしたいと思います。
なお、この設定流し込みには infra.controller_configuration.dipatch
ロールが利用されます。変数ファイルの書きっぷりは以下のページが参考になります。
- Seeding Ansible Automation Platform Content At Installation Time
- aap-cac/controller at main · ffirg/aap-cac · GitHub
インストール Playbook の実行
$ ansible-playbook -i inventory ansible.containerized_installer.install -K BECOME password: (作業ユーザーのパスワードを入力)
(オプション -K
でbecomeパスワードを対話的に入力するの手間な時は ansible_become_password
を指定するなど)
8分位で終わりました。aap_install.log
にログが記録さます。
なお、Playbook の指定はカレントディレクトリから見たファイル名ではなく、ansible.containerized_installer
コレクション内の Playbook install
を指しています。ansible.containerized_installer
コレクションはインストーラーに同梱されていいて、Playbook の実体は <解凍ディレクトリ>/collections/ansible_collections/ansible/containerized_installer/playbooks/install.yml
です。
ansible.cfg
で以下のように collections_path
が指定されているため、 ansible.containerized_installer
コレクションを認識できるようになっています。
[defaults] collections_path = ./collections inventory = ./inventory log_path = ./aap_install.log
Playbook のファイル名の補完ができなくて少し不便ですが、ansible-core 2.11 からこのようにコレクション内の Playbook を呼べるようになっています。
なお、2023年月時点の公式ブログでは、export ANSIBLE_COLLECTIONS_PATH=/full-path-to-installer/collections
でコレクションがあるパスを指定していますが、上記の ansible.cfg
で ansible-playbook
コマンドを実行する分には export
不要です。
動作確認
無事にジョブテンプレートが実行できました。
Automation Controller のバージョンは、4.5.11 でした。ここは変動するかもしれません。
postinstall の処理で指定したプロジェクト「My Project」も追加されて、同期も成功していました。
■ インストール時のトラブルシューティング
本記事の手順はあたかも最初からうまくいったように書きましたが、実際は試行錯誤がありました。その中で出会った事象や対処などをまとめます。
あくまで今回利用したバージョンですので、今後のバージョンでは再現性がないかもしれません。
トラシュー1: ジョブテンプレートを実行しても「保留中」のままになる
インストールの Playbook が正常に終了した後、試しに Dome Job Template を実行すると「保留中」のまま先に進まないことがありました。
他にも、インストール Playbook を実行中、postinstall の処理にジョブが起動する処理(プロジェクトの設定など)があると、そのジョブが保留中のままタイムアウトとなり、タスク infra.controller_configuration.projects : Managing Projects | Wait for finish the projects management
でエラーになることがありました。
原因: インベントリで localhost
を指定していたため
複数のケースが考えられますが、今回の場合は、EE を実行するための receptor
コンテナが起動していなかったためでした。
インストール Playbook 実行後の podman ps
の結果は以下のとおり receptor
と automation-controller-task
がありませんでした。
$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f728f9c17261 registry.redhat.io/rhel8/postgresql-13:latest run-postgresql 6 minutes ago Up 5 minutes postgresql 54a15d3dfdd7 registry.redhat.io/rhel8/redis-6:latest run-redis 5 minutes ago Up 5 minutes redis f7e9f4709730 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 4 minutes ago Up About a minute automation-controller-rsyslog f0b5d5f93ae5 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 4 minutes ago Up About a minute automation-controller-web
podman ps -a
で調べてみると receptor
と automation-controller-task
はそれぞれ終了していました。
$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f728f9c17261 registry.redhat.io/rhel8/postgresql-13:latest run-postgresql 8 minutes ago Up 8 minutes postgresql 54a15d3dfdd7 registry.redhat.io/rhel8/redis-6:latest run-redis 8 minutes ago Up 8 minutes redis 12b94e181d9b registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel8:latest /usr/bin/receptor... 7 minutes ago Exited (1) 7 minutes ago receptor f7e9f4709730 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 7 minutes ago Up 4 minutes automation-controller-rsyslog 12dbc9d8db3f registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 7 minutes ago Exited (0) 3 minutes ago automation-controller-task f0b5d5f93ae5 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 7 minutes ago Up 3 minutes automation-controller-web
で、まず receptor
がなんで異常終了したんだろうと、podman logs receptor
でログを確認したら Error: node ID "localhost" is reserved
とありました。
$ podman logs receptor Error: node ID "localhost" is reserved
どうやら、プログラムとしての receptor の処理として「localhost
は予約されているため、node の id に指定できない」ということのようでした。
遡ってみると、試しに inventory
で automationcontroller
グループのホストに localhost
を指定したときがありました。この localhost
という値が巡り巡って ansible.containerized_installer.receptor
ロール内のテンプレート receptor.conf.j2
で、node
の id
として利用され、先述のエラーとなっていたようです。
# roles/receptor/templates/receptor.conf.j2 --- - node: id: {{ _receptor_hostname }} # ...(略)...
もう一つのコンテナ、podman logs automation-controller-task
のほうは、詳細を追えませんでしたが、おそらく receptor
のエラーとも関係があるのだと思います。
エラー抜粋
$ podman logs automation-controller-task ...(略)... Traceback (most recent call last): File "/usr/bin/awx-manage", line 8, in <module> sys.exit(manage()) File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/__init__.py", line 175, in manage execute_from_command_line(sys.argv) File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/core/management/base.py", line 412, in run_from_argv self.execute(*args, **cmd_options) File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/core/management/base.py", line 458, in execute output = self.handle(*args, **options) File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/main/management/commands/run_dispatcher.py", line 68, in handle consumer.run() File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/main/dispatch/worker/base.py", line 236, in run self.worker.on_start() File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/main/dispatch/worker/task.py", line 141, in on_start dispatch_startup() File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/main/tasks/system.py", line 120, in dispatch_startup cluster_node_heartbeat() File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/main/tasks/system.py", line 578, in cluster_node_heartbeat inspect_execution_and_hop_nodes(instance_list) File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/main/tasks/system.py", line 517, in inspect_execution_and_hop_nodes mesh_status = ctl.simple_command('status') File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/receptorctl/socket_interface.py", line 81, in simple_command self.connect() File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/receptorctl/socket_interface.py", line 99, in connect raise ValueError(f"Socket path does not exist: {path}") ValueError: Socket path does not exist: /run/receptor/receptor.sock ...(略)...
対処: localhost
以外を指定
もともとちょっと意地悪感覚で指定した inventory
の automationcontroller
グループのホストに localhost
を、実際のホスト名(名前解決可)に変更して再度インストール Playbook を実行しました。
・・一筋縄ではいかず以下のエラーになりました。変なタイミングでホスト名を変更したため、整合性が取れなくなったのだと思います。
TASK [ansible.containerized_installer.automationcontroller : Wait for the Controller API to te ready] *** fatal: [rhel9-aap24c]: FAILED! => {"changed": false, "elapsed": 0, "msg": "Status code was -1 and not [200]: Request failed: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'rhel9-aap24c'. (_ssl.c:1129)>", "redirected": false, "status": -1, "url": "https://rhel9-aap24c:443/api/v2/ping/"}
詳細を調べる気力がなかったので、一度アンインストール Playbook を実行してから、インストール Playbook を実行しました。
完了の podman ps
は以下のとおりです。
$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1bdb7ba2d638 registry.redhat.io/rhel8/postgresql-13:latest run-postgresql 4 minutes ago Up 4 minutes postgresql 5db357812714 registry.redhat.io/rhel8/redis-6:latest run-redis 4 minutes ago Up 4 minutes redis 2c9dfbbeb62b registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel8:latest /usr/bin/receptor... 4 minutes ago Up 4 minutes receptor 3beee138c0e6 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 3 minutes ago Up 34 seconds automation-controller-rsyslog fe2516aff573 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 3 minutes ago Up 31 seconds automation-controller-task 15133bf168e8 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 3 minutes ago Up 20 seconds automation-controller-web
receptor
も automation-controller-task
も起動しました。
これでジョブが正常に実行できるようになりました。postinstall でプロジェクトの設定をするようにしている場合も、無事に終了するようになりました。
トラシュー2: プロジェクトの設定がタイムアウトエラー
今回は postinstall の処理で、プロジェクト設定の流し込みを含めていますが、以下のエラーになることがありました。
TASK [infra.controller_configuration.projects : Managing Projects | Wait for finish the projects management] ************************************ FAILED - RETRYING: [rhel9-aap24c]: Managing Projects | Wait for finish the projects management (30 retries left). FAILED - RETRYING: [rhel9-aap24c]: Managing Projects | Wait for finish the projects management (29 retries left). FAILED - RETRYING: [rhel9-aap24c]: Managing Projects | Wait for finish the projects management (28 retries left). ...(略)... FAILED - RETRYING: [rhel9-aap24c]: Managing Projects | Wait for finish the projects management (2 retries left). FAILED - RETRYING: [rhel9-aap24c]: Managing Projects | Wait for finish the projects management (1 retries left). failed: [rhel9-aap24c] (item=Create/Update Project My Project | Wait for finish the project creation) => {"__projects_job_async_results_item": {"__controller_project_item": {"name": "My Project", "organization": "Default", "scm_branch": "main", "scm_clean": true, "scm_delete_on_update": false, "scm_type": "git", "scm_update_on_launch": true, "scm_url": "https://github.com/akira6592/tower-sample-nw"}, "ansible_job_id": "j210680799387.309524", "ansible_loop_var": "__controller_project_item", "changed": false, "failed": 0, "finished": 0, "results_file": "/home/admin/.ansible_async/j210680799387.309524", "started": 1}, "ansible_job_id": "j210680799387.309524", "ansible_loop_var": "__projects_job_async_results_item", "attempts": 30, "changed": false, "finished": 0, "results_file": "/home/admin/.ansible_async/j210680799387.309524", "started": 1, "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
あれれと思って、Automation Controller の GUI にログインして確認すると、プロジェクトは正常に設定されていた、という状況でした。
原因: プロジェクト同期処理が間に合わなかった
設定の流し込みには、infra.controller_configuration.dipatch
ロールが利用されます。この際、非同期で処理します。デフォルトでは 1秒間隔で状況確認して、30回リトライして処理が完了しなければエラーになります。
何度かインストールを試していると、デフォルトではうまくいったりいかなかったりしました。
プロジェクトについては、ただ設定するだけなく、設定直後に同期処理(git clone)が実行されるので、他の設定項目よりは時間がかかる傾向があるかもしれません。たまたまプロジェクトで試して出会えてよかったです。
なお、前述の「トラシュー1: ジョブテンプレートを実行しても「保留中」のままになる」の原因の一つである、コンテナ receptor
がない場合もこの事象が発生します。この場合は、プロジェクト同期処理に必要なコンテナがないことになりますので、インストールを何回実行しても毎回タイムアウトになります。
対処: チューニング
コンテナ receptor
があるのにタイムアウトになっている場合は、状況確認の間隔やリトライ回数を調整します。
inventory
内の以下の変数で調整できます。
変数名 | デフォルト値 | 説明 |
---|---|---|
controller_postinstall_async_delay |
1 | 状態確認の間隔(秒) |
controller_postinstall_async_retries |
30 | リトライ回数 |
公式ドキュメントにも本件についての記載があります。変数名が controller_configuration_async_*
なので微妙に違いますが挙動としては同じようです。README.md
に載ってる変数名だと controller_postinstall_async_*
です。
今回は、controller_postinstall_async_delay
を 2
に指定して、再度インストール Playbook を実行しました。
トラシュー3: 接続確認タスク Wait for the Web port to be reachable
でエラーになる
一度インストールが完了した後、変数 nginx_https_port
で nginx の listen ポートを変更し、再度 Playbook を実行すると、Automation Controller へのライセンス投入前の接続確認で、以下のエラーになってしまいました。
TASK [ansible.containerized_installer.automationcontroller : Wait for the Web port to be reachable] ************************** fatal: [rhel9-aap24c]: FAILED! => {"changed": false, "elapsed": 300, "msg": "Timeout when waiting for 127.0.0.1:443"}
処理の中身としては、ansible.containerized_installer.automationcontroller
ロール内のタスクファイル license.yml
にあるタスクで、ansible.builtin.wait
モジュールが使用されています。
なお、このタスクは controller_license_file
が定義されているときだけ実行されます。そのため、マニフェストファイルを指定していない場合はこのエラーは発生しません。
原因: listen ポートの変更が反映されないため
変数 nginx_https_port
の値で nginx の設定ファイルを変更した後、コンテナ automation-controller-web
を再起動していないためのようです。
以下詳細です。
ansible.containerized_installer.automationcontroller
ロール内の containers.yml
にあるタスク Create the automation controller web container
で nginx の設定ファイルを生成します。そのタスクに notify: Restart controller web
指定されています。
ハンドラー Restart controller web
では、ansible.builtin.systemd
モジュールを利用して、サービス automation-controller-web.service
を再起動します。結果的にコンテナ automation-controller-web
が再起動されて、変更された nginx の設定ファイルも反映されます。
ここだけ見るとうまくいくように見えますが、再起動のハンドラーが起動する前に、接続確認のタスクがあるため、listen ポート変更すると正常に接続確認できなくなってしまいます。
「一通りタスクが終わった後に、ハンドラーを起動する」という順番の仕様が考慮されていないように見えます。
対処: 一度アンインストール(暫定)
少々大げさですが、一度アンインストールしてから、再度インストールしました。
$ ansible-playbook -i inventory ansible.containerized_installer.uninstall -K ...(略)... $ ansible-playbook -i inventory ansible.containerized_installer.install -K ...(略)...
他の方法として、接続確認のタスク Wait for the Web port to be reachable
の実行中に、手動でサービス automation-controller-web.service
を再起動する方法も考えらますが、タイミング勝負のため少々アクション要素があります。
なお、この事象はあくまで今回検証した ansible.containerized_installer
コレクション 1.3.3
での事象のため、今後修正されるかもしれません。
その他: アンインストールしてもカーネルパラメーターの変更が残る
トラブルシューティングではないですが、気が付いたことが一点。
インストーラーが、カーネルパラメーター net.ipv4.ip_unprivileged_port_start
を調整する際 /etc/sysctl.conf
に、
net.ipv4.ip_unprivileged_port_start=443
のように記載されますが、アンインストールの Playbook を実行しても残ります。インストール前の値がどうだったか保存しておく術がないので、しょうがないのかなと思います。
もしかしたら他にもアンインストールで、設定が残るものもあるかもしれません。
■ 調べたこと
インストール処理の中身や、自動起動、ポート開放で気になったことをいくつか調べたので、まとめておきます。
全体
podman ps
の結果は以下の通りです。概ねコンテナ名で役割がわかりそうです。
$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3910331f6865 registry.redhat.io/rhel8/postgresql-13:latest run-postgresql 4 hours ago Up 4 hours postgresql 86e602e1c6e4 registry.redhat.io/rhel8/redis-6:latest run-redis 4 hours ago Up 4 hours redis 71b5bad7d7f1 registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel8:latest /usr/bin/receptor... 4 hours ago Up 4 hours receptor 84df241d5ae3 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 4 hours ago Up 4 hours automation-controller-rsyslog 7ffa833dd597 registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 4 hours ago Up 4 hours automation-controller-task 344e8869af0c registry.redhat.io/ansible-automation-platform-24/controller-rhel8:latest /usr/bin/launch_a... 4 hours ago Up 4 hours automation-controller-web
後で再度触れますが PORTS
欄は空欄です。
podman info
インストールユーザー(非root)での podman info
の結果は以下のとおりです。
▼クリックして展開(長いので)
$ podman info host: arch: amd64 buildahVersion: 1.33.8 cgroupControllers: - memory - pids cgroupManager: systemd cgroupVersion: v2 conmon: package: conmon-2.1.10-1.el9.x86_64 path: /usr/bin/conmon version: 'conmon version 2.1.10, commit: fb8c4bf50dbc044a338137871b096eea8041a1fa' cpuUtilization: idlePercent: 99.19 systemPercent: 0.23 userPercent: 0.58 cpus: 4 databaseBackend: sqlite distribution: distribution: rhel version: "9.4" eventLogger: journald freeLocks: 2034 hostname: rhel9-aap24c idMappings: gidmap: - container_id: 0 host_id: 1000 size: 1 - container_id: 1 host_id: 100000 size: 65536 uidmap: - container_id: 0 host_id: 1000 size: 1 - container_id: 1 host_id: 100000 size: 65536 kernel: 5.14.0-427.35.1.el9_4.x86_64 linkmode: dynamic logDriver: journald memFree: 144547840 memTotal: 3836272640 networkBackend: netavark networkBackendInfo: backend: netavark dns: package: aardvark-dns-1.10.0-3.el9_4.x86_64 path: /usr/libexec/podman/aardvark-dns version: aardvark-dns 1.10.0 package: netavark-1.10.3-1.el9.x86_64 path: /usr/libexec/podman/netavark version: netavark 1.10.3 ociRuntime: name: crun package: crun-1.14.3-1.el9.x86_64 path: /usr/bin/crun version: |- crun version 1.14.3 commit: 1961d211ba98f532ea52d2e80f4c20359f241a98 rundir: /run/user/1000/crun spec: 1.0.0 +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +YAJL os: linux pasta: executable: "" package: "" version: "" remoteSocket: exists: true path: /run/user/1000/podman/podman.sock security: apparmorEnabled: false capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT rootless: true seccompEnabled: true seccompProfilePath: /usr/share/containers/seccomp.json selinuxEnabled: true serviceIsRemote: false slirp4netns: executable: /usr/bin/slirp4netns package: slirp4netns-1.2.3-1.el9.x86_64 version: |- slirp4netns version 1.2.3 commit: c22fde291bb35b354e6ca44d13be181c76a0a432 libslirp: 4.4.0 SLIRP_CONFIG_VERSION_MAX: 3 libseccomp: 2.5.2 swapFree: 4111724544 swapTotal: 4227854336 uptime: 16h 38m 46.00s (Approximately 0.67 days) variant: "" plugins: authorization: null log: - k8s-file - none - passthrough - journald network: - bridge - macvlan - ipvlan volume: - local registries: search: - registry.access.redhat.com - registry.redhat.io - docker.io store: configFile: /home/admin/.config/containers/storage.conf containerStore: number: 6 paused: 0 running: 6 stopped: 0 graphDriverName: overlay graphOptions: {} graphRoot: /home/admin/.local/share/containers/storage graphRootAllocated: 26164068352 graphRootUsed: 8558268416 graphStatus: Backing Filesystem: xfs Native Overlay Diff: "true" Supports d_type: "true" Supports shifting: "false" Supports volatile: "true" Using metacopy: "false" imageCopyTmpDir: /var/tmp imageStore: number: 4 runRoot: /run/user/1000/containers transientStore: false volumePath: /home/admin/.local/share/containers/storage/volumes version: APIVersion: 4.9.4-rhel Built: 1723107101 BuiltTime: Thu Aug 8 17:51:41 2024 GitCommit: "" GoVersion: go1.21.11 (Red Hat 1.21.11-1.el9_4) Os: linux OsArch: linux/amd64 Version: 4.9.4-rhel
systemd 連携の概要
podman は systemd との連携機能があり、Conteinerized AAP の各コンテナは systemd 経由で起動、停止するようになっています。
インストールユーザー(非root)でユニットファイルが作成されることが特徴です。~/.config/systemd/user/
ディレクトリ配下に、各コンテナに対応するユニットファイルがあります。
$ ls -l ~/.config/systemd/user/ total 28 -rw-r--r--. 1 admin admin 864 Sep 24 12:40 automation-controller-rsyslog.service -rw-r--r--. 1 admin admin 849 Sep 24 12:40 automation-controller-task.service -rw-r--r--. 1 admin admin 844 Sep 24 12:40 automation-controller-web.service drwxr-xr-x. 2 admin admin 4096 Sep 24 12:43 default.target.wants drwxrwx---. 2 admin admin 27 Sep 24 12:37 podman.service.d -rw-r--r--. 1 admin admin 698 Sep 24 12:39 postgresql.service -rw-r--r--. 1 admin admin 688 Sep 24 12:40 receptor.service -rw-r--r--. 1 admin admin 673 Sep 24 12:39 redis.service drwxr-xr-x. 2 admin admin 27 Sep 24 12:37 sockets.target.wants
systemctl
コマンドで操作する場合は --user
オプションが必要です。
systemctl
コマンド使用例1:
$ systemctl list-unit-files -t service --user UNIT FILE STATE PRESET automation-controller-rsyslog.service enabled disabled automation-controller-task.service enabled disabled automation-controller-web.service enabled disabled dbus-broker.service enabled enabled dbus.service alias - dirmngr.service static - gpg-agent.service static - grub-boot-success.service static - podman-auto-update.service disabled disabled podman-kube@.service disabled disabled podman-restart.service disabled disabled podman.service disabled disabled postgresql.service enabled disabled receptor.service enabled disabled redis.service enabled disabled ssh-agent.service static - systemd-exit.service static - systemd-tmpfiles-clean.service static - systemd-tmpfiles-setup.service enabled enabled 19 unit files listed.
systemctl
コマンド使用例2:
$ systemctl status automation-controller-web.service --user ● automation-controller-web.service - Podman automation-controller-web.service Loaded: loaded (/home/admin/.config/systemd/user/automation-controller-web.service; enabled; preset: disabled) Active: active (running) since Tue 2024-09-24 12:43:57 JST; 4h 58min ago Docs: man:podman-generate-systemd(1) Process: 27457 ExecStart=/usr/bin/podman start automation-controller-web (code=exited, status=0/SUCCESS) Main PID: 27469 (conmon) Tasks: 1 (limit: 23160) Memory: 756.0K CPU: 75ms CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/automation-controller-web.service └─27469 /usr/bin/conmon --api-version 1 -c 344e8869af0c02b02b2f72033143527167153164ad6adc548e675c4fcfa2995f -u 344e8869af0c02b02b2f720331435271671531> ...(略)...
systemctl
コマンド使用例3:
$ systemctl list-dependencies --user default.target ● ├─automation-controller-rsyslog.service ● ├─automation-controller-task.service ● ├─automation-controller-web.service ● ├─postgresql.service ● ├─receptor.service ● ├─redis.service ● └─basic.target ● ├─systemd-tmpfiles-setup.service ● ├─paths.target ● ├─sockets.target ● │ ├─dbus.socket ● │ └─podman.socket ● └─timers.target ● ├─grub-boot-success.timer ● └─systemd-tmpfiles-clean.timer
ユニットファイルの例
systemd のユニットファイルは、インストール処理内の containers.podman.podman_container
モジュールの generate_systemd
オプションの指定によって生成されます。
generate_systemd.new
オプションの指定はなくデフォルトの false
扱いです。なので、インストール処理内でコンテナを create
して、systemd 経由で start
する、という流れです。いきなり run
ではないです。
コンテナの CreateCommand
を確認すると、odman container create
になっていました。
$ podman inspect automation-controller-web ...(略)... "CreateCommand": [ "podman", "container", "create", "--name", "automation-controller-web", ...(略)...
以下は、私の環境の /.config/systemd/user/automation-controller-web.service
の例です。ExecStart
が podman start
になっていることが確認できます。
# automation-controller-web.service # autogenerated by Podman 4.9.4-rhel # Tue Sep 24 12:40:39 JST 2024 [Unit] Description=Podman automation-controller-web.service Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/run/user/1000/containers # User-defined dependencies Requires=postgresql.service redis.service [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=90 ExecStart=/usr/bin/podman start automation-controller-web ExecStop=/usr/bin/podman stop \ -t 30 automation-controller-web ExecStopPost=/usr/bin/podman stop \ -t 30 automation-controller-web PIDFile=/run/user/1000/containers/overlay-containers/344e8869af0c02b02b2f72033143527167153164ad6adc548e675c4fcfa2995f/userdata/conmon.pid Type=forking [Install] WantedBy=default.target
systemd 連携による自動起動
前述のユニットファイルにある通り、Install
セクションでは、WantedBy=default.target
が指定されていて、systemctl enable|disable
できるようになっていました。
インストール処理内では、ansible.builtin.systemd
モジュールで、起動と enable されるようになっています。これにより自動起動を実現しているようです。
ただ、前述通り、ユニットファイルはユーザーレベルのものです。この場合、デフォルトではユーザーがログインすると起動、ログアウトすると停止するため、サービス提供に向きません。
どうなってるんだろうと思ったのですが、インストール処理の中で loginctl enable-linger ユーザー名
が実行されていました。これにより、システ起動時にサービスが起動するようになるようです。
参考: 14.2. systemd サービスの有効化 | Red Hat Product Documentation
ポート開放の仕組み
前述通り podman ps
での表示は PORTS
は空欄でした。どうやってポート開放しているのかなと思ったので調べました。
--network host
でコンテナが起動されていました。
$ podman inspect automation-controller-web ...(略)... "CreateCommand": [ ...(略)... "--network", "host", ...(略)...
なお、ホスト側での ss
はこんな感じでした。
$ ss -nap | grep 443 # automation-controller-web の listen 分 tcp LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=27533,fd=6),("nginx",pid=27532,fd=6),("nginx",pid=27531,fd=6),("nginx",pid=27530,fd=6),("nginx",pid=27525,fd=6)) tcp LISTEN 0 511 [::]:443 [::]:* users:(("nginx",pid=27533,fd=7),("nginx",pid=27532,fd=7),("nginx",pid=27531,fd=7),("nginx",pid=27530,fd=7),("nginx",pid=27525,fd=7))
デフォルトでは、一般ユーザーでは 443
は listen できませんが、前述通りインストール処理内でカーネルパラメーター net.ipv4.ip_unprivileged_port_start
を調整しているので listen できます。
インストール処理中、ansible.posix.firewalld
モジュールで firewalld の調整もしてくれます。
ストレージ・ボリューム関連
ボリューム一覧は以下の通りです。
$ podman volume ls DRIVER VOLUME NAME local postgresql local redis_data local redis_etc local redis_run local receptor_run local receptor_runner local receptor_home local receptor_data
ボリュームのパスは以下の通りです。ルートレス Podman としての標準のままです。
$ ls -l ~/.local/share/containers/storage/volumes/ total 0 drwx------. 3 admin admin 19 Sep 24 12:39 postgresql drwx------. 3 admin admin 19 Sep 24 12:39 receptor_data drwx------. 3 admin admin 19 Sep 24 12:39 receptor_home drwx------. 3 admin admin 19 Sep 24 12:39 receptor_run drwx------. 3 admin admin 19 Sep 24 12:39 receptor_runner drwx------. 3 admin admin 19 Sep 24 12:39 redis_data drwx------. 3 admin admin 19 Sep 24 12:39 redis_etc drwx------. 3 admin admin 19 Sep 24 12:39 redis_run
また、~/aap
に用途ごとにディレクトリがあり、この配下を各コンテナがバインドマウントしています。
$ ls -l ~/aap/ total 0 drwxrwx---. 3 admin admin 55 Sep 24 12:37 containers drwxrwx---. 7 admin admin 75 Sep 24 12:40 controller drwxrwx---. 2 admin admin 42 Sep 24 12:39 postgresql drwxrwx---. 3 admin admin 17 Sep 24 12:39 receptor drwxr-x---. 3 admin admin 52 Sep 24 12:39 tls
例えば automation-controller-web
の場合は以下の通り。
$ podman inspect automation-controller-web ...(略)... "HostConfig": { "Binds": [ "receptor_run:/run/receptor:U,rw,rprivate,nosuid,nodev,rbind", "redis_run:/run/redis:z,rw,rprivate,nosuid,nodev,rbind", "/home/admin/aap/controller/etc/tower.key:/etc/tower/tower.key:ro,rprivate,rbind", "/home/admin/aap/controller/etc/tower.cert:/etc/tower/tower.cert:ro,rprivate,rbind", "/home/admin/aap/controller/etc/launch_awx_task.sh:/usr/bin/launch_awx_task.sh:ro,rprivate,rbind", "/home/admin/aap/controller/data/job_execution:/home/admin/aap/controller/data/job_execution:rw,rprivate,rbind", "/home/admin/aap/controller/data/projects:/home/admin/aap/controller/data/projects:rw,rprivate,rbind", ...(略)...
おわりに
コンテナによるインストールはデプロイが早く、ライセンスの自動適用や設定の投入も一緒にできるが便利だなと思いました。
現状、インストールがうまくいかなかったときは、一度アンイストールしてから再度インストールするほうが良いような感覚でした。
将来の AAP のバージョンで GA になったら、またチェックしたいと思います。
まとめ(再掲)
- podman でデプロイする方式、ルートレス
- デプロイ後にライセンスの適用や設定投入もできる
- 各コンテナはユーザーレベルの systemd 経由で起動
試せなかったこと
興味はあったけど今回試せなかったこと一覧
- http の禁止(https のみ)
- 作業マシン以外へのデプロイ
- Automation mesh 構成
- トラシュー1 のように、インストール処理中にコンテナ
receptor
に異常終了した時に、インストール処理を中断させる方法
参考
Podman と systemd の連携周りでは以下の書籍を参考にさせていただきました。