第 10 章、Ansible テストのトラブルシューティング

1.プレイブックのトラブルシューティング

1. ANSIBLE ログ ファイル

デフォルトでは、Red Hat Ansible Engine はその出力をログ ファイルに記録しないように設定されています。組み込みのロギング インフラストラクチャを提供しますが、ansible.cfg構成ファイルのdefault配置文件部分中的log_pathパラメーター$ANSIBLE_LOG_PATH环境变量来配置または これらの設定のいずれかが設定されている場合、ansible は ansible および ansible-playbook コマンドからの出力を ansible.cfg 設定ファイルまたは $ANSIBLE_LOG_PATH 環境変数によって設定されたログ ファイルに保存します。もちろん、最近はプレイブックの実行時に結果が自動的に出力されるため、通常はあまり使用されません。

//デフォルトの保存場所を開く

[student@server ansible]$ vim ansible.cfg
#log_path = /var/log/ansible.log
[student@server ansible]$ sudo touch /var/log/ansible.log
[student@server ansible]$ ll /var/log/ansible.log 
-rw-r--r-- 1 root root 0 Nov  4 17:02 /var/log/ansible.log
//修改权限
[student@server ansible]$ sudo chown student.student /var/log/ansible.log 
[student@server ansible]$ ll /var/log/ansible.log 
-rw-r--r-- 1 student student 0 Nov  4 17:02 /var/log/ansible.log
//任意运行一个playbook就可以导入日志了
[student@server ansible]$ cat /var/log/ansible.log 
2022-11-04 17:08:16,993 p=46685 u=student n=ansible | PLAY [test] ********************************************************************
2022-11-04 17:08:17,006 p=46685 u=student n=ansible | TASK [Gathering Facts] *********************************************************

2. モジュールのデバッグ

通过debug模块可以了解play中发生的情况。此模块可以显示play中某个点上某个变量的值. この機能は、変数を使用して相互に通信するタスクをデバッグする場合 (たとえば、あるタスクの出力を後続のタスクの出力として使用する場合) に重要です。

次の例では debug task を使用していますmsg和var设置。最初の例では、ansible-playbook 出力に表示されるメッセージの一部として ansible_facts[ 'memfree_mb' ] ファクトのランタイム値を示しています。2 番目の例は、出力変数の値を表示します。

[root@server ansible]# vim a.yml 
---
- name: test
  hosts: node1
  tasks:
    - name: free mem
      debug:
        msg: this system free mem is {
   
   { ansible_memfree_mb }}
      register: output        //调用输出结果
      
    - name: output vars
      debug:
        var: output       //显示变量的详细内容

ここで var も msg を使用できますが、変数に「{ { }}」を追加する必要があります

3. 管理エラー:

Playbook の実行中にさまざまな問題が発生する可能性があります。それらは主に、Playbook の構文またはそれが使用するテンプレートに関連するか、管理対象ホストとの接続の問題 (たとえば、マニフェスト ファイル内の管理対象ホストのホスト名のエラー) に関連しています。 )。これらのエラーは、実行時に ansible-playbook コマンドによって出力されます。

但也可以使用--syntax-check选项检查playbook的YAML语法. Playbook を使用する前、または関連する問題が発生した場合は、フォーマット エラーがないか構文チェックを実行することをお勧めします (比較的大規模なプロジェクトの管理に適しています)。

[root@foundation0 ansible]# ansible-playbook --syntax-check a.yml

也可以使用--step选项来逐步调试playbook,一次一个任务. ansible-playbook --step コマンドは、実行する各タスクの確認をインタラクティブに求めます。
// 実行するかどうか対話的に尋ねる

[student@server ansible]$ ansible-playbook test.yml --step

PLAY [test] ********************************************************************
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: y

2. ansible 管理対象ホストのトラブルシューティング

検査モードをテスト ツールとして使用する

ansible-playbook --check コマンドを使用して、Playbook に対してスモーク テスト (別名、実行前) を実行できます。このオプションは、管理対象ホストの構成を変更せずに Playbook を実行します。Playbook で使用されるモジュールが検査モードをサポートしている場合、管理対象ホストで行われた変更は表示されますが、介入は行われません。モジュールが検査モードをサポートしていない場合、変更は表示されませんが、モジュールはまだ何もしません。

语法:ansible-playbook --check playbook.yml

注: ansible-playbook --check は、条件が使用されている場合、正しく機能しない可能性があります。これは単なるシミュレーションです。

play に設定を追加することで、個々のタスクをチェック モードで実行するかどうかを制御することもできますcheck_mode语法则它始终以检查模式运行--check オプションが ansible-playbook に渡されるかどうかに関係なく、タスクに check_mode: yes が設定されている場合。同様に、タスクに check_mode: no が設定されている場合、--check が ansible-playbook に渡されても、タスクは常に正常に実行されます。
例 1:

[root@server ansible]# vim b.yml
---
- name: touch file
  hosts: node1
  tasks:
    - name: touch file1
      file:
        path: /tmp/file1
        state: touch
            
[root@server ansible]# ansible-playbook b.yml --check

PLAY [touch file] **********************************************************************************

TASK [Gathering Facts] *****************************************************************************
ok: [node1]

TASK [touch file1] *********************************************************************************
ok: [node1]

PLAY RECAP *****************************************************************************************
node1                      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

この時点で、node1 に移動して、file1 ファイルが /tmp ディレクトリに作成されたかどうかを確認したところ、file1 ファイルが作成されていないことがわかりました。これは、-check オプションを使用して Playbook を確認すると、実際には変更されないことを示しています。制御されたホスト、そして私が前にあなたに言った -C は同じであり、実行前に属します。

[root@server ansible]# ssh root@node1
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Thu May 13 17:33:59 2021 from 172.16.30.30
[root@node1 ~]# ls /tmp/
systemd-private-d415e2d79c8344a699f94b887c2e33d6-bluetooth.service-LnOEkh
systemd-private-d415e2d79c8344a699f94b887c2e33d6-bolt.service-pEp4ii
systemd-private-d415e2d79c8344a699f94b887c2e33d6-colord.service-iWH4dE
systemd-private-d415e2d79c8344a699f94b887c2e33d6-fwupd.service-xrlwGf
systemd-private-d415e2d79c8344a699f94b887c2e33d6-geoclue.service-FhuTfg
systemd-private-d415e2d79c8344a699f94b887c2e33d6-ModemManager.service-OLIlWO
systemd-private-d415e2d79c8344a699f94b887c2e33d6-rtkit-daemon.service-KmmVEn
tracker-extract-files.0
vmware-root_791-4282302006
[root@node1 ~]# 

例 2: Playbook で check_mode パラメーターを yes に設定し、Playbook を再度実行する

[root@server ansible]# cat b.yml 
---
- name: touch file
  hosts: node1
  check_mode: yes
  tasks: 
    - name: touch file1
      file: 
        path: /tmp/file1
        state: touch

当我们正常使用ansible-playbook命令执行时,它仍然处于预执行,也就是说不管你手动是否添加了--check选项,它都属于预执行。
[root@server ansible]# ansible-playbook b.yml 

PLAY [touch file] **********************************************************************************

TASK [Gathering Facts] *****************************************************************************
ok: [node1]

TASK [touch file1] *********************************************************************************
ok: [node1]

PLAY RECAP *****************************************************************************************
node1                      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

例 3: Playbook で check_mode パラメーターを no に設定し、Playbook を再度実行する

[root@server ansible]# cat b.yml 
---
- name: touch file
  hosts: node1
  check_mode: no
  tasks: 
    - name: touch file1
      file: 
        path: /tmp/file1
        state: touch

我们在执行该playbook的时候添加--check选项,此时我们会发现并没有进行预执行,而是对受控主机进行了修改
[root@server ansible]# cat b.yml 
---
- name: touch file
  hosts: node1
  check_mode: no
  tasks: 
    - name: touch file1
      file: 
        path: /tmp/file1
        state: touch

验证:
[root@server ansible]# ssh root@node1
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Thu May 13 17:40:49 2021 from 172.16.30.30
[root@node1 ~]# ls /tmp/
file1
systemd-private-d415e2d79c8344a699f94b887c2e33d6-bluetooth.service-LnOEkh
systemd-private-d415e2d79c8344a699f94b887c2e33d6-bolt.service-pEp4ii
systemd-private-d415e2d79c8344a699f94b887c2e33d6-colord.service-iWH4dE
systemd-private-d415e2d79c8344a699f94b887c2e33d6-fwupd.service-xrlwGf
systemd-private-d415e2d79c8344a699f94b887c2e33d6-geoclue.service-FhuTfg
systemd-private-d415e2d79c8344a699f94b887c2e33d6-ModemManager.service-OLIlWO
systemd-private-d415e2d79c8344a699f94b887c2e33d6-rtkit-daemon.service-KmmVEn
tracker-extract-files.0
vmware-root_791-4282302006
[root@node1 ~]# 

さらに、ansible-playbook命令还提供一个 --diff 选项このオプションは、管理対象ホスト上のテンプレート ファイルに加えられた変更を報告します。--check オプションと組み合わせると、これらの変更はコマンド出力に表示されますが、実際には行われません。

例 1: --diff のみを使用します。実際に Playbook を実行し、同時に制御対象ホストの前後で変更された情報を一覧表示します。

[root@server ansible]# cat b.yml 
---
- name: touch file
  hosts: node1
  tasks: 
    - name: touch file2
      file: 
        path: /tmp/file2
        state: touch

[root@server ansible]# ansible-playbook --diff b.yml 

PLAY [touch file] **********************************************************************************

TASK [Gathering Facts] *****************************************************************************
ok: [node1]

TASK [touch file2] *********************************************************************************
--- before                //会列出此文件的创建之前后创建后的信息
+++ after
@@ -1,6 +1,6 @@
 {
-    "atime": 1620898998.0370545,
-    "mtime": 1620898998.0370545,
+    "atime": 1620898998.04052,
+    "mtime": 1620898998.04052,
     "path": "/tmp/file2",
-    "state": "absent"
+    "state": "touch"
 }

changed: [node1]

PLAY RECAP *****************************************************************************************
node1                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

3. テストにモジュールを使用する

一部のモジュールは、管理対象ホストのステータスに関する追加情報を提供できます。以下の表にリストされているのは、管理対象ホストの問題をテストおよびデバッグするために使用できる Ansible モジュールの一部です。

1.URIモジュール

uri模块提供了一种方式,可以检查RESTful API是否返回需要的内容

例 1:
a.yml の playbook を作成し、url が http://server.example.com であることを確認し、返されるコンテンツを設定し、url の実行を確認した結果を変数 cy として登録し、 cy 変数の内容、URL の内容が変数 cy.content に表示されていることがわかります。

[root@server ansible]# vim a.yml
---
- name: test
  hosts: node1
  tasks:
    - name: uri test
      uri:
        url: http://server.example.com      //查询网页存放位置
        return_content: yes                    //需要返回值
      register: cy

    - name: debug1
      debug:
        var: cy              //输出变量结果


[root@server ansible]# ansible-playbook a.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [uri test] ****************************************************************
ok: [node1]

TASK [debug1] ******************************************************************
ok: [node1] => {
    "cy": {
        "accept_ranges": "bytes",
        "changed": false,
        "connection": "close",
        "content": "chenyu\n",       #网页返回内容,因为我们定义了return_content: yes
        "content_length": "7",
        "content_type": "text/html; charset=UTF-8",
        "cookies": {},
        "cookies_string": "",
        "date": "Fri, 14 May 2021 14:33:17 GMT",
        "elapsed": 0,
        "etag": "\"7-5c24b04a72bbf\"",
        "failed": false,
        "last_modified": "Fri, 14 May 2021 14:25:39 GMT",
        "msg": "OK (7 bytes)",
        "redirected": false,
        "server": "Apache/2.4.37 (Red Hat Enterprise Linux)",
        "status": 200,
        "url": "http://server.example.com"
    }
}

PLAY RECAP *********************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

例 2:
URL が http://server.example.com であることを確認し、内容を返す必要がないことを設定し、URL を確認した結果を変数 cy として登録し、cy 変数の内容を表示すると、 cy はまったくありません。内容はこの変数です。

[root@server ansible]# vim a.yml
---
- name: test
  hosts: node1
  tasks:
    - name: uri test
      uri:
        url: http://server.example.com
        return_content: no
      register: cy

    - name: debug1
      debug:
        var: cy

[root@server ansible]# ansible-playbook a.yml   //会发现变量cy中压根就没有content的子项。

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [uri test] ****************************************************************
ok: [node1]

TASK [debug1] ******************************************************************
ok: [node1] => {
    "cy": {
        "accept_ranges": "bytes",
        "changed": false,
        "connection": "close",
        "content_length": "7",
        "content_type": "text/html; charset=UTF-8",
        "cookies": {},
        "cookies_string": "",
        "date": "Fri, 14 May 2021 14:34:56 GMT",
        "elapsed": 0,
        "etag": "\"7-5c24b04a72bbf\"",
        "failed": false,
        "last_modified": "Fri, 14 May 2021 14:25:39 GMT",
        "msg": "OK (7 bytes)",
        "redirected": false,
        "server": "Apache/2.4.37 (Red Hat Enterprise Linux)",
        "status": 200,
        "url": "http://server.example.com"
    }
}

PLAY RECAP *********************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

2.スクリプトモジュール

スクリプト モジュールは、管理対象ホストでのスクリプトの実行をサポートし、スクリプトにゼロ以外のリターン コードがある場合に失敗を報告します。スクリプトは制御ノードに存在し、管理対象ホストに転送されて実行される必要があります。

例:
スクリプト adhoc.sh を作成し、スクリプト モジュールを使用してスクリプトを制御対象ホストに送信して実行します。

[root@server ansible]# cat adhoc.sh    //这个脚本是不需要给权限
#!/bin/bash
touch /tmp/file2

[root@server ansible]# cat b.yml 
---
- name: test
  hosts: all
  tasks: 
    - name: script test
      script: /etc/ansible/adhoc.sh 

[root@server ansible]# ansible-playbook b.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]
ok: [node2]

TASK [script test] *************************************************************
changed: [node2]
changed: [node1]

PLAY RECAP *********************************************************************
node1                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node2                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

验证:
验证发现该脚本在每个受控主机中都执行了
[root@node1 ~]# ls /tmp/
file2

[root@node2 ~]# ls /tmp
file2

3.統計モジュール

stat モジュールがファイルを収集するという事実は、stat コマンドと非常によく似ています。可以使用它来确定受控主机的文件是否存在或获取有关该文件的其他信息. ファイルが存在しなくても stat タスクは失敗しませんが、登録された変数は *.stat.exists に対して false を報告します。

例 1:
制御ノード node1 の /tmp/abc ファイルが存在するかどうかを確認する

[root@server ansible]# cat c.yml 
---
- name: test
  hosts: node1
  tasks: 
    - name: stat test
      stat: 
        path: /tmp/abc
      register: cy

    - name: debug1
      debug: 
        var: cy

执行c.yml这个playbook,我们发现cy.stat.exists变量的值为false,说明此文件在node1上不存在。
[root@server ansible]# ansible-playbook c.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [stat test] ***************************************************************
ok: [node1]

TASK [debug1] ******************************************************************
ok: [node1] => {
    "cy": {
        "changed": false,
        "failed": false,
        "stat": {
            "exists": false
        }
    }
}

PLAY RECAP *********************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

例 2:
制御ノード node1 の /tmp/file2 ファイルが存在するかどうかを確認する

[root@server ansible]# cat c.yml 
---
- name: test
  hosts: node1
  tasks: 
    - name: stat test
      stat: 
        path: /tmp/file2
      register: cy

    - name: debug1
      debug: 
        var: cy

执行该playbook,我们发现cy.stat变量的值里面有/tmp/file2的相关信息,说明该文件存在
[root@server ansible]# ansible-playbook c.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [stat test] ***************************************************************
ok: [node1]

TASK [debug1] ******************************************************************
ok: [node1] => {
    "cy": {
        "changed": false,
        "failed": false,
        "stat": {                               //列出了所有文件
            "atime": 1621004553.648727,
            "attr_flags": "",
            "attributes": [],
            "block_size": 4096,
            "blocks": 0,
            "charset": "binary",
            "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
            "ctime": 1621003594.5807807,
            "dev": 2051,
            "device_type": 0,
            "executable": false,
            "exists": true,
            "gid": 0,
            "gr_name": "root",
            "inode": 136,
            "isblk": false,
            "ischr": false,
            "isdir": false,
            "isfifo": false,
            "isgid": false,
            "islnk": false,
            "isreg": true,
            "issock": false,
            "isuid": false,
            "mimetype": "inode/x-empty",
            "mode": "0644",
            "mtime": 1621003594.5807807,
            "nlink": 1,
            "path": "/tmp/file2",
            "pw_name": "root",
            "readable": true,
            "rgrp": true,
            "roth": true,
            "rusr": true,
            "size": 0,
            "uid": 0,
            "version": "3070191212",
            "wgrp": false,
            "woth": false,
            "writeable": true,
            "wusr": true,
            "xgrp": false,
            "xoth": false,
            "xusr": false
        }
    }
}

PLAY RECAP *********************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

4.モジュールをアサートする

assert是fail模块(手动中止输出结果)的一种替代选择. assert モジュールは、条件のリストを値として受け取る that オプションをサポートしています。如果这些条件中的任何一个为false,则任务失败

例 1:
assert モジュールのパラメーターの判定が真命題 (つまり、値が存在する) の場合、タスクは正常に実行されます。

[root@server ansible]# cat c.yml 
---
- name: test
  hosts: node1
  tasks: 
    - name: stat test
      stat: 
        path: /tmp/file2
      register: cy

    - name: fail 
      assert: 
        that: 
         - cy.stat.block_size is defined         ——判断cy这个变量是被定义了的
        fail_msg: chenyu failed                  —— 如果命令执行失败输出的结果
        success_msg: chenyu success      ——命令成功后输出的结果

    - name: debug1
      debug: 
        msg: chenyu
[root@server ansible]# ansible-playbook c.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [stat test] ***************************************************************
ok: [node1]

TASK [fail] ********************************************************************
ok: [node1] => {
    "changed": false,
    "msg": "chenyu success"
}

TASK [debug1] ******************************************************************
ok: [node1] => {
    "msg": "chenyu"
}

PLAY RECAP *********************************************************************
node1                      : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

例 2:
assert モジュールの判定が複数の判定であるパラメータの場合、一方が true で他方が false の場合、失敗メッセージが返されます。

[root@server ansible]# cat c.yml 
---
- name: test
  hosts: node1
  tasks: 
    - name: stat test
      stat: 
        path: /tmp/file2
      register: cy

    - name: fail 
      assert: 
        that: 
         - cy.stat.block_size is defined  
         - cy.stat.path is not defined             ——假命题
        fail_msg: chenyu failed
        success_msg: chenyu success

    - name: debug1
      debug: 
        msg: chenyu


[root@server ansible]# ansible-playbook c.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [stat test] ***************************************************************
ok: [node1]

TASK [fail] ********************************************************************
fatal: [node1]: FAILED! => {
    "assertion": "cy.stat.path is not defined",
    "changed": false,
    "evaluated_to": false,
    "msg": "chenyu failed"
}

PLAY RECAP *********************************************************************
node1                      : ok=2    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

fail で判定された条件が true の場合は Playbook を中止し、
assert で判定された条件が false の場合は Playbook を中止します

4.接続のトラブルシューティング

Ansible を使用してホストを管理する際の一般的な問題の多くは、ホスト接続に関連するだけでなく、リモート ユーザーや権限昇格に関する構成の問題にも関連しています。

管理対象ホストの認証に関連する問題が発生した場合は、設定ファイルまたは play にあることを確認してください正确设置remote_user(使用什么用户身份执行)また、正しい SSH キーが設定されていることを確認するか、このユーザーに正しいパスワードを指定する必要があります。

become を正しく設定し、正しい become_user (デフォルトでは root) を使用してください。正しい sudo パスワードが入力されていること、および管理対象ホストで sudo が適切に構成されていることを確認します。

より微妙な問題は、マニフェストの設定に関係しています。複数のネットワーク アドレスを持つ複雑なサーバーの場合、システムに接続するときに特定のアドレスまたは DNS 名を使用する必要がある場合があります。ユーザーは、読みやすさを向上させるために、このアドレスをコンピュータのインベントリ名として使用したくない場合があります。ホスト インベントリー変数 ansible_host を設定できます。これは、インベントリー名を別の名前または IP アドレスで上書きし、そのホストに接続するために ansible によって使用されます。この変数は、そのホストの host_vars ファイルまたはディレクトリ、またはマニフェスト ファイル自体で設定できます。

[root@server ansible]# cat hosts 
node1
node100 ansible_host=node1        ——当不想暴露主机名,可以在清单中定义别名

[root@server ansible]# cat a.yml 
---
- name: test
  hosts: node100
  tasks: 
    - name: touch file
      file: 
        path: /tmp/aaa
        state: touch
        

执行该playbook后,我们去验证一下是否在node1中创建了/tmp/aaa文件
[root@server ansible]# ansible-playbook a.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node100]

TASK [touch file] **************************************************************
changed: [node100]

PLAY RECAP *********************************************************************
node100                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


验证:验证得知,我们对node100主机进行操作,实际上是对node1主机进行执行任务
[root@node1 ~]# ls /tmp/
aaa

アドホック コマンドを使用した管理対象ホストのテスト
次の例は、アドホック コマンドを使用して管理対象ホストで実行できるチェックの一部を示しています。
ping モジュールを使用して、管理対象ホストに接続できるかどうかをテストできます。オプションを渡して、権限昇格と資格情報が正しく構成されていることをテストできます。

[student@server ansible]$ ansible all -m ping
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

おすすめ

転載: blog.csdn.net/cxyxt/article/details/127692743