第6章 AAP2 用の Playbook の変換
Ansible Automation Platform 2 とそのコンテナー化された実行環境では、localhost の使用方法が変更されました。Ansible Automation Platform の以前のバージョンでは、localhost に対してジョブが実行され、これは基盤となる Automation Controller ホスト上で実行されていました。これは、データと永続的なアーティファクトを保存するために使用できます。
Ansible Automation Platform 2 では、localhost はコンテナー内で実行されていることを意味しますが、これは本質的に一時的なものです。Localhost は、特定のホストに関連付けられなくなり、ポータブルな実行環境では、適切な環境とソフトウェアの前提条件がすでに実行環境コンテナーに組み込まれていれば、どこでも実行できることになります。
6.1. 自動実行からのデータの永続化
ローカル Automation Controller ファイルシステムは、データをそのホストに結び付けるため、逆効果であると考えてください。マルチノードクラスターがある場合、毎回異なるホストに接続することができ、これにより、相互に依存するワークフローを作成中で、ディレクトリーが作成済みの場合は、問題が発生する可能性があります。たとえば、ディレクトリーが 1 つのノードでのみ作成され、別のノードで Playbook が実行されている場合、矛盾する結果となります。
解決策は、Amazon S3、Gist、またはデータをデータエンドポイントに rsync するロールなど、何らかの形式の共有ストレージソリューションを使用することです。
ランタイムにデータまたは設定をコンテナーに注入するオプションが存在します。これは、Automation Controller の分離されたジョブパスオプションを使用して実現できます。
これにより、ランタイムにディレクトリーとファイルを実行環境にマウントする方法が提供されます。これは、ansible-runner を使用して自動化メッシュを Podman コンテナーに注入し、自動化を開始することにより、自動化メッシュを通じて実現されます。以下は、分離されたジョブパスを使用するユースケースの一部を示しています。
- SSL 証明書を実行環境に組み込むのではなく、ランタイムに提供します。
- SSH 設定などのランタイム設定データを渡しますが、自動化中に使用したいものであれば何でもかまいません。
- オートメーションの実行前、実行中、実行後に使用されるファイルの読み取りと書き込み。
使用するには次のような注意点があります。
- ボリュームマウントは、自動化実行が可能なすべてのノード (つまり、ハイブリッドコントロールプレーンノードとすべての実行ノード) に事前に存在する必要があります。
SELinux が有効になっている場合 (Ansible Automation Platform のデフォルト)、ファイル権限に注意してください。
- ルートレス Podman は OCP ベース以外のインストールで実行されるため、これは重要です。
注意事項を慎重に確認する必要があります。ルートレス Podman と Podman ボリュームマウントのランタイムオプション、分離されたジョブパスの [:OPTIONS] 部分についてよく読むことを強く推奨します。これが、Ansible Automation Platform 2 内で使用されるものだからです。
6.1.1. Playbook 例の変換
例
これは、ジョブの実行中にファイルの読み取りと書き込みをできるようにする /mydata という共有ディレクトリーの例です。これは、オートメーションの実行に使用する実行ノードにすでに存在している必要がある点に注意してください。
このジョブを実行するには aape1.local 実行ノードをターゲットにします。基盤となるホストにはすでにこれが設定されているからです。
[awx@aape1 ~]$ ls -la /mydata/ total 4 drwxr-xr-x. 2 awx awx 41 Apr 28 09:27 . dr-xr-xr-x. 19 root root 258 Apr 11 15:16 .. -rw-r--r--. 1 awx awx 33 Apr 11 12:34 file_read -rw-r--r--. 1 awx awx 0 Apr 28 09:27 file_write
簡単な Playbook を使って、アクセスを許可するために定義されたスリープでオートメーションを起動し、プロセスを理解して、ファイルの読み書きを示します。
# vim:ft=ansible:
- hosts: all gather_facts: false ignore_errors: yes vars: period: 120 myfile: /mydata/file tasks: - name: Collect only selected facts ansible.builtin.setup: filter: - 'ansible_distribution' - 'ansible_machine_id' - 'ansible_memtotal_mb' - 'ansible_memfree_mb' - name: "I'm feeling real sleepy..." ansible.builtin.wait_for: timeout: "{{ period }}" delegate_to: localhost - ansible.builtin.debug: msg: "Isolated paths mounted into execution node: {{ AWX_ISOLATIONS_PATHS }}" - name: "Read pre-existing file..." ansible.builtin.debug: msg: "{{ lookup('file', '{{ myfile }}_read' - name: "Write to a new file..." ansible.builtin.copy: dest: "{{ myfile }}_write" content: | This is the file I've just written to. - name: "Read written out file..." ansible.builtin.debug: msg: "{{ lookup('file', '{{ myfile }}_write') }}"
Ansible Automation Platform 2 ナビゲーションパネルから Jobs オプションから Job settings を選択します。
を選択します。次に、分離されたジョブを公開するパス:
[ "/mydata:/mydata:rw" ]
ボリュームマウントはコンテナー内で同じ名前でマップされ、読み取り/書き込み機能を備えています。これは、ジョブテンプレートを起動するときに使用されます。
実行ごとにスリープ期間を調整できるように、起動時のプロンプト を extra_vars に設定する必要があります。デフォルトは 30 秒です。
起動され、wait_for モジュールがスリープのために呼び出されたら、実行ノードに行き、何が実行されているかを確認できます。
実行が正常に完了したことを確認するには、次のコマンドを実行してジョブの出力を取得します。
$ podman exec -it 'podman ps -q' /bin/bash bash-4.4#
これで、実行中の実行環境コンテナーに入りました。
権限を見ると、awx が root になっていることがわかりますが、ユーザーをサンドボックスに似たカーネル名前空間にマップするルートレス Podman を使用しているため、これはスーパーユーザーのような実際の root ではありません。shadow-utils 用のルートレス Podman の仕組みに関する詳細は、How does rootless Podman work? を参照してください。
bash-4.4# ls -la /mydata/ Total 4 drwxr-xr-x. 2 root root 41 Apr 28 09:27 . dr-xr-xr-x. 1 root root 77 Apr 28 09:40 .. -rw-r—--r–. 1 root root 33 Apr 11 12:34 file_read -rw-r—--r–. 1 root root 0 Apr 28 09:27 file_write
結果を確認すると、このジョブは失敗しました。その理由を理解するには、残りの出力を調べる必要があります。
TASK [Read pre-existing file…]******************************* 10:50:12 ok: [localhost] => { “Msg”: “This is the file I am reading in.” TASK {Write to a new file...}********************************* 10:50:12 An exception occurred during task execution. To see the full traceback, use -vvv. The error was: PermissionError: [Errno 13] Permission denied: b'/mydata/.ansible_tmpazyqyqdrfile_write' -> b' /mydata/file_write' Fatal: [localhost]: FAILED! => {"changed": false, :checksum": "9f576o85d584287a3516ee8b3385cc6f69bf9ce", "msg": "Unable to make b'/root/.ansible/tmp/anisible-tim-1651139412.9808054-40-91081834383738/source' into /mydata/file_write, failed final rename from b'/mydata/.ansible_tmpazyqyqdrfile_write': [Errno 13] Permission denied: b'/mydata/.ansible_tmpazyqyqdrfile_write' -> b'/mydata/file_write} ...ignoring TASK [Read written out file...] ****************************** 10:50:13 Fatal: [localhost]: FAILED: => {"msg": "An unhandled exception occurred while running the lookup plugin 'file'. Error was a <class 'ansible.errors.AnsibleError;>, original message: could not locate file in lookup: /mydate/file_write. Vould not locate file in lookup: /mydate/file_write"} ...ignoring
:rw が設定されているにもかかわらずジョブは失敗したため、書き込み機能が必要です。プロセスは既存のファイルを読み取ることはできましたが、書き出すことはできませんでした。これは、コンテナーにマウントされたボリュームコンテンツに適切なラベルを付ける必要がある SELinux 保護によるものです。ラベルがない場合、SELinux はコンテナー内でのプロセスの実行を阻止する可能性があります。OS によって設定されたラベルは、Podman によって変更されることはありません。詳細は、Podman ドキュメントを参照してください。
これはよくある誤解である可能性があります。デフォルトを :z に設定しました。これにより、Podman は共有ボリューム上のファイルオブジェクトのラベルを変更するように指示されます。
したがって、:z を追加することも、追加しないこともできます。
分離されたジョブを公開するパス:
[ "/mydata:/mydata" ]
Playbook は期待どおりに機能するようになりました。
PLAY [all] **************************************************** 11:05:52 TASK [I'm feeling real sleepy. . .] *************************** 11:05:52 ok: [localhost] TASK [Read pre-existing file...] ****************************** 11:05:57 ok: [localhost] => { "Msg": "This is the file I'm reading in." } TASK [Write to a new file…] ********************************** 11:05:57 ok: [localhost] TASK [Read written out file…] ******************************** 11:05:58 ok: [localhost] => { “Msg”: “This is the file I’ve just written to.”
基盤となる実行ノードのホストに戻ると、新しく書き出された内容があります。
Red Hat OpenShift 内で自動化ジョブを起動するためにコンテナーグループを使用している場合、同じパスをその環境に公開するように Ansible Automation Platform 2 に指示することもできますが、設定でデフォルトを On
に切り替える必要があります。
有効にすると、これは、実行に使用される Pod 仕様内に volumeMounts および volumes として注入します。以下に例を示します。
apiVersion: v1 kind: Pod Spec: containers: - image: registry.redhat.io/ansible-automation-platform-24/ee-minimal-rhel8 args: - ansible runner - worker - –private-data-dir=/runner volumeMounts: mountPath: /mnt2 name: volume-0 readOnly: true mountPath: /mnt3 name: volume-1 readOnly: true mountPath: /mnt4 name: volume-2 readOnly: true volumes: hostPath: path: /mnt2 type: “” name: volume-0 hostPath: path: /mnt3 type: “” name: volume-1 hostPath: path: /mnt4 type: “” name: volume-2
実行中のコンテナー内のストレージはオーバーレイファイルシステムを使用しています。tmpfs がアンマウントされるのと同様に、実行中のコンテナー内の変更はジョブの完了後に破棄されます。