- 1 はじめに
- 2 検証環境
- 3 事前準備
- 4 playbookの構文をチェックする方法(–syntax-check)
- 5 デバッグメッセージを表示する方法(-v,-vv...)
- 6 タスク毎に実行を確認する方法(--step)
- 7 debugモジュールを使う方法
- 8 failモジュールを使う方法
- 9 assertモジュールを使う方法
- 10 debuggerオプションを使う方法
- Y 参考図書
- Z 参考情報
1 はじめに
本記事では、Ansibleのデバッグ方法について説明します。
2 検証環境
動作検証をするための環境は以下のとおりです。
192.168.122.0/24 control ------------------------------------- node1 .220 .87
ホスト名 | 役割 |
---|---|
control | コントロールノードとして動作します。Ansibleをインストールします。 |
node1 | ターゲットノードとして動作します。モジュールが実行されるホストです |
コントロールノード、ターゲットノードのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 9.2 (Turquoise Kodkod)
コントロールノード、ターゲットノードのカーネル版数は以下のとおりです。
[root@server ~]# uname -r 5.14.0-284.11.1.el9_2.x86_64
3 事前準備
ansibleのインストールや公開鍵認証の設定方法などは、Ansibleの使い方(モジュール編) - hana_shinのLinux技術ブログを参照してください。
4 playbookの構文をチェックする方法(–syntax-check)
–syntax-checkは、playbookの構文をチェックするオプションです。構文をチェックするだけで、playbookの実行はしません。
テスト用のplaybookを作成します。このplaybookに誤りはありません。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: The output of magic variables ansible.builtin.debug: msg: The name of playbook is {{ ansible_play_name }}
--syntax-checkオプションを付けて、playbookを実行します。
[root@control ~]# ansible-playbook -i hosts.ini test.yml --syntax-check playbook: test.ym
意図的にmsgの開始位置を左にずらして、debugモジュールと同じ位置にしてみます。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: The output of magic variables ansible.builtin.debug: msg: The name of playbook is {{ ansible_play_name }}
--syntax-checkオプションを付けて、playbookを実行すると、構文エラーが発生していることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml --syntax-check ERROR! conflicting action statements: debug, msg The error appears to be in '/root/test.yml': line 4, column 7, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: tasks: - name: The output of magic variables ^ here
5 デバッグメッセージを表示する方法(-v,-vv...)
-vはデバッグメッセージを出力するオプションです。vの個数は最大6個(-vvvvvv)まで指定できます。-vがデバックメッセージを最も簡潔に出力します。vの数が多くなると、デバッグメッセージをより詳細に出力します。-vvvからネットーワークに関するデバッグメッセージが出力されます。
-vを指定してplaybookを実行すると、デバッグメッセージが出力されていることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml -v Using /etc/ansible/ansible.cfg as config file PLAY [Sample Playbook] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************************** ok: [192.168.122.220] TASK [Execute the hostname command] ***************************************************************************************************** changed: [192.168.122.220] => {"changed": true, "cmd": ["/usr/bin/hostname"], "delta": "0:00:00.007782", "end": "2024-02-24 22:11:47.767717", "msg": "", "rc": 0, "start": "2024-02-24 22:11:47.759935", "stderr": "", "stderr_lines": [], "stdout": "node1", "stdout_lines": ["node1"]} PLAY RECAP ****************************************************************************************************************************** 192.168.122.220 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
6 タスク毎に実行を確認する方法(--step)
--stepは、Ansible Playbookを実行する際に、各タスクごとにユーザーに対して処理を続けるか中断するかを確認するオプションです。このオプションを使用すると、Playbookの実行中に各タスクが開始される前に、ユーザーに確認メッセージが表示されます。
テスト用のplaybookを作成します。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Display nodename ansible.builtin.debug: msg: "The name of the remote host is {{ ansible_facts.nodename }}" - name: Display kernel version ansible.builtin.debug: msg: "The kernel version of the remote host is {{ ansible_facts.kernel }}"
--stepオプションを指定してplaybookを実行します。各タスクで以下のいずれかを押下します。
・n:タスクを実行しません。
・y:タスクを実行します。
・c:最後のタスクまで自動で実行します。
以下の例では、最初にyを押下して、リモートホストからファクトを収集します。その後、2回ともyを押下してタスクを実行しています。ちなみに、ファクトの収集に対してNを押下すると、リモートホストからホスト名等のファクトを入手できないので、その後のタスクの実行は失敗します。
[root@control ~]# ansible-playbook -i hosts.ini test.yml --step PLAY [Sample Playbook] *********************************************************************************** Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: y Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: *********************************************** TASK [Gathering Facts] *********************************************************************************** ok: [192.168.122.220] Perform task: TASK: Display nodename (N)o/(y)es/(c)ontinue: y Perform task: TASK: Display nodename (N)o/(y)es/(c)ontinue: ********************************************** TASK [Display nodename] ********************************************************************************** ok: [192.168.122.220] => { "msg": "The name of the remote host is node1" } Perform task: TASK: Display kernel version (N)o/(y)es/(c)ontinue: y Perform task: TASK: Display kernel version (N)o/(y)es/(c)ontinue: **************************************** TASK [Display kernel version] **************************************************************************** ok: [192.168.122.220] => { "msg": "The kernel version of the remote host is 5.14.0-284.11.1.el9_2.x86_64" } PLAY RECAP *********************************************************************************************** 192.168.122.220 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
7 debugモジュールを使う方法
debugは、playbookの実行中にメッセージを表示し、変数や式のデバッグするためのモジュールです。詳細は、ansible.builtin.debug module -- Print statements during execution — Ansible Core Documentationを参照してください。
7.1 msgパラメータを使う方法
マジック変数を標準出力に出力するplaybookファイルを作成します。マジック変数とは、Ansible がシステム内の状態を反映する変数です。ユーザーはマジック変数に値を設定することはできません。ここでは、playbookの名前を保持するマジック変数(ansible_play_name)の値を出力してみます。マジック変数は、特別な変数 — Ansible Documentationを参照してください。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: The output of magic variables ansible.builtin.debug: msg: The name of playbook is {{ ansible_play_name }}
playbookを実行すると、プレイブックの名前(Sample Playbook)が表示れていることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ***************************************************************************************************** TASK [Gathering Facts] ***************************************************************************************************** ok: [192.168.122.220] TASK [The output of magic variables] *************************************************************************************** ok: [192.168.122.220] => { "msg": "The name of playbook is Sample Playbook" } PLAY RECAP ***************************************************************************************************************** 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
7.2 varパラメータを使う方法
次の内容のplaybookファイルを作成します。commandモジュールに対してhostnameコマンドをパラメータとして渡し、registerディレクティブを使ってhostnameコマンドの実行結果をresult変数に格納します。そして、その後のタスクでdebugモジュールを実行してhostnameコマンドの実行結果を表示します。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Execute the hostname command shell: /usr/bin/hostname register: result - name: Print return information from the previous task ansible.builtin.debug: var: result
playbookを実行すると、hostnameコマンドの実行結果が表示れていることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************************** ok: [192.168.122.220] TASK [Execute the hostname command] ***************************************************************************************************** changed: [192.168.122.220] TASK [Print return information from the previous task] ********************************************************************************** ok: [192.168.122.220] => { "result": { "changed": true, "cmd": "/usr/bin/hostname", "delta": "0:00:00.011434", "end": "2024-02-24 20:57:19.969301", "failed": false, "msg": "", "rc": 0, "start": "2024-02-24 20:57:19.957867", "stderr": "", "stderr_lines": [], "stdout": "node1", "stdout_lines": [ "node1" ] } } PLAY RECAP ****************************************************************************************************************************** 192.168.122.220 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
実行結果のうち、ホスト名だけを表示する場合、以下のようにvar変数にresult.stdoutと指定します。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Execute the hostname command shell: /usr/bin/hostname register: result - name: Print return information from the previous task debug: var: result.stdout
playbookを実行すると、ターゲットノードのホスト名(node1)が表示れていることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************************** ok: [192.168.122.220] TASK [Execute the hostname command] ***************************************************************************************************** changed: [192.168.122.220] TASK [Print return information from the previous task] ********************************************************************************** ok: [192.168.122.220] => { "result.stdout": "node1" } PLAY RECAP ****************************************************************************************************************************** 192.168.122.220 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
7.3 verbosityパラメータを使う方法
verbosityは、出力メッセージを詳細に表示するパラメータです。しかし、以下のようなplaybookを作成して実行してみましたが、私の環境では、デバッグメッセージが表示されませんでした。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Execute the hostname command ansible.builtin.command: cmd: /usr/bin/hostname register: var_hostname - name: Display hostname command result ansible.builtin.debug: var: var_hostname verbosity: 1
playbookを実行します。デバッグメッセージは表示されませんでした。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************************** ok: [192.168.122.220] TASK [Execute the hostname command] ***************************************************************************************************** changed: [192.168.122.220] TASK [Display hostname command result] ************************************************************************************************** skipping: [192.168.122.220] PLAY RECAP ****************************************************************************************************************************** 192.168.122.220 : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 [root@control ~]#
8 failモジュールを使う方法
failは、特定の条件が満たされた場合に、Playbookの実行を中止し、エラーメッセージを表示するモジュールです。
8.1 ファイルの状態を使った例
以下の処理を実行するplaybookを作成します。
・/tmp/test.txtが存在する場合:エラーメッセージ(File does't exist)を表示しない
・/tmp/test.txtが存在しない場合:エラーメッセージ(File does't exist)を表示する
なお、statモジュールについては、Ansibleの使い方(モジュール編) - hana_shinのLinux技術ブログを参照してください。
(1) その1(条件に一致しない場合)
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Check the status of /tmp/test.txt ansible.builtin.stat: path: /tmp/test.txt register: result - name: Fail if /tmp/test.txt does not exist ansible.builtin.fail: msg: "File doesn't exist" when: not result.stat.exists
ターゲットノードでテスト用のファイルを作成します。
[root@node1 ~]# touch /tmp/test.txt
playbookを実行します。/tmp/test.txtが存在するので、エラーメッセージが表示されないことがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.122.220] TASK [Check the status of /tmp/test.txt] ******************************************************************************************* ok: [192.168.122.220] TASK [if /tmp/test.txt does not exist] ********************************************************************************************* skipping: [192.168.122.220] PLAY RECAP ************************************************************************************************************************* 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 [root@control ~]#
(2) その2(条件に一致する場合)
ターゲットノードでテスト用ファイルを削除します。
[root@node1 ~]# rm /tmp/test.txt rm: 通常の空ファイル '/tmp/test.txt' を削除しますか? y
playbookを実行します。/tmp/test.txtが存在しないので、エラーメッセージが表示されていることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.122.220] TASK [Check the status of /tmp/test.txt] ******************************************************************************************* ok: [192.168.122.220] TASK [if /tmp/test.txt does not exist] ********************************************************************************************* fatal: [192.168.122.220]: FAILED! => {"changed": false, "msg": "File does't exist"} PLAY RECAP ************************************************************************************************************************* 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 [root@control ~]#
8.2 ファイルサイズを使った例
以下の処理を実行するplaybookを作成します。
・ファイルサイズが3バイト未満の場合:ファイルサイズを表示してplaybookを中断する
・ファイルサイズが3バイト以上の場合:正常終了する
(1) その1(条件に一致する場合)
以下の処理を実行するplaybookを作成します。
・ファイルサイズが3バイト未満の場合:ファイルサイズを表示してplaybookを中断する
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Check the status of /tmp/test.txt ansible.builtin.stat: path: /tmp/test.txt register: result - name: Fail if /tmp/test.txt size is less than 3 bytes ansible.builtin.fail: msg: "File size is {{ result.stat.size }} bytes" when: result.stat.size < 3
ターゲットノードでテスト用のファイル(2byte)を作成します。
[root@node1 ~]# echo 0 > /tmp/test.txt [root@node1 ~]# ls -l /tmp/test.txt -rw-r--r--. 1 root root 2 2月 25 22:22 /tmp/test.txt
playbookを実行します。ファイルサイズが2バイトである旨を表示して、playbookを終了していることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.122.220] TASK [Check the status of /tmp/test.txt] ******************************************************************************************* ok: [192.168.122.220] TASK [if /tmp/test.txt does not exist] ********************************************************************************************* fatal: [192.168.122.220]: FAILED! => {"changed": false, "msg": "File size is 2 byte "} PLAY RECAP ************************************************************************************************************************* 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 [root@control ~]#
(2) その2(条件に一致しない場合)
ターゲットノードでテスト用のファイル(4byte)を作成します。
[root@node1 ~]# echo 012 > /tmp/test.txt [root@node1 ~]# ls -l /tmp/test.txt -rw-r--r--. 1 root root 4 2月 25 22:25 /tmp/test.txt
playbookを実行します。playbookが正常終了していることがわかります。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.122.220] TASK [Check the status of /tmp/test.txt] ******************************************************************************************* ok: [192.168.122.220] TASK [if /tmp/test.txt does not exist] ********************************************************************************************* skipping: [192.168.122.220] PLAY RECAP ************************************************************************************************************************* 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 [root@control ~]#
9 assertモジュールを使う方法
assertは、条件に一致しない場合、Playbookの実行を中止しエラーメッセージを表示するモジュールです。詳細は、ansible.builtin.assert module -- Asserts given expressions are true — Ansible Core Documentationを参照してください。
以下の処理を実行するplaybookを作成します。
・ファイルサイズが3バイト未満の場合:ファイルサイズを表示してplaybookを中断する
・ファイルサイズが3バイト以上の場合:正常終了する
(1) その1(条件に一致する場合)
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 tasks: - name: Check the status of /tmp/test.txt ansible.builtin.stat: path: /tmp/test.txt register: result - name: Fail if /tmp/test.txt size is less than 3 bytes ansible.builtin.assert: that: - result.stat.size >= 3 fail_msg: "The file size is less than 3 bytes. The process will be aborted"
ターゲットノードでテスト用のファイル(4byte)を作成します。
[root@node1 ~]# echo 012 > /tmp/test.txt [root@node1 ~]# ls -l /tmp/test.txt -rw-r--r--. 1 root root 4 2月 25 22:25 /tmp/test.txt
playbookを実行します。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.122.220] TASK [Check the status of /tmp/test.txt] ******************************************************************************************* ok: [192.168.122.220] TASK [if /tmp/test.txt does not exist] ********************************************************************************************* ok: [192.168.122.220] => { "changed": false, "msg": "All assertions passed" } PLAY RECAP ************************************************************************************************************************* 192.168.122.220 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
(2) その2(条件に一致しない場合)
ターゲットノードでテスト用のファイル(2byte)を作成します。
[root@node1 ~]# echo 0 > /tmp/test.txt [root@node1 ~]# ls -l /tmp/test.txt -rw-r--r--. 1 root root 2 2月 25 23:14 /tmp/test.txt
playbookを実行します。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************** ok: [192.168.122.220] TASK [Check the status of /tmp/test.txt] ******************************************************************************** ok: [192.168.122.220] TASK [Fail if /tmp/test.txt size is less than 3 bytes] ****************************************************************** fatal: [192.168.122.220]: FAILED! => { "assertion": "result.stat.size >= 3", "changed": false, "evaluated_to": false, "msg": "The file size is less than 3 bytes. The process will be aborted" } PLAY RECAP ************************************************************************************************************** 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 [root@control ~]#
10 debuggerオプションを使う方法
debuggerオプションは、playbook実行中、デバッガを起動するオプションです。gdbやcrash等のデバッガと同じように、playbookのステップ実行や変数の値を確認したりすることができます。
playbookを作成します。このとき、"debugger: always"という1行を記載します。
[root@control ~]# vi test.yml [root@control ~]# cat test.yml - name: Sample Playbook hosts: node1 debugger: always tasks: - name: Install the latest version of Apache ansible.builtin.dnf: name: httpd state: latest
playbookを実行します。以下は、hコマンドを押下して、デバッガのヘルプを表示してるところです。
[root@control ~]# ansible-playbook -i hosts.ini test.yml PLAY [Sample Playbook] ***************************************************************************************************************** TASK [Gathering Facts] ***************************************************************************************************************** ok: [192.168.122.220] [192.168.122.220] TASK: Gathering Facts (debug)> h Documented commands (type help <topic>): ======================================== EOF c continue h help p pprint q quit r redo u update_task [192.168.122.220] TASK: Gathering Facts (debug)>
ここでは、cを押下してplaybookの処理を先に進めてみます。最初のc押下でファクトの収集、2つ目のc押下でhttpdパッケージをインストールしています。
[192.168.122.220] TASK: Gathering Facts (debug)> c TASK [Install the latest version of Apache] ******************************************************************************************** ok: [192.168.122.220] [192.168.122.220] TASK: Install the latest version of Apache (debug)> c PLAY RECAP ***************************************************************************************************************************** 192.168.122.220 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@control ~]#
Y 参考図書
本記事の作成に以下の図書を参考にしました。
Ansible実践ガイド 第4版[基礎編] impress top gearシリーズ
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ
Ansible の使い方
Ansible Playbookとはなにか [書き方 | 基本 | YAML] - APC Automation blog