てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] もくもく会コンテンツのリポジトリにある資料「Ansible Best Practices」

Ansible ユーザー会では定期的にもくもく会というハンズオンイベントを開催しています。

次回は 2022/04/21 です

コンテンツは以下のリポジトリにあります。

github.com

先日見つけたのですが、Ansible Best Practicesという資料がありました。

こうかいても動くけど、こう書いたほうがいい、というようなことや、テクニックが書かれています。

良い資料だなと思ったのでリンクを共有します。

github.com

ディレクトリは以下。

github.com

[Ansible] Automation Controller 上で実行環境コンテナ内のコレクション一覧を確認する(やや力技)

はじめに

AAP 2.x になってから、Ansible の実行環境が Python の venv から、コンテナに変わりました。

コンテナの中に、利用するコレクションを仕込んでおくわけですが、Automation Controller を触ってるときに、コンテナ内のコレクション一覧を確認したいときがあります。 ターミナルの戻らずに。横着かもなんですが・・。

そんなときの力技です。

アドホック実行を利用

Automation Controller にも、CLI 同様にアドホック実行機能があります。これを応用して localhost を対象として、確認したい実行環境を選んで ansible-galaxy colleciton list を実行すればコレクションの一覧を表示できます。

まず localhost があるインベントリで localhost を選択し、コマンドの実行をクリックします。デフォルトでは、Demo Inventory の中にあります。

localhost でコマンド実行

ここからアドホック実行のウィザード画面になります。

モジュールに command、引数に ansible-galaxy colleciton list を指定します。

利用モジュールと引数を指定

アドホック実行だと何故か認証情報の指定が必須(ジョブテンプレートでは任意)なので、ダミー的に Demo Credential を選択します。

認証情報の指定

確認画面になるので起動ボタンをクリックします。

確認画面

実行結果として、コレクション一覧が表示されます。

コレクション一覧の表示

Automation Controller 4.1.0 の Default execution environment (registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest ) では以下の表示になりました。

# /usr/share/ansible/collections/ansible_collections
Collection              Version
----------------------- -------
amazon.aws              2.0.0  
ansible.controller      4.1.0  
ansible.netcommon       2.4.0  
ansible.network         1.2.0  
ansible.posix           1.2.0  
ansible.security        1.0.0  
ansible.utils           2.4.2  
ansible.windows         1.7.3  
arista.eos              3.1.0  
cisco.asa               2.1.0  
cisco.ios               2.5.0  
cisco.iosxr             2.5.0  
cisco.nxos              2.7.1  
cloud.common            2.0.3  
frr.frr                 1.0.3  
ibm.qradar              1.0.3  
junipernetworks.junos   2.6.0  
kubernetes.core         2.1.1  
openvswitch.openvswitch 2.0.2  
redhat.insights         1.0.5  
redhat.openshift        2.0.1  
redhat.rhv              1.4.4  
redhat.satellite        2.2.0  
servicenow.itsm         1.2.0  
splunk.es               1.0.2  
trendmicro.deepsec      1.1.0  
vmware.vmware_rest      2.1.0  
vyos.vyos               2.6.0  

もちろん、途中で選択する実行環境によって、内容が変わります。

別の実行環境の場合

おまけ(ansible-navigator の場合)

ansible-navigator collectionsだとこんな表示ができます。ターミナルに戻ってこれをやるのが正攻法かなと思います。

ansible-navigator によるコレクション一覧

コレクションを指定すると、所属するモジュール類が表示されます。さらに進んでいくとドキュメントに相当する情報も見れます。

モジュール類の一覧

Backlog の Git 機能の課題とプルリクエスト連携機能をためした

はじめに

タスク管理ツール(SaaS)である Backlog にはGit ホスティング機能があります。

https://support-ja.backlog.com/hc/ja/categories/360002262194-Git-Subversion

プルリクエスト機能もあるため、課題と関連付けできると経緯をトレースできていいなと思いました。

プルリクエスト画面側で関連課題を手動で選択もできますが、自動で関連付ける方法がいくつかあるようでした。

試したことを簡単にまとめます。

コミットメッセージと課題の連携

コミットメッセージに課題キーを含めると、課題のコメントにコミットメッセージが書き込まれます。

公式サイトから

「コミットと課題を連携する」にチェックを入れると、コミットメッセージに課題キーを含めてコミットすることで、その課題に自動的にコメントを登録できます。

この機能はデフォルトで有効になってました。

なお、課題キーとは課題の識別子で、プロジェクトキー-連番 という形式です。例えば TE-129 というものです。URLの課題の件名の左にも表示されます。コピペにはこのボタンが便利です。

課題キーのコピペ

それでは試してみます。

現状 TE-129 という課題があるものとします。

TE-129 add sakana というメッセージでコミットします。その後 git push します。

無事に、課題 TE-129 のコメントに、コミットメッセージが書き込まれました。

コメントにコミットメッセージが書き込まれた

コミットハッシュをクリックすると差分が表示されて便利です。

差分表示

プルリクエストの件名と関連課題の連携

今度はプルリクエスト時の連携です。

実は先程、ブランチ名に課題キーを含めるという一工夫をしました(add-sakana/TE-129)。「件名」「関連課題」の連携を確かめるためです。

公式サイトから

プルリクエストブランチの名前に、Backlogの課題キーを含めておくと、その課題の件名が「件名」に表示されます

「関連課題」にその課題キーが自動で設定されます。これらの値は変更することもできます

今回は add-sakana/TE-129 のように /課題キー というブランチ名にしましたが、スラッシュには意味はありません。「課題キーを含めておくと」ということなので、他の区切り文字や、課題キーのみのブランチ名でも大丈夫だと思います。

ということで、プルリクエストを出します。

以下のように、自動で件名や関連課題が入りました。この2箇所はブランチ名に課題キーを含めたことによる動作です。

件名と関連課題の自動入力

件名がしっくり来なかったら手動で修正してしまえば良いと思います。

また、プルリクエストに関連課題を設定することで、課題側のプルリクエストが表示され、コメントとしても書き込まれます。

課題側の関連プルリクエス

プルリクエストが作成されたことのコメント

おわりに

修正の経緯を追えるようにしておけるのは、何かと便利ですね。

firewalld の Intra Zone Forwarding の機能有無やデフォルト値

はじめに

firewalld の firewall-cmd --list-all の結果で、forward という項目がある環境とない環境があることに気が付きました。forward-ports とはまた別物です。

0.9.0で導入された、Intra Zone Forwarding という機能のものによるようです。

気になったので、いくつか別途用意して表示のされ方などを確認しました。

まとめ

先にまとめです。

RHEL firewalld バージョン Intra Zone Forwarding 機能有無 Intra Zone Forwarding デフォルト設定
8.4 0.8.2 なし -
8.4 0.9.3 あり 無効
9.0 Beta 1.0.0 あり 有効

firewalld 0.8.2 on RHEL 8.4

Red Hat Enterprise Linux 8.4 を、GUIがないサーバーとしてインストールした環境です。

[admin@localhost ~]$ cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.4 (Ootpa)

バージョン確認

firewalld 0.8.2 がインストールされています。

[admin@localhost ~]$ sudo dnf list --installed | grep -i firewalld
firewalld.noarch                              0.8.2-6.el8                                 @anaconda 
firewalld-filesystem.noarch                   0.8.2-6.el8                                 @anaconda 

firewall-cmd --list-all

firewall-cmd --list-all コマンドの結果は以下のとおりです。forward という項目はありません、

[admin@localhost ~]$ sudo firewall-cmd --list-all 
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

firewalld 0.9.3 on RHEL 8.4

続いて、firewalld アップグレードした環境で試します。

firewalld のアップグレード

[admin@localhost ~]$ sudo dnf upgrade firewalld
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for x86_64 - AppStream (RPMs)                       33 MB/s |  39 MB     00:01    
Red Hat Enterprise Linux 8 for x86_64 - BaseOS (RPMs)                          35 MB/s |  45 MB     00:01    
Dependencies resolved.
==============================================================================================================
 Package                     Architecture  Version                 Repository                            Size
==============================================================================================================
Upgrading:
 firewalld                   noarch        0.9.3-7.el8_5.1         rhel-8-for-x86_64-baseos-rpms        502 k
 firewalld-filesystem        noarch        0.9.3-7.el8_5.1         rhel-8-for-x86_64-baseos-rpms         77 k
 python3-firewall            noarch        0.9.3-7.el8_5.1         rhel-8-for-x86_64-baseos-rpms        433 k

Transaction Summary
==============================================================================================================
Upgrade  3 Packages

Total download size: 1.0 M
Is this ok [y/N]: y
...()...

バージョン確認

0.9.3 になりました。

[admin@localhost ~]$ sudo dnf list --installed | grep -i firewalld
firewalld.noarch                              0.9.3-7.el8_5.1                             @rhel-8-for-x86_64-baseos-rpms
firewalld-filesystem.noarch                   0.9.3-7.el8_5.1                             @rhel-8-for-x86_64-baseos-rpms

firewall-cmd --list-all

firewall-cmd --list-all コマンドの結果を見ると foward: no という項目が追加されました。

[admin@localhost ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: no
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

これが firewalld 0.9.0で導入された、Intra Zone Forwarding という機能のものによるようです。

この時点では、デフォルトでオフです。(Intra Zone Forwarding 説明ページから)

By default, all currently shipped zone definitions and user created zones have forward disabled.

設定を変更してみる (有効化)

firewall-cmd コマンドのヘルプを見ると、以下オプションが増えていました。

...(略)...
  --add-forward        Enable forwarding of packets between interfaces and
                       sources in a zone [P] [Z] [T]
  --remove-forward     Disable forwarding of packets between interfaces and
                       sources in a zone [P] [Z]
  --query-forward      Return whether forwarding of packets between interfaces
                       and sources has been enabled for a zone [P] [Z]
...(略)...

軽く試します。

[admin@localhost ~]$ sudo firewall-cmd --add-forward --permanent
success
[admin@localhost ~]$ sudo firewall-cmd --reload
success

変更後、firewall-cmd --list-all を見ると forward: yes になりました。

[admin@localhost ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

一応、/etc/firewalld/zones/public.xml ファイルを見ます。<forward/> がついてました。

[admin@localhost ~]$ sudo cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
  <service name="cockpit"/>
  <forward/>
</zone>

設定を変更してみる (無効化)

--remove-forward で元に戻します。

[admin@localhost ~]$ sudo firewall-cmd --remove-forward --permanent
success
[admin@localhost ~]$ sudo firewall-cmd --reload
success

forward: no に戻りました。

[admin@localhost ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

/etc/firewalld/zones/public.xml からは <forward/> が消えました。

[admin@localhost ~]$ sudo cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
  <service name="cockpit"/>
</zone>

1.0.0 on RHEL 9.0 Beta

今度は別に構築した、Red Hat Enterprise Linux 9.0 Beta の環境で試します。

[admin@localhost ~]$ cat /etc/redhat-release 
Red Hat Enterprise Linux release 9.0 Beta (Plow)

バージョン確認

firewalld 1.0.0 がインストールされています。

[admin@localhost ~]$ sudo dnf list --installed | grep -i firewalld
firewalld.noarch                              1.0.0-3.el9_b                             @anaconda 
firewalld-filesystem.noarch                   1.0.0-3.el9_b                             @anaconda 

firewall-cmd --list-all

firewall-cmd --list-all コマンドの結果を確認します。

[admin@localhost ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

おっと、デフォルトで forward: yes でした。

firewalld のリリースノートとたどってみると、ちょうど 1.0.0 で Intra Zone Forwarding がデフォルトで有効になったようです。

Intra-zone forwarding by default

github.com

firewalld.org

なお、微妙に別件のようですが、Red Hat Enterprise Linux 9.0 Beta のリリースノートの Networking には

Changed behavior in firewalld when transmitting packets between zones

という記載がありました。

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9-beta/html/9.0_release_notes/new-features#enhancement_networking

Red Hat Enterprise Linux 9.0 の Python 環境を少し探ってみた

はじめに

Red Hat Enterprise Linux 9.0 を、GUIでない方のサーバーとしてインストールしました。

[2022/05/19追記] Red Hat Enterprise Linux 9.0 正式版がリリースされたため、ベータだった箇所を正式版で確認した内容に更新しました。

Python 周りがどうのようになっているのか、試しながら調べてみました。あくまで私の環境で調べたという状態なので、お手元と異なるかもしれません。

python コマンドが使える

RHEL 8 系では、デフォルトで python コマンドが使えませんでしたが、使えました。

[admin@rhel90test ~]$ cat /etc/redhat-release 
Red Hat Enterprise Linux release 9.0 (Plow)
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ python --version
Python 3.9.10
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ which python
/usr/bin/python

/usr/bin/python3.9 へのシンボリックリンク

python* 系コマンドの関係は以下の通り

[admin@rhel90test ~]$ ls -al /usr/bin/python*
lrwxrwxrwx. 1 root root     9  211 22:59 /usr/bin/python -> ./python3
lrwxrwxrwx. 1 root root     9  211 22:51 /usr/bin/python3 -> python3.9
-rwxr-xr-x. 1 root root 16040  211 22:51 /usr/bin/python3.9

ドキュメントには

実稼働環境では、python3 または python3.9 を明示的に使用することが推奨されます。

とあります。

pip コマンドは利用不可

[admin@rhel90test ~]$ which pip
/usr/bin/which: no pip in (/home/admin/.local/bin:/home/admin/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ pip
-bash: pip: コマンドが見つかりません
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ 
[admin@rhel90test ~]$ pip3
-bash: pip3: コマンドが見つかりません

ドキュメントには、

バージョンを指定しないコマンド (python3-pip パッケージの /usr/bin/pip など) がいくつか利用できます。

とあります。

venv 内では利用可能でした。

[admin@rhel90test ~]$ python -m venv .venv
[admin@rhel90test ~]$ source .venv/bin/activate
(.venv) [admin@rhel90test ~]$ pi
pic         pidwait     pigz        ping        pinky       pip3        pivot_root  
pidof       pifconfig   pinfo       ping6       pip         pip3.9      
(.venv) [admin@rhel90test ~]$ pip    # tab
pip     pip3    pip3.9  
(.venv) [admin@rhel90test ~]$ python    # tab
python     python3    python3.9  

/usr/libexec/platform-python は健在

RHEL 8 からあった、/usr/libexec/platform-python はありました。/usr/bin/python3.9 へのシンボリックリンクです。

(.venv) [admin@rhel90test ~]$ ls -al /usr/libexec/platform-python
lrwxrwxrwx. 1 root root 18  211 22:51 /usr/libexec/platform-python -> /usr/bin/python3.9

dnf list --installed の結果

dnf list --installedgrep -i python した結果は以下のとおりです。前述の通りGUIでない方のサーバーとしてインストールした環境です。

libcap-ng-python3.x86_64                      0.8.2-7.el9                    @AppStream
policycoreutils-python-utils.noarch           3.3-6.el9_0                    @AppStream
python-unversioned-command.noarch             3.9.10-2.el9                   @AppStream
python3.x86_64                                3.9.10-2.el9                   @anaconda 
python3-audit.x86_64                          3.0.7-101.el9_0.2              @AppStream
python3-chardet.noarch                        4.0.0-5.el9                    @anaconda 
python3-cloud-what.x86_64                     1.29.26-3.el9_0                @anaconda 
python3-dasbus.noarch                         1.4-5.el9                      @AppStream
python3-dateutil.noarch                       1:2.8.1-6.el9                  @anaconda 
python3-dbus.x86_64                           1.2.18-2.el9                   @anaconda 
python3-decorator.noarch                      4.4.2-6.el9                    @anaconda 
python3-dmidecode.x86_64                      3.12.2-27.el9                  @anaconda 
python3-dnf.noarch                            4.10.0-5.el9_0                 @anaconda 
python3-dnf-plugins-core.noarch               4.0.24-4.el9_0                 @anaconda 
python3-ethtool.x86_64                        0.15-2.el9                     @anaconda 
python3-file-magic.noarch                     5.39-8.el9                     @AppStream
python3-firewall.noarch                       1.0.0-4.el9                    @anaconda 
python3-gobject-base.x86_64                   3.40.1-5.el9                   @anaconda 
python3-gpg.x86_64                            1.15.1-6.el9                   @anaconda 
python3-hawkey.x86_64                         0.65.0-5.el9_0                 @anaconda 
python3-idna.noarch                           2.10-7.el9                     @anaconda 
python3-iniparse.noarch                       0.4-45.el9                     @anaconda 
python3-inotify.noarch                        0.9.6-25.el9                   @anaconda 
python3-libcomps.x86_64                       0.1.18-1.el9                   @anaconda 
python3-libdnf.x86_64                         0.65.0-5.el9_0                 @anaconda 
python3-librepo.x86_64                        1.14.2-1.el9                   @anaconda 
python3-libs.x86_64                           3.9.10-2.el9                   @anaconda 
python3-libselinux.x86_64                     3.3-2.el9                      @AppStream
python3-libsemanage.x86_64                    3.3-2.el9                      @AppStream
python3-libstoragemgmt.x86_64                 1.9.3-1.el9                    @AppStream
python3-libxml2.x86_64                        2.9.13-1.el9                   @anaconda 
python3-lxml.x86_64                           4.6.5-2.el9                    @AppStream
python3-nftables.x86_64                       1:0.9.8-12.el9                 @anaconda 
python3-pexpect.noarch                        4.8.0-7.el9                    @anaconda 
python3-pip-wheel.noarch                      21.2.3-6.el9                   @anaconda 
python3-policycoreutils.noarch                3.3-6.el9_0                    @AppStream
python3-psutil.x86_64                         5.8.0-12.el9                   @AppStream
python3-ptyprocess.noarch                     0.6.0-12.el9                   @anaconda 
python3-pysocks.noarch                        1.7.1-12.el9                   @anaconda 
python3-pyyaml.x86_64                         5.4.1-6.el9                    @anaconda 
python3-requests.noarch                       2.25.1-6.el9                   @anaconda 
python3-rpm.x86_64                            4.16.1.3-12.el9_0              @anaconda 
python3-setools.x86_64                        4.4.0-4.el9                    @anaconda 
python3-setuptools.noarch                     53.0.0-10.el9                  @anaconda 
python3-setuptools-wheel.noarch               53.0.0-10.el9                  @anaconda 
python3-six.noarch                            1.15.0-9.el9                   @anaconda 
python3-subscription-manager-rhsm.x86_64      1.29.26-3.el9_0                @anaconda 
python3-systemd.x86_64                        234-18.el9                     @anaconda 
python3-tracer.noarch                         0.7.5-4.el9                    @AppStream
python3-urllib3.noarch                        1.26.5-3.el9                   @anaconda 
(.venv) [admin@rhel90test ~]$ 

参考

RHEL 9.0 日本語版ドキュメント

access.redhat.com

ベータ時代

rheb.hatenablog.com

www.redhat.com

access.redhat.com

access.redhat.com

Python in RHEL 9

access.redhat.com

[Ansible/AAP] Automation mesh でコントロールノードと実行ノードの分離を試してみた

はじめに

Red Hat Ansible Automation Platform(以下AAP) 2.1 では、スケーラビリティと信頼性を向上させる Automation mesh という機能が導入されました。

AAP1.2 (Ansible Tower としては3.8) までにあった Isolated Node 相当の機能を備えつつ、さらに機能強化されたようなかたちでしょうか。

この記事では、簡単な構成で試したことをまとめます。はじめて調べて試して自分だまとめただけのレベルですので、なにか間違い等あれば @akira6592 までご連絡いただけると助かります。

なお、レッドハットさんの以下のウェビナーを聞いて概要をつかめたので、やってみようと思いました。めちゃくちゃ参考になりました、ありがとうございます!

最新 Ansible Automation Platform 2.1 (AAP 2.1 ) の概要紹介、最新アップデート、実機デモ

珍しく長い記事です。

■ 1. Automation mesh におけるノードの種類

Automation mesh の構成では、それぞれのノードに役割があります。

ノードの役割 説明
コントロールノード(Control node) 司令塔。Automation Controller の Web UI や API の提供し、実行ノード(後述)にジョブの実行を指示する。プロジェクトの更新のようなコントロールプレーンの処理はこのノード内で行われる
実行ノード(Execution node) 実際にジョブを実行するノード。コントロールノードからの指示を受ける
ホップノード(Hop node) コントロールノードと実行ノードの間を取り持つノード
ハイブリッドノード(Hybrid node) コントロールノードと実行ノードの役割を兼ね備えたノード。AAP 2.1 のインストーラーでは、デフォルトで localhost がハイブリッドノードになる

各ノードは必ず分離しといけないというわけではなく、環境の状況に応じて使い分けます。

たとえば、シンプルにハイブリッドノードだけで事が足りることもあるでしょうし、コントロールノード、と実行ノードを分けたほうがいいこともあるでしょう。はたまた、ホップノードを挟んで延伸したほうがいいここともあるでしょう。

■ 2. 今回の環境 (コントロールノードと実行ノードの分類)

この記事ではコントロールノードと実行ノードそれぞれ1台ずつの構成をとります。ホップノードは挟みません。

mesh と呼べるほどではないですが、これまでハイブリッドノード構成から役割を分離する構成として、最低限の一番シンプルな構成で試してみよう、というのが趣旨です。

登場人物やそれぞれのノードと役割は以下のとおりです。

役割と動作

各動作の説明です。

No. 動作 説明
(1) ブラウザからジョブテンプレート実行指示 Automation Controller の利用者が Web UI や API を利用して、ジョブテンプレートの実行を指示する
(2) ジョブテンプレート実行開始 利用者からの指示によってジョブテンプレートの実行を開始
(3) プロジェクト更新用EEイメージpull プロジェクト更新に利用する EE(Execution Environment) のイメージを(手元になければ)pullする。利用するイメージは Automation Controller の画面の [実行環境] > [Control Plane Execution Environment] で定義されている registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest
(4) プロジェクト更新用EE起動 プロジェクト更新用EEを起動する
(5) プロジェクト更新 プロジェクトの SCM タイプが git の場合は、リポジトリからプロジェクトを更新する
(6) コレクションダウンロード プロジェクト内の collections/requirements.ymlに利用するコレクションが定義されている場合にコレクションをダウンロードする。デフォルトでは Ansible Galaxy から(今回の構成も)
(7) ジョブ実行指示 コントロールノードから実行ノードに対してジョブの実行を指示する。デフォルトでは TCP 27199 ポートを利用する
a. ダイナミックインベントリ更新用EEイメージpull ダイナミックインベントリ(インベントリ内の「ソース」)があり「起動時の更新」が有効の場合はイメージをpull。デフォルトでは Control Plane Execution Environment に定義の registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest を利用?(Default Execution Environment と同じイメージなので区別が付かない・・ )
b. ダイナミックインベントリ更新用EE起動・更新 a. の続きでダイナミックインベントリを更新。(7) と a. b. の順序関係が分からずこのあたりは数字表記ではない・・。※またこの処理が実行ノードで実行されるのかどうかは少々自信なし
(8) ジョブ実行用EEイメージpull ジョブ実行に利用する EE のイメージを(手元になければ)pullする。利用するイメージは Automation Controller の画面の [実行環境] > [Default Execution Environment] で定義されている registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest 。結果的にデフォルトでは Control Plane Execution Environment と同じイメージ
(9) ジョブ実行用EE起動 ジョブ実行用のEEを起動する
(10) Playbookによる操作 Playbook 実行による操作。今回は Cisco IOSルーターに対して SSH で操作する

今回は試せていませんが、ダイナミックインベントリの更新は、実行ノード側でされるそうです(少々自信なし)。

(2023/12/04 追記)ただ、AAP 2.1 の Automation mesh のドキュメントには control nodes run project and inventory updates and system jobs, but not regular jobs. とある。

なお、点線で示しているとおりコントロールノードからマネージドノードへ直接アクセスできない構成です。マネージドノードとアクセスできる側に実行ノードを置くことで、コントロールノードから間接的にマネージドノードを制御できるようになります。

今回構築するコントロールノードと実行ノード1台ずつの構成では、信頼性は特に向上しないと思いますが、事情があってAutomation Controller から直接マネージドノードにアクセスできないという場合には、解決策になりそうです(公式ブログ What's new: an introduction to automation mesh)でいうDesign for your enterprise)。

■ 3. 下準備

RHEL を2台(コントロールノード、実行ノード)用意した状態からはじめます。

3.1. subscription-manage による作業

subscription-managerregisterattach をして、AAP をインストールできる状態にしておきます。コントロールノード、実行ノードともに必要な作業です。(後述しますが今回AAPのインストーラーはバンドル版ではなく、通常版を利用します。)

# コントロールノード・実行ノード両方
sudo subscription-manager register           # 要ログイン
sudo subscription-manager list --available   # AAPが含まれるプールIDを控える
sudo subscription-manager attach --pool AAPが含まれるプールID

実行ログ

$ sudo subscription-manager register
Registering to: subscription.rhsm.redhat.com:443/subscription
Username: (ユーザー名を入力)
Password: (パスワードを入力)
The system has been registered with ID: xxxxx
The registered system name is: xxxxx
$ sudo subscription-manager list --available
  (いろいろPoolが表示される)
$ sudo subscription-manager attach --pool AAPが含まれるプールID
Successfully attached a subscription for: Red Hat Developer Subscription for Individuals

加えて、AWS 側に構築したコントロールノード側は明示的にリポジトリ有効化をしておきます。(参考ツイート、ありがとうございます)

# コントロールノード(AWS)側のみ
sudo subscription-manager config --rhsm.manage_repos=1

3.2. SSHキーの接続

あとのインストールの中で、コントロールノードからノードに Ansible による SSH 接続が行われます。そのため、認証できる状態にしておく必要があります。

今回は公開鍵認証方式で準備します。キーペアが未作成、未登録の状態から始めているので、以下コマンドでキーペアを作成して、実行ノードに登録します。

# コントロールノード側のみ
ssh-keygen -t rsa
ssh-copy-id admin@実行ノードのグローバルIP

実行ノードに対して Ansible からパスワード認証でログインできる状態であれば特にこの作業は不要です。

■ 4. インストール

コントロールノード側で作業します。

4.1. インストーラーの準備

Automation Controller のインストールには AAP のインストーラーを利用します。

AAP 2.1 の公式ドキュメントの「RED HAT ANSIBLE AUTOMATION PLATFORM インストーラーの選択および取得」を参考にして、インストーラーをダウンロードして「コントロールノード」に配置します。

今回はバンドル版ではないインストーラansible-automation-platform-setup-2.1.1-1.tar.gz を利用します。

配置後、解凍して、ディレクトリを移動します。

# コントロールノード側作業
tar xvzf ansible-automation-platform-setup-2.1.1-1.tar.gz
cd ansible-automation-platform-setup-2.1.1-1

4.2. inventory の修正(構成の指定)

AAP のインストーラーは、設定ファイルとしてインベントリファイル inventory を利用します。先ほど移動したディレクトansible-automation-platform-setup-2.1.1-1 にあります。

このファイルの中で、コントロールノード、実行ノードのホスト、各種パスワードなどの指定をします。

今回の構成は、公式ドキュメント「Red Hat Ansible Automation Platform 自動化メッシュガイド」内の「単一の実行ノードを持つ単一ノードのコントロールプレーン」と同じなので、その inventory をベースにしてます。

ポイントだけ抜粋します。

[automationcontroller]
localhost ansible_connection=local

[automationcontroller:vars]
node_type=control
peers=execution_nodes

[execution_nodes]
rhel84ace2 ansible_host=実行ノードのグローバルIP ansible_user=admin ansible_ssh_private_key_file=/home/ec2-user/.ssh/id_rsa  ansible_become=yes ansible_become_password=昇格パスワード

# ...(略)...
[all:vars]
admin_password='Automation Controllerへのadminパスワード'

# ...(略)...
pg_password='DBのパスワード'

# ...(略)...
registry_url='registry.redhat.io'
registry_username='registry.redhat.ioへのユーザー名'
registry_password='registry.redhat.ioへのパスワード'

各セクションでの指定の説明は以下のとおりです。なお、今回インストーラーはコントロールノードで実行するため localhost はコントロールノードを指します。

セクション 説明
[automationcontroller] localhost がデフォルトで定義されていてそのまま利用
[automationcontroller:vars] 今回は localhost をコントロールノードとして分離したいので node_type=control を指定。デフォルトは node_type=hybrid 相当で、ハイブリッドノード(コントロールノード兼実行ノード)になる
[execution_nodes] 実行ノードを指定する。インストーラー内部で Playbook が呼ばれ、ここで指定したノードに接続、インストールするため、Ansible的なお作法で接続できるようにしておく必要がある。要 root 権限。利用するユーザーや権限に応じて要変更
[all:vars] 特にノードの構成とは関係なく定義するもの。デフォルトのハイブリッドノードの構成でインストールするときと同じ

execution_nodes グループに所属するホストに対して、対応する SSH ホストキーがコントロールノード上に登録されていない場合、ホストキーチェックで一時停止します。これを防ぐには、あらかじめホストキーを登録しておくか、ansible.cfghost_key_checking=False を指定するなどして対策をしておきます。Ansibleの一般的な対応方法と同じです。

また、インストール中にコントロールノードから実行ノードへのレセプター経由の通信テストが行われます。そのため、あらかじめ実行ノードへの通信経路上で SSH だけでなくTCP 27199ポートが許可されるようにしておく必要があります。

4.3. インストーラーの実行

それでは、インストーラの実行です。ansible-automation-platform-setup-2.1.1-1 ディレクトリのまま以下のコマンドを実行します。

sudo ./setup.sh

今回の環境では、15-20分ほどかかりました。

初めて実行したときは以下のエラーで止まってしまいました。実行ノードへの TCP 27199 は開放していたのですが・・。

TASK [ansible.automation_platform_installer.receptor : Validate connectivity for Mesh peers] ***
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (10 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (9 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (8 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (7 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (6 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (5 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (4 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (3 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (2 retries left).
FAILED - RETRYING: [localhost]: Validate connectivity for Mesh peers (1 retries left).
failed: [localhost] (item=rhel84ace2) => {"ansible_loop_var": "item", "attempts": 10, "changed": true, "cmd": ["receptorctl", "--socket", "/var/run/awx-receptor/receptor.sock", "ping", "実行ノードのグロバル", "--count", "1"], "delta": "0:00:00.137918", "end": "2022-03-19 06:49:42.683413", "failed_when_result": true, "item": "rhel84ace2", "msg": "non-zero return code", "rc": 2, "start": "2022-03-19 06:49:42.545495", "stderr": "", "stderr_lines": [], "stdout": "Error: no route to node", "stdout_lines": ["Error: no route to node"]}
...ignoring

...(略)...

TASK [ansible.automation_platform_installer.receptor : Report error when mesh connectivity issue is detected] ***
fatal: [localhost]: FAILED! => {"changed": false, "msg": "An error was detected on Controller Mesh network. Please verify the task output above for further details."}
skipping: [rhel84ace2] => {"changed": false, "skip_reason": "Conditional result was False"}

...(略)...

PLAY RECAP *********************************************************************
localhost                  : ok=258  changed=129  unreachable=0    failed=1    skipped=141  rescued=0    ignored=7   
rhel84ace2                 : ok=77   changed=35   unreachable=0    failed=0    skipped=53   rescued=0    ignored=1  

特に何もせず、もう一度インストーラーを実行したら最後まで正常に完了したため、ポート開放状況の問題ではなさそうででした。

正常完了すると最後はこんなログが表示されました。

PLAY RECAP *********************************************************************
localhost                  : ok=244  changed=53   unreachable=0    failed=0    skipped=162  rescued=0    ignored=0   
rhel84ace2                 : ok=68   changed=10   unreachable=0    failed=0    skipped=62   rescued=0    ignored=0   

The setup process completed successfully.
Setup log saved to /var/log/tower/setup-2022-03-19-10:16:41.log.

権限昇格不足だとこんなエラーに

今回の inventory[execution_nodes] で指定したユーザーの場合、ansible_become による権限昇格が必要でしたが、指定し忘れたときは以下のエラーが表示されました。内部で uid でチェックしているようです。

TASK [ansible.automation_platform_installer.config_dynamic : Ensure user is root] ***
skipping: [localhost] => {"changed": false, "skip_reason": "Conditional result was False"}
fatal: [rhel84ace2]: FAILED! => {"changed": false, "msg": "UID on remote machine is 1000 (0 required). Check Ansible connection and become settings."}

4.5. 構成図の出力(オマケ)

オマケ的な位置づけですが、inventory で指定した、各ノードの構成図を Graphviz の dot ファイルで生成する機能が、インストーラーにあります。

 ./setup.sh -- -t generate_dot_file

この方法は、インストーラー内で実行される Playbook の構成図作成処理に generate_dot_file タグが付いているため、そのタグを指定しています。インストーラーのコマンドの -- の後に、インストーラー内部の ansible-playbook コマンドのオプションを渡せる性質を利用しています。構成図作成処理には never タグも付いているため、デフォルトでは図が作成されません。

今回の構成の場合は、以下の mesh-topology.dot が生成されました。

$ cat mesh-topology.dot 
strict digraph "" {
    rankdir = TB
    node [shape=box];
    subgraph cluster_0 {
        graph [label="Control Nodes", type=solid];
        {
            rank = same;
            "localhost";
        }
    }

    "rhel84ace2";
    "localhost" -> "rhel84ace2";
}

描画するこのようになります。(こちらのサイトを利用)

コントロールノード、実行ノードそれぞれ1台のシンプルな構成

なお、inventory[automationcontroller:var] で、node_typehybridcontrol 以外の値を指定したときは以下のエラーが表示されました。実際はただのスペルミスでした。

TASK [Parse Mesh] **************************************************************
fatal: [localhost]: FAILED! => {"msg": "Receptor node localhost has an invalid node_type for group automationcontroller, it must be one of the following: hybrid, control"}

この構成図の作成機能でも、ファクト収集が実行され、実行ノードへのSSH接続がされます。そのため、実際のインストールの前に、構成図を出力して、接続や構成の確認するのはアリかもしれません。

■ 5. 状態確認

インストールが無事にできたようなので、いろいろ状態を確認します。すべてコントロールノードでの作業です。

5.1. API による状態確認

まず手始めに API での確認です。

API/api/v2/ping/を叩くと、インスタンスグループとして各ノードの情報が表示されます。認証情報も不要なので、とても手軽に確認できます。

コントロールノードに対してGETで実行します。

https://コントロールノードのグローバルIP/api/v2/ping/

結果は以下のとおりです。instances 配下にノードが2台あり、node_type が実行ノードでは、execution、コントロールノードでは control であることが分かります。

{
    "ha": false,
    "version": "4.1.1",
    "active_node": "localhost",
    "install_uuid": "xxx",
    "instances": [
        {
            "node": "実行ノードのグローバルIP",
            "node_type": "execution",   // ポイント
            "uuid": "yyy",
            "heartbeat": "2022-03-19T10:14:06.737391Z",
            "capacity": 57,
            "version": "ansible-runner-2.1.1"
        },
        {
            "node": "localhost",
            "node_type": "control",   // ポイント
            "uuid": "zzz",
            "heartbeat": "2022-03-19T10:14:06.678438Z",
            "capacity": 55,
            "version": "4.1.1"
        }
    ],
    "instance_groups": [
        {
            "name": "controlplane",
            "capacity": 55,
            "instances": [
                "localhost"
            ]
        },
        {
            "name": "default",
            "capacity": 57,
            "instances": [
                "実行ノードのグローバルIP"
            ]
        }
    ]
}

なお、ハイブリッドノードで構築(デフォルト)した場合、instancesnode_type の値は hybrid になります。

5.2. receptorctl コマンドによる状態確認

Automation mesh 内のノード感の通信状況のなどの操作をする receptorctl というコマンドがあります。 前述のウェビナーで知りました。

pingtraceroutestatus を確認します。

ping の結果は以下のとおりです。正常に返ってきています。

$ sudo su - awx   # awx ユーザーに切り替え
$ receptorctl --socket /var/run/awx-receptor/receptor.sock ping 実行ノードのグローバルIP
Reply from 実行ノードのグローバルIP in 139.429964ms
Reply from 実行ノードのグローバルIP in 140.613656ms
Reply from 実行ノードのグローバルIP in 139.723559ms
Reply from 実行ノードのグローバルIP in 139.933604ms

通信経路上で TCP 27199 を閉めたり、実行ノード上で sudo systemctl stop receptor すると、Error: timeoutError: no route to node になりました。

traceroute の結果は以下のとおりです。ホップノードを挟んでいないのであまりおもしろい結果ではないです。

$  receptorctl --socket /var/run/awx-receptor/receptor.sock traceroute 実行ノードのグローバルIP
0: localhost.localdomain in 76.941µs
1: 実行ノードのグローバルIP in 139.982863ms

あくまで Automation mesh のノードとしての経路を示すので、IPレベルの traceroute とは経路の見え方が異なります。

status の結果は以下のとおりです。正しく認識していそうな表示です。Cost は、メッシュ構成のどの経路を優先するかを決めるもののようです。ルーティングと似ていますね。

$ receptorctl --socket /var/run/awx-receptor/receptor.sock status
Node ID: localhost.localdomain
Version: 1.1.1
System CPU Count: 2
System Memory MiB: 7556

Connection            Cost
実行ノードのグローバルIP        1

Known Node            Known Connections
実行ノードのグローバルIP        {'localhost.localdomain': 1}
localhost.localdomain {'実行ノードのグローバルIP': 1}

Route                 Via
実行ノードのグローバルIP        実行ノードのグローバルIP

Node                  Service   Type       Last Seen             Tags
localhost.localdomain control   StreamTLS  2022-03-19 11:16:39   {'type': 'Control Service'}
実行ノードのグローバルIP        control   StreamTLS  2022-03-19 20:07:28   {'type': 'Control Service'}

Node                  Secure Work Types
localhost.localdomain local, kubernetes-runtime-auth, kubernetes-incluster-auth
実行ノードのグローバルIP        ansible-runner

なお、receptorctl --help を表示すると、他にも connectreloadversionwork というコマンドがありました。

Commands:
  connect     Connect the local terminal to a Receptor service on a remote...
  ping        Ping a Receptor node.
  reload      Reload receptor configuration.
  status      Show the status of the Receptor network.
  traceroute  Do a traceroute to a Receptor node.
  version     Show version information for receptorctl and the receptor node
  work        Commands related to unit-of-work processing

5.3. Web UI にる状態確認

今度は、Automation Controller の Web UI(コントロールノード)での確認をします。

ライセンス認証がまだの場合は済ませておきます。今回はマニフェストファイルを利用しました。

パッと見はハイブリッドノードで構築したときと変わりませんが、違いはインスタンスグループ画面に出ます。

[管理] > [インスタンスグループ] 画面には、control planedefault というインスタンスグループが表示されます。この内 default をクリックします。

インスタンスグループ default をクリック

インスタンスグループの詳細画面が表示されるので、インスタンス タブをクリックします。

インスタンスグループ default で「インスタンス」をクリック

インスタンスの一覧が表示されます。実行ノードとして指定したノードがあることが分かります。インストーラーの inventoryansible_host 変数に指定した実行ノードのグローバルIPアドレスの値が、インスタンス名として利用されていました。

インスタンス一覧

なお、ハイブリッドノードとして構築した場合はこの画面では localhost のみでした。

更にインスタンス名をクリックすると、詳細が表示されます。定期的にヘルスチェックが行われるようで、状態は良好のようでした。眺めてるとヘルチェックは1分間隔のようでした。

実行ノードインスタンスの詳細

あくまで Web UI を持つのはコントロールノードなので、実行ノードには http アクセスできません。

5.4. パケットレベルのコマンドによる状態確認(オマケ)

これはオマケ的な扱いですが、実行ノード上で tcpdump を眺めていると、コントロールノードとコネクションがはられた状態のまま、10秒間隔でパケットが飛んでいました。 ポーリングのようなものでしょうか。Automation Controller の Web UI で確認できるヘルスチェックの間隔ともまた異なるようです。

契機となるパケットの向きは、以下のように [コントロールノード] > [実行ノード:27199] のときもあれば、逆の時もありました。なにか条件によって変わるのかもしれませんが、詳細は不明です。rhel84ace2 が実行ノードです。

19:56:34.311143 IP コントロールノードのグローバルIP.33580 > rhel84ace2.27199: Flags [P.], seq 341:574, ack 241, win 849, options [nop,nop,TS val 1363547663 ecr 2963536384], length 233
19:56:34.311176 IP rhel84ace2.27199 > コントロールノードのグローバルIP.33580: Flags [.], ack 574, win 1432, options [nop,nop,TS val 2963542674 ecr 1363547663], length 0
19:56:34.381586 IP rhel84ace2.27199 > コントロールノードのグローバルIP.33580: Flags [P.], seq 241:467, ack 574, win 1432, options [nop,nop,TS val 2963542744 ecr 1363547663], length 226
19:56:34.521230 IP コントロールノードのグローバルIP.33580 > rhel84ace2.27199: Flags [.], ack 467, win 849, options [nop,nop,TS val 1363547874 ecr 2963542744], length 0
19:56:44.310948 IP コントロールノードのグローバルIP.33580 > rhel84ace2.27199: Flags [P.], seq 574:807, ack 467, win 849, options [nop,nop,TS val 1363557663 ecr 2963542744], length 233
19:56:44.310969 IP rhel84ace2.27199 > コントロールノードのグローバルIP.33580: Flags [.], ack 807, win 1432, options [nop,nop,TS val 2963552674 ecr 1363557663], length 0
19:56:44.382521 IP rhel84ace2.27199 > コントロールノードのグローバルIP.33580: Flags [P.], seq 467:693, ack 807, win 1432, options [nop,nop,TS val 2963552745 ecr 1363557663], length 226
19:56:44.522032 IP コントロールノードのグローバルIP.33580 > rhel84ace2.27199: Flags [.], ack 693, win 849, options [nop,nop,TS val 1363557875 ecr 2963552745], length 0
19:56:54.311047 IP コントロールノードのグローバルIP.33580 > rhel84ace2.27199: Flags [P.], seq 807:1040, ack 693, win 849, options [nop,nop,TS val 1363567664 ecr 2963552745], length 233
19:56:54.311080 IP rhel84ace2.27199 > コントロールノードのグローバルIP.33580: Flags [.], ack 1040, win 1432, options [nop,nop,TS val 2963562674 ecr 1363567664], length 0
19:56:54.383541 IP rhel84ace2.27199 > コントロールノードのグローバルIP.33580: Flags [P.], seq 693:919, ack 1040, win 1432, options [nop,nop,TS val 2963562746 ecr 1363567664], length 226
19:56:54.523149 IP コントロールノードのグローバルip.33580 > rhel84ace2.27199: Flags [.], ack 919, win 849, options [nop,nop,TS val 1363567876 ecr 2963562746], length 0

逆のときの例(別の環境ですが rhel84ace が実行ノード) https://twitter.com/akira6592/status/1504827993528889344/photo/1

■ 6. 動作確認1: Demo Job Template

ようやく、ジョブテンプレートの実行です。なるべく単純なもので試したかったので、デフォルトで存在するジョブテンプレートを試しました。

デモプロジェクト Demo Project (リポジトリ https://github.com/ansible/ansible-tower-samples)を参照し、localhost で debug メッセージを表示するだけのものです。

6.1. プロジェクト更新がいつの間に失敗

さてジョブを実行しよう、と思ったのですが、プロジェクトの更新が失敗していることに気が付きました。とくに更新の操作はしていませんが。詳細は不明です。

Demo Project の初期のエラー

更新を再実行したら正常になりました。

6.2. ジョブテンプレート実行

気を取り直して、Web UI から Demo Job Template を起動します。

結果はこちら。

Demo Job Template の起動

うまくいったようです。

若干気になるのが、ジョブ実行画面の詳細画面で以下のメッセージが表示されている点です。

Task was marked as running but was not present in the job queue, so it has been marked as failed.

気になるメッセージ

再実行したら先のメッセージは表示されなくなりました。何度か試して見る限り、実行ノードにイメージがない状態でpullからはじめるとこのエラーが表示される傾向がありました。再実行で解消しても、イメージを削除して再実行すると再現しました。

再実行で解消

イメージpullなどの様子

ジョブテンプレート実行によってイメージが pull されることなどを確認しました。それぞれ awx ユーザーでの確認です。

コントロールノード上

ジョブの実行前は何もイメージがない状態です。

# コントロールノード
$ podman images
REPOSITORY  TAG         IMAGE ID    CREATED     SIZE

ジョブ実行中の podman ps です。これはプロジェクト更新によるもののはずです。特に利用するイメージを指定していないため、実行環境 Control Plane Execution Environment で指定された registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest が利用されています。

# コントロールノード
$ podman ps
CONTAINER ID  IMAGE                                                                        COMMAND               CREATED       STATUS           PORTS       NAMES
16c6fdd371a7  registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest  ansible-playbook ...  1 second ago  Up 1 second ago              ansible_runner_8

ジョブ実行後、イメージが残っています。

# コントロールノード
$ podman images
REPOSITORY                                                            TAG         IMAGE ID      CREATED     SIZE
registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8  latest      2fa77afffbf6  4 days ago  1.17 GB

実行ノード上

ジョブの実行前は何もイメージがない状態です。

# 実行ノード
$ podman images
REPOSITORY  TAG         IMAGE ID    CREATED     SIZE

ジョブ実行中の podman ps です。これはジョブ本体の実行によるもののはずです。特に利用するイメージを指定していないため、実行環境 Default Execution Environment で指定された registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest が利用されています。結果的に Control Plane Execution Environment で指定したイメージと同じになっています。

# 実行ノード
$ podman ps
CONTAINER ID  IMAGE                                                                        COMMAND               CREATED                 STATUS                     PORTS       NAMES
36745a921bc9  registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest  ansible-playbook ...  Less than a second ago  Up Less than a second ago              ansible_runner_9

ジョブ実行後、イメージが残ってます。

# 実行ノード
$ podman images
REPOSITORY                                                            TAG         IMAGE ID      CREATED     SIZE
registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8  latest      2fa77afffbf6  4 days ago  1.17 GB

■ 7. 動作確認2: 家の中のマネージドノードを操作するジョブテンプレート

いよいよ、本命のジョブテンプレートの実行を試します。マネージドノードとなる Cisco IOS の機器は、コントロールノードがら IP 的に直接アクセスできない家の中にあります。

7.1. 各種設定

先程試したデモ用とは異なり、以下の工夫を仕込みます。

  • ジョブの実行の EE には Minimal execution environment で定義している、registry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8:latestを利用
    • この EE には cisco.ios コレクションは含まれていない
  • collections/requirements.yml によるコレクションのダウンロード
    • これにより、Minimal execution environment でも cisco.ios コレクションが利用できるようになる
  • スタティックなインベントリ定義に加え、ダイナミックなインベントリプラグイン azure.azcollection.azure_rm を利用
    • マネージドノードが家の機器であることをわかりやすくするため、実際に操作するマネージドノードはスタティックに定義
    • azure.azcollection.azure_rm の方は、ダイナミックインベントリの更新がどのノードで行わるかの確認用

プロジェクト設定

git 連携のプロジェクトを作成します。

collections/requirements.yml には、cisco.ios コレクションをダウンロードするための定義をしてあります。コントロールノード上でこの定義にしたがってダウンロードされます。

---
collections:
  - name: cisco.ios
    version: 2.8.0

他、show コマンドを実行して debug 表示するだけの Playbook などがあります。

認証情報設定

2つの認証情報を作成します。

  1. Cisco IOSルーターへの接続に利用する認証情報(タイプ: マシン)
  2. azure.azcollection.azure_rm インベントリプラグイン用の認証情報(タイプ: Microsoft Azure Resource Manager)

インベントリー設定

インベントリーオブジェクトとして inv_main を作成し、その中にスタティック定義とダイナミックな定義(インベントリソース)をします。

  1. 家の Cisco IOSルーター ios01 を定義
    • ansible_host 変数に 192.168.1.11 を指定、このアドレスはコントロールノードからはアクセス不可だが、実行ノードからはアクセス可
  2. azure.azcollection.azure_rm インベントリプラグインを利用するインベントリソースを定義
    • 認証情報には、先程作成した タイプ Microsoft Azure Resource Manager の認証情報を指定
    • 「起動時の更新」にチェックを入れる
    • 実行環境は特に指定しない
    • 前述の通り、こちらはダイナミックインベントリ更新がどのノードでされるかの確認用なので、ジョブからは利用しない

ソースの設定

ジョブテンプレート設定

これまで作成した、インベントリー、プロジェクト、認証情報を指定します。

Playbook には、Cisco IOSルーターに show コマンドを実行して debug 表示するだけのものを指定します。show コマンドの実行には、cisco.ios コレクションのモジュールを利用します。

また、実行環境には Minimal execution environment を指定します。イメージは registry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8:latest です。 デフォルトの Default execution environment 定義したイメージ registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest とは異なり、cisco.ios コレクションが入っていません。ですが、前述の通り、プロジェクト内の collections/requirements.ymlcisco.ios を定義しているため、動的にダウンロード後に利用可能になるという仕組みです。

ジョブテンプレートの設定として「インスタンスグループ」もありますが、今回は指定なしにしてみます。

ジョブテンプレートの作成

7.2. ジョブテンプレート実行

さて、実行です。通常通りジョブテンプレートを実行します。うまく実行できたようです。

ジョブテンプレートの実行結果 - 出力

ジョブテンプレート実行結果 - 詳細

実行ノード上での awx ユーザーでいくつか確認します。

イメージpullなどの様子

コントロードノード上

ジョブ実行中の podman ps は以下の通りです。おそらくプロジェクト更新と、collections/requirements.yml の定義に基づくコレクションのダウンロードしているものかと思います。

# コントロールノード
$ podman ps
CONTAINER ID  IMAGE                                                                        COMMAND               CREATED         STATUS             PORTS       NAMES
3cf5dcde1a65  registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest  ansible-playbook ...  19 seconds ago  Up 19 seconds ago              ansible_runner_230

実行ノード上

ジョブ実行中の podman ps です。 2段階あります。

1段階目は、ダイナミックインベントリの更新です。COMMANDansible-inventory になっていることからそう判断しました(ドキュメントなどで正確に知りたいところ)。タイミング的には、コントロールノード側で処理のあとでした。

# 実行ノード
CONTAINER ID  IMAGE                                                                        COMMAND               CREATED        STATUS            PORTS       NAMES
5e0850bc6a5f  registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:latest  ansible-inventory...  9 seconds ago  Up 9 seconds ago              ansible_runner_231

2段階目は、実際のジョブの実行です。ジョブテンプレートの実行環境で指定した、ee-minimal-rhel8 のほうのイメージのコンテナが起動していることが分かります。

# 実行ノード
CONTAINER ID  IMAGE                                                                      COMMAND               CREATED        STATUS            PORTS       NAMES
e663d893937f  registry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8:latest  ansible-playbook ...  3 seconds ago  Up 3 seconds ago              ansible_runner_229

ジョブ実行後、イメージが残ってます。

# 実行ノード
$ podman images
REPOSITORY                                                            TAG         IMAGE ID      CREATED     SIZE
registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8  latest      2fa77afffbf6  6 days ago  1.17 GB
registry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8    latest      d8b3521c4042  6 days ago  394 MB

インベントリーの確認

ジョブテンプレート実行後、想定通り azure.azcollection.azure_rm インベントリプラグインによるホストが追加されました。

Azure 上の VM が追加されている

collections/requirements.yml の定義 ないとエラー(オマケ)

なお、collections/requirements.yml を削除して再実行したら、想定通りモジュールが見つからない旨のエラーになりました。EE Minimal execution environment で実行されたことが、このことからも分かります。

まとめ・雑感

長くなりましたが、AAP 2.1 で導入された Automation mesh を試しました。シンプルにコントロールノード、実行ノードそれぞれ1台ずつの構成でした。

分離させることによって、なにがどちらのノードの実行させるのかが、調べたり試したりすることによって少し理解できいました。

今回の構成では、コントロールノードが直接アクセスできない構成でも、実行ノードを経由することによって制御可能になる、という点がメリットだと思います。

実行ノードが社内LANにより近い側に置かれると思いますが、依然としてコンテナレジストリへのアクセスが必要なのでインターネット接続性が必要です。もし何らかの事情で、インターネット接続性がない場合は、イメージ予めローカルに置いておくか、アクセスできる範囲に Private Automation Hub や GitLab などのコンテナレジストリを配置するかという形にになるかと思います。

今回はじめて Automation mesh を試しましたが、まだ以下の疑問が残っています。機会があれば調べてみたいと思います。

  • 実行ノードでコンテナレジストリにアクセスするための認証情報はどこからくるのか
    • 毎回 コントロールノードからくるのか、インストール時に実行ノード側に保存されるのか
  • 各ノードを追加、削除する方法
  • ジョブ実行時の例のメッセージの詳細
    • Task was marked as running but was not present in the job queue, so it has been marked as failed.

  • ダイナミックインベントリ更新に利用されるデフォルトイメージは Default Execution Environment のものか Control Plane Execution Environment のものか
    • 実質同じイメージであり、変更もできないのであまり気にする必要もなさそう

参考資料

www.ansible.com www.ansible.com access.redhat.com events.redhat.com

[Ansible] ansible-lint 6.0.0 のインストールで ansible-core 2.12.3 も一緒にインストールされる

はじめに

先日 ansible-lint 6.0.0 がリリースされました。

github.com

.config/ansible-lint.yml を読み込むようになったり、ansible 2.9 や Python3.6、3.7 がサポートされなくなったり、フォーマット機能がつくなど変更がありました。

また、インストールしたときにも気がついたのですが、ansible-core をセットでインストールするようになりました。

Made ansible-core a direct dependency (#1888) @ssbarnea

インストールのドキュメントからは、

You need to either install the desired version of Ansible yourself or mention one of the helper extras:

とういう記載がなくなりました

ansible-lint 6.0.0 をインストールすることによって、ansible-core 2.12.3 もインストールされることを試したので結果をまとめます。

  • 動作確認環境

検証1: ほぼ素の venv から

素の venv に pip install pip --upgrade だけした状態から始めます。

事前

% pip list
Package    Version
---------- -------
pip        22.0.4
setuptools 60.5.0

ansible-lint 6.0.0 インストールとその後

ansible-lint をインストールします。現在は私の環境(Python 3.9.10) 6.0.0 がインストールされます。

% pip install ansible-lint
Collecting ansible-lint
  Using cached ansible_lint-6.0.0-py3-none-any.whl (136 kB)
Collecting wcmatch>=7.0
  Using cached wcmatch-8.3-py3-none-any.whl (42 kB)
Collecting pyyaml
  Using cached PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl (197 kB)
Collecting ansible-core>=2.12.0
  Using cached ansible-core-2.12.3.tar.gz (7.8 MB)
...(略)...

インストール後、確認すると ansiblec-core 2.12.3 もインストールされたことが確認できます。

% pip list                
Package          Version
---------------- -------
ansible-compat   2.0.0
ansible-core     2.12.3   # ここ
ansible-lint     6.0.0
bracex           2.2.1
...(略)...
yamllint         1.26.3

別のchangelogにも記載がありましたが、yamllint 入りますね。

検証2: ansible-core 2.11 系インストールの状態から

次は pip install pip --upgrade 後に

pip install ansible-core==2.11.9 

を実行した状態から始めます。

事前

ansible-core 2.11.9 がインストールされています。

 % pip list
Package      Version
------------ -------
ansible-core 2.11.9
cffi         1.15.0
cryptography 36.0.2
Jinja2       3.0.3
MarkupSafe   2.1.1
packaging    21.3
pip          22.0.4
pycparser    2.21
pyparsing    3.0.7
PyYAML       6.0
resolvelib   0.5.4
setuptools   60.5.0

ansible-lint 6.0.0 インストールとその後

ansible-lint をインストールします。途中、もともと入っていた ansibl-core 2.11.9 がアンインストールされるログも見受けられます。

% pip install ansible-lint
Collecting ansible-lint
  Using cached ansible_lint-6.0.0-py3-none-any.whl (136 kB)
Collecting ansible-core>=2.12.0
  Using cached ansible-core-2.12.3.tar.gz (7.8 MB)
  Preparing metadata (setup.py) ... done
...(略)...
Using legacy 'setup.py install' for yamllint, since package 'wheel' is not installed.
Installing collected packages: commonmark, subprocess-tee, ruamel.yaml.clib, pygments, pathspec, bracex, yamllint, wcmatch, ruamel.yaml, rich, ansible-compat, enrich, ansible-core, ansible-lint
  Running setup.py install for yamllint ... done
  Attempting uninstall: ansible-core
    Found existing installation: ansible-core 2.11.9
    Uninstalling ansible-core-2.11.9:
      Successfully uninstalled ansible-core-2.11.9
...(略)...

インストール後、確認すると ansible-core 2.12.3 もインストールされたことが確認できます。

% pip list                
Package          Version
---------------- -------
ansible-compat   2.0.0
ansible-core     2.12.3   # ここ
ansible-lint     6.0.0
bracex           2.2.1
...(略)...
yamllint         1.26.3

ansibleコマンド の バージョン表記も 2.12.3 になります。

 % ansible --version
ansible [core 2.12.3]

検証3: ansible 2.9 系インストールの状態からだとエラーに

一応・・。

今度は pip install pip --upgrade 後に

pip install ansible==2.9.27

を実行した状態から始めます。ansible 2.9 系からです。

事前

ansible 2.9.27 がインストールされている状態です。

 % pip list
Package      Version
------------ -------
ansible      2.9.27
cffi         1.15.0
cryptography 36.0.2
Jinja2       3.0.3
MarkupSafe   2.1.1
pip          22.0.4
pycparser    2.21
PyYAML       6.0
setuptools   60.5.0

ansible コマンドのバージョン表記も 2.9.27 です。

% ansible --version
ansible 2.9.27

ansible-lint 6.0.0 インストール(エラー)とその後

ansible-lint をインストールしようと試みます。エラーになりました。ansible 2.10 でパッケージの分け方が変更された関係で、ansible 2.9 以前から 2.10 以降にアップグレードする際は、いったん ansible をアンインストールしてくださいという件です。なので、ansible-lint そのものの事情というより、ansible の事情ということかなと思います。

ansible

% pip install ansible-lint
Collecting ansible-lint
  Using cached ansible_lint-6.0.0-py3-none-any.whl (136 kB)
Collecting yamllint>=1.25.0
  Using cached yamllint-1.26.3.tar.gz (126 kB)
  Preparing metadata (setup.py) ... done
...(略)...
Installing collected packages: resolvelib, commonmark, subprocess-tee, ruamel.yaml.clib, pyparsing, pygments, pathspec, bracex, yamllint, wcmatch, ruamel.yaml, rich, packaging, ansible-compat, enrich, ansible-core, ansible-lint
  Running setup.py install for yamllint ... done
  Running setup.py install for ansible-core ... error
  error: subprocess-exited-with-error
  
  × Running setup.py install for ansible-core did not run successfully.
  │ exit code: 1
  ╰─> [28 lines of output]
      Traceback (most recent call last):
        File "<string>", line 2, in <module>
        File "<pip-setuptools-caller>", line 34, in <module>
        File "/private/var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/pip-install-47xu8j2h/ansible-core_1efb8a412bd249b9a33bf132097bea90/setup.py", line 120, in <module>
          _validate_install_ansible_core()
        File "/private/var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/pip-install-47xu8j2h/ansible-core_1efb8a412bd249b9a33bf132097bea90/setup.py", line 91, in _validate_install_ansible_core
          raise RuntimeError(
      RuntimeError:
      
          ****************************************************************************
      
          Cannot install ansible-core with a pre-existing ansible==2.9.27
          installation.
      
          Installing ansible-core with ansible-2.9 or older, or ansible-base-2.10
          currently installed with pip is known to cause problems. Please uninstall
          ansible and install the new version:
      
              pip uninstall ansible
              pip install ansible-core
      
          If you want to skip the conflict checks and manually resolve any issues
          afterwards, set the ANSIBLE_SKIP_CONFLICT_CHECK environment variable:
      
              ANSIBLE_SKIP_CONFLICT_CHECK=1 pip install ansible-core
      
          ****************************************************************************
      
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure

× Encountered error while trying to install package.
╰─> ansible-core

note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.

事後はこうなりました。ansible-lint はインストールされていません。ansible 2.9.27 は残ったままです。

% pip list
Package          Version
---------------- -------
ansible          2.9.27
ansible-compat   2.0.0
bracex           2.2.1
cffi             1.15.0
commonmark       0.9.1
cryptography     36.0.2
enrich           1.2.7
Jinja2           3.0.3
MarkupSafe       2.1.1
packaging        21.3
pathspec         0.9.0
pip              22.0.4
pycparser        2.21
Pygments         2.11.2
pyparsing        3.0.7
PyYAML           6.0
resolvelib       0.5.4
rich             12.0.0
ruamel.yaml      0.17.21
ruamel.yaml.clib 0.2.6
setuptools       60.5.0
subprocess-tee   0.3.5
wcmatch          8.3
yamllint         1.26.3

Python 3.6、3.7系の場合 は ansible-lint 5系まで

ansible-lint 6.0.0 の changelogに、

Remove support for py36 and py37 (#1850) @ssbarnea

とあるように、Python 3.6 と 3.7 はサポートされなくなりました

そのため、たとえば、Python 3.6.8 の環境で pip install ansible-lint を実行しても、現在の場合 5.4.0 までしかインストールされません。なので、ansible-core はセットでインストールされません。

終わりに

ansible-lint 6.0.0 をインストールすることによって、ansible-core 2.12.3 もインストールされることを確認しました。

インストール時は少し注意が必要かなと思います。lint用の別のvenvを用意するのがよいでしょうか。

また、 ansible 2.9 の環境には ansible-lint 5 系までとセットで使うべし、ということも分かりました(ansible-lint 6.0.0 の changelog でいう Remove support for ansible 2.9)。

調べ中のメモ