ブロックと rescue を使用したエラー処理

AnsibleBeginner
オンラインで実践に進む

はじめに

Ansible の block を使用すると、関連するタスクをグループ化できます。rescue セクションはブロック内のタスクが失敗したときに実行され、always セクションは成功・失敗にかかわらず常に実行されます。

この実験では、制御された障害を発生させてそこから復旧し、その後、障害発生条件を無効にして同じ Playbook を再実行することで、正常な実行パスを確認します。

エラー処理用プロジェクトの作成

このステップでは、ローカルの管理対象ホストを 1 つ持ち、block、rescue、always のマーカーを記録するためのレポートディレクトリを備えた小さなプロジェクトを作成します。

cd /home/labex/project
mkdir -p rhce-ansible/{inventory,playbooks,reports}
cd rhce-ansible
cat > ansible.cfg <<'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = False
EOF
cat > inventory/hosts <<'EOF'
[managed]
host ansible_connection=local
EOF

reports ディレクトリは、Playbook が各パスのマーカーを書き込む場所です。これにより、ターミナルの出力だけに頼ることなく、ブロックの動作を可視化できます。

block、rescue、always を含む Playbook の作成

このステップでは、制御された障害を発生させる Playbook を作成します。simulate_failure が true の場合にブロックが失敗し、rescue セクションが復旧マーカーを書き込み、always セクションが監査マーカーを書き込むようにします。 このステップのコマンドを実行する前に、Ansible プロジェクトディレクトリに戻ってください。これにより、LabEx が各ステップを個別に実行する場合でもコマンドが安定します。

cd /home/labex/project/rhce-ansible
cat > playbooks/block-rescue.yml <<'EOF'
---
- name: Practice block rescue and always
  hosts: managed
  gather_facts: false
  vars:
    simulate_failure: true
  tasks:
    - name: Remove old markers
      ansible.builtin.file:
        path: "/home/labex/project/rhce-ansible/reports/{{ item }}.txt"
        state: absent
      loop:
        - block-success
        - rescued
        - always

    - name: Protect a risky operation with rescue
      block:
        - name: Run a command that may fail
          ansible.builtin.command: /usr/bin/false
          when: simulate_failure | bool

        - name: Mark block success
          ansible.builtin.copy:
            dest: /home/labex/project/rhce-ansible/reports/block-success.txt
            content: |
              block completed
            mode: '0644'
      rescue:
        - name: Mark rescue path
          ansible.builtin.copy:
            dest: /home/labex/project/rhce-ansible/reports/rescued.txt
            content: |
              rescued controlled failure
            mode: '0644'
      always:
        - name: Mark always path
          ansible.builtin.copy:
            dest: /home/labex/project/rhce-ansible/reports/always.txt
            content: |
              always ran
            mode: '0644'
EOF

リスクのあるコマンド /usr/bin/false は、常に失敗して終了します。simulate_failure が true の場合、ブロックはその失敗したタスクで停止し、rescue セクションが rescued.txt を書き込み、always セクションはどちらの場合でも always.txt を書き込みます。

ansible-playbook playbooks/block-rescue.yml --syntax-check

block、rescue、always キーワードは、同じインデントレベルで揃える必要があります。構文チェックは、制御された障害を実行する前にセクションの配置ミスを見つけるための迅速な方法です。

制御された障害パスの実行

このステップでは、デフォルトで障害が有効になっている Playbook を実行します。Play の要約(recap)には、失敗した Play ではなく、復旧されたタスクが表示されるはずです。 このステップのコマンドを実行する前に、Ansible プロジェクトディレクトリに戻ってください。

cd /home/labex/project/rhce-ansible
ansible-playbook playbooks/block-rescue.yml | tee reports/failure-path.txt

この実行では、要約に rescued=1 および failed=0 が表示されることが期待されます。これは、Ansible がブロック内のタスクの失敗を検知し、rescue タスクを実行したため、Play 全体としては失敗とみなされなかったことを意味します。

cat reports/rescued.txt reports/always.txt

2 つのマーカーファイルには、それぞれ rescued controlled failure と always ran と記述されているはずです。ブロックが成功マーカーのタスクに到達しなかったため、このパスでは block-success.txt は表示されません。

追加変数を使用した成功パスの実行

このステップでは、コマンドラインで simulate_failure を上書きします。ブロックは正常に完了し、rescue は実行されず、always は引き続き実行されるはずです。 このステップのコマンドを実行する前に、Ansible プロジェクトディレクトリに戻ってください。

cd /home/labex/project/rhce-ansible
ansible-playbook playbooks/block-rescue.yml -e simulate_failure=false | tee reports/success-path.txt

-e simulate_failure=false オプションは、この実行時のみ Playbook の変数を上書きします。これで false コマンドはスキップされ、通常のブロックが block-success.txt に到達し、rescue セクションは実行されません。

cat reports/block-success.txt reports/always.txt

成功パスでは block completed と always ran が表示されるはずです。Playbook は開始時に古いマーカーを削除するため、この実行後には rescued.txt は存在しなくなります。

障害時と成功時のエビデンスの比較

このステップでは、保存された 2 つの Playbook 実行結果を比較します。エビデンスを小さく保つことで、出力全体を読まなくても、どのパスが実行されたかを簡単にトラブルシューティングできます。 このステップのコマンドを実行する前に、Ansible プロジェクトディレクトリに戻ってください。

cd /home/labex/project/rhce-ansible
grep -E 'rescued=|failed=' reports/failure-path.txt reports/success-path.txt

障害パスのレポートには rescued=1 が含まれ、成功パスのレポートには rescued=0 が含まれているはずです。どちらも failed=0 となりますが、その理由は異なります。

ls -1 reports

レポートリストには、保存された両方の Playbook 出力と、直近のパスで生成されたマーカーが含まれているはずです。両方の出力を保持しておくことで、rescue が要約にどのような変化をもたらすかを比較しやすくなります。

まとめ

block、rescue、always セクションを使用して制御された障害を処理し、同じ Playbook を正常なパスで実行して、保存されたエビデンスを比較しました。