今回構築するコントロールノードと実行ノード1台ずつの構成では、信頼性は特に向上しないと思いますが、事情があってAutomation Controller から直接マネージドノードにアクセスできないという場合には、解決策になりそうです(公式ブログ What's new: an introduction to automation mesh)でいうDesign for your enterprise)。
$ 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
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."}
なお、inventory の [automationcontroller:var] で、node_type を hybrid や control 以外の値を指定したときは以下のエラーが表示されました。実際はただのスペルミスでした。
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"}
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
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(コントロールノード)での確認をします。
# コントロールノード
$ 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
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: 家の中のマネージドノードを操作するジョブテンプレート
いよいよ、本命のジョブテンプレートの実行を試します。マネージドノードとなる CiscoIOS の機器は、コントロールノードがら IP 的に直接アクセスできない家の中にあります。
7.1. 各種設定
先程試したデモ用とは異なり、以下の工夫を仕込みます。
ジョブの実行の EE には Minimal execution environment で定義している、registry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8:latestを利用
# コントロールノード
$ 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
# 実行ノード
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
# 実行ノード
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
% 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.
% terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# iosxe_rest.ntp_post will be created
+ resource "iosxe_rest" "ntp_post" {
+ id = (known after apply)
+ method = "POST"
+ path = "/data/Cisco-IOS-XE-native:native/ntp/server"
+ payload = jsonencode(
{
+ Cisco-IOS-XE-ntp:server-list = [
+ {
+ ip-address = "10.0.0.1"
},
+ {
+ ip-address = "10.0.0.2"
},
+ {
+ ip-address = "10.0.0.3"
},
]
}
)
+ response = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
2.4. terraform apply の実行
いよいよ terraform apply です。
% terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# iosxe_rest.ntp_post will be created
+ resource "iosxe_rest" "ntp_post" {
+ id = (known after apply)
+ method = "POST"
+ path = "/data/Cisco-IOS-XE-native:native/ntp/server"
+ payload = jsonencode(
{
+ Cisco-IOS-XE-ntp:server-list = [
+ {
+ ip-address = "10.0.0.1"
},
+ {
+ ip-address = "10.0.0.2"
},
+ {
+ ip-address = "10.0.0.3"
},
]
}
)
+ response = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes # yes を入力
iosxe_rest.ntp_post: Creating...
iosxe_rest.ntp_post: Creation complete after 1s [id=4155581422]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
ネットワーク機器側を確認すると無事に3台分が追加されていることが確認できました。
csrv1000(config)#do sh run | inc ntp
ntp server 10.0.0.1
ntp server 10.0.0.2
ntp server 10.0.0.3
普通に RESTCONF で考えると、すでに設定が入ってる状態に 再度 POST すると 409 Conflict あたりになるかと思います。
ということで試しました。
% terraform plan
iosxe_rest.ntp_post: Refreshing state... [id=4155581422]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
No changes. なので、特に何もしない結果になりました。
これは、Terraform 側の処理として手元に保管されている state ファイルと比較した結果、一致しているのでリクエストすら出さなかった、という状態だと思います。このあたりは、Terraform らしさでしょうか。
■ 3. NTP サーバー設定3台から2台 (POSTのまま、エラー)
続いて、エラーになるかなと思いつつも、tf ファイルで4台目を追加して POST のまま実行にする、というのを試しました。
% terraform plan
iosxe_rest.ntp_post: Refreshing state... [id=4155581422]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
Terraform will perform the following actions:
# iosxe_rest.ntp_post will be updated in-place
~ resource "iosxe_rest" "ntp_post" {
id = "4155581422"
~ payload = jsonencode(
~ {
~ Cisco-IOS-XE-ntp:server-list = [
# (2 unchanged elements hidden)
{
ip-address = "10.0.0.3"
},
+ {
+ ip-address = "10.0.0.4"
},
]
}
)
# (2 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
3.3.terraform apply の実行
実際に terraform apply を実行するとエラーになります。
% terraform apply
iosxe_rest.ntp_post: Refreshing state... [id=4155581422]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
Terraform will perform the following actions:
# iosxe_rest.ntp_post will be updated in-place
~ resource "iosxe_rest" "ntp_post" {
id = "4155581422"
~ payload = jsonencode(
~ {
~ Cisco-IOS-XE-ntp:server-list = [
# (2 unchanged elements hidden)
{
ip-address = "10.0.0.3"
},
+ {
+ ip-address = "10.0.0.4"
},
]
}
)
# (2 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
iosxe_rest.ntp_post: Modifying... [id=4155581422]
╷
│ Error: failed: status code: 409 - error: {
│ "errors": {
│ "error": [
│ {
│ "error-message": "object already exists: /ios:native/ios:ntp/ios-ntp:server/ios-ntp:server-list[ios-ntp:ip-address='10.0.0.1']",
│ "error-path": "/Cisco-IOS-XE-native:native/ntp/Cisco-IOS-XE-ntp:server",
│ "error-tag": "data-exists",
│ "error-type": "application"
│ }
│ ]
│ }
│ }
│
│
│ with iosxe_rest.ntp_post,
│ on ntp_post.tf line 1, in resource "iosxe_rest" "ntp_post":
│ 1: resource "iosxe_rest" "ntp_post" {
│
╵
Terraform 的に、差分ありと判断してリクエストを出した結果、すでにある設定を POST してるので、エラーになったということだと思います。ステータスコードは 409、また "error-tag": "data-exists" とあります。
3.4. 仕切り直し
さて、こうなると少々厄介です。 state ファイルには 4台目がある状態で、ネットワーク機器側3台分のままです。
今回は挙動をいろいろ確認するためなので、だいぶ乱暴ですがいったん state ファイル類を削除します(通常は推奨されることではないと思います)。
csrv1000(config)#no ntp server 10.0.0.1
csrv1000(config)#no ntp server 10.0.0.2
csrv1000(config)#no ntp server 10.0.0.3
csrv1000(config)#do sh run | inc ntp
csrv1000(config)#
% terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# iosxe_rest.ntp_put will be created
+ resource "iosxe_rest" "ntp_put" {
+ id = (known after apply)
+ method = "PUT"
+ path = "/data/Cisco-IOS-XE-native:native/ntp"
+ payload = jsonencode(
{
+ Cisco-IOS-XE-native:ntp = {
+ Cisco-IOS-XE-ntp:server = {
+ server-list = [
+ {
+ ip-address = "10.0.0.1"
},
+ {
+ ip-address = "10.0.0.2"
},
+ {
+ ip-address = "10.0.0.3"
},
]
}
}
}
)
+ response = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
4.4 terraform apply の実行
terraform apply を実行します。
% terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# iosxe_rest.ntp_put will be created
+ resource "iosxe_rest" "ntp_put" {
+ id = (known after apply)
+ method = "PUT"
+ path = "/data/Cisco-IOS-XE-native:native/ntp"
+ payload = jsonencode(
{
+ Cisco-IOS-XE-native:ntp = {
+ Cisco-IOS-XE-ntp:server = {
+ server-list = [
+ {
+ ip-address = "10.0.0.1"
},
+ {
+ ip-address = "10.0.0.2"
},
+ {
+ ip-address = "10.0.0.3"
},
]
}
}
}
)
+ response = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
iosxe_rest.ntp_put: Creating...
iosxe_rest.ntp_put: Creation complete after 1s [id=4117814902]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
ネットワーク機器側の設定を確認すると無事に設定が入っていました。
csrv1000(config)#do sh run | inc ntp
ntp server 10.0.0.1
ntp server 10.0.0.2
ntp server 10.0.0.3
■ 5. NTP サーバー設定3台から4台へ (PUT)
3台分設定されている状態から、PUTで4台分にします。
5.1. ntp_put.tf の修正
PUT で 3台追加したところで、今度は先程使った ntp_put.tf を編集して、4台の設定にします。
terraform plan を実行します。4台目 10.0.0.4 を追加しますよ、と表示されます。
% terraform plan
iosxe_rest.ntp_put: Refreshing state... [id=4117814902]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
Terraform will perform the following actions:
# iosxe_rest.ntp_put will be updated in-place
~ resource "iosxe_rest" "ntp_put" {
id = "4117814902"
~ payload = jsonencode(
~ {
~ Cisco-IOS-XE-native:ntp = {
~ Cisco-IOS-XE-ntp:server = {
~ server-list = [
# (2 unchanged elements hidden)
{
ip-address = "10.0.0.3"
},
+ {
+ ip-address = "10.0.0.4"
},
]
}
}
}
)
# (2 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
5.3. terraform apply の実行
terraform apply を実行します。
% terraform apply
iosxe_rest.ntp_put: Refreshing state... [id=4117814902]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
Terraform will perform the following actions:
# iosxe_rest.ntp_put will be updated in-place
~ resource "iosxe_rest" "ntp_put" {
id = "4117814902"
~ payload = jsonencode(
~ {
~ Cisco-IOS-XE-native:ntp = {
~ Cisco-IOS-XE-ntp:server = {
~ server-list = [
# (2 unchanged elements hidden)
{
ip-address = "10.0.0.3"
},
+ {
+ ip-address = "10.0.0.4"
},
]
}
}
}
)
# (2 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
iosxe_rest.ntp_put: Modifying... [id=4117814902]
iosxe_rest.ntp_put: Modifications complete after 2s [id=477754463]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
無事に設定されました。
csrv1000(config)#do sh run | inc ntp
ntp server 10.0.0.1
ntp server 10.0.0.2
ntp server 10.0.0.3
ntp server 10.0.0.4
terraform plan を実行します。10.0.0.2、10.0.0.3、10.0.0.4 は削除しますよと示されます。
% terraform plan
iosxe_rest.ntp_put: Refreshing state... [id=477754463]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
Terraform will perform the following actions:
# iosxe_rest.ntp_put will be updated in-place
~ resource "iosxe_rest" "ntp_put" {
id = "477754463"
~ payload = jsonencode(
~ {
~ Cisco-IOS-XE-native:ntp = {
~ Cisco-IOS-XE-ntp:server = {
~ server-list = [
{
ip-address = "10.0.0.1"
},
- {
- ip-address = "10.0.0.2"
},
- {
- ip-address = "10.0.0.3"
},
- {
- ip-address = "10.0.0.4"
},
]
}
}
}
)
# (2 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
6.3. terraform apply の実行
terraform apply を実行します。
% terraform apply
iosxe_rest.ntp_put: Refreshing state... [id=477754463]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
Terraform will perform the following actions:
# iosxe_rest.ntp_put will be updated in-place
~ resource "iosxe_rest" "ntp_put" {
id = "477754463"
~ payload = jsonencode(
~ {
~ Cisco-IOS-XE-native:ntp = {
~ Cisco-IOS-XE-ntp:server = {
~ server-list = [
{
ip-address = "10.0.0.1"
},
- {
- ip-address = "10.0.0.2"
},
- {
- ip-address = "10.0.0.3"
},
- {
- ip-address = "10.0.0.4"
},
]
}
}
}
)
# (2 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
iosxe_rest.ntp_put: Modifying... [id=477754463]
iosxe_rest.ntp_put: Modifications complete after 1s [id=1111786887]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
無事に 10.0.0.1 のみになりました。
csrv1000(config)#do sh run | inc ntp
ntp server 10.0.0.1
csrv1000(config)#