Ansible:Reboot 後も処理を継続する方法(Ansible 2.9.6)

インフラサーバ

作業環境

  • CentOS 8.0
  • Python 3.7.7
  • Ansible 2.9.6

Ansible における Reboot について

Ansible で設定変更操作を行った後、設定反映させるために再起動(Reboot)を実施したい場合があります。

Reboot させるためには command モジュールや shell モジュールを使用して reboot コマンドを実行させる方法が思いつくと思いますが、コマンドで reboot を実行するとその時点で対象機器との接続が切れて Ansible が停止してしまいます。(以下 例1)

■ playbook 例1

- hosts: all
  become: yes
  tasks:
    - name: Execute reboot
      shell:
        cmd: 'reboot'
    - name: Debug
      debug:
        msg: Finish!

■ Ansible 実行結果

PLAY [all] **********************************************************************************************************

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

TASK [Execute reboot] ***********************************************************************************************
fatal: [10.69.34.191]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Shared connection to 10.69.34.191 closed.", "unreachable": true}

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

Reboot 後も処理を継続する方法

Reboot 後も Playbook の処理を継続するためには、以下の手順を取ります。

  1. 非同期で Reboot 処理を実施する
  2. 対象機器の ssh ポートが down するのを待つ
  3. 対象機器の ssh ポートが up するのを待つ
  4. 後続処理

■ playbook 例2

- hosts: all
  become: yes
  tasks:
    - name: Execute reboot
      shell:
        cmd: 'sleep 2 && reboot'
      async: 1
      poll: 0
    - name: Wait for SSH port down
      become: no
      wait_for:
        host: '{{ inventory_hostname }}'
        port: '{{ ansible_ssh_port }}'
        state: stopped
      delegate_to: 127.0.0.1
    - name: Wait for SSH port up
      become: no
      wait_for:
        host: '{{ inventory_hostname }}'
        port: '{{ ansible_ssh_port }}'
        state: started
      delegate_to: 127.0.0.1
    - name: Debug
      debug:
        msg: Finish!

■ Ansible 実行結果

PLAY [all] **********************************************************************************************************

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

TASK [Execute reboot] ***********************************************************************************************
changed: [10.69.34.191]

TASK [Wait for SSH port down] ***************************************************************************************
ok: [10.69.34.191 -> 127.0.0.1]

TASK [Wait for SSH port up] *****************************************************************************************
ok: [10.69.34.191 -> 127.0.0.1]

TASK [Debug] ********************************************************************************************************
ok: [10.69.34.191] => {
    "msg": "Finish!"
}

PLAY RECAP **********************************************************************************************************
10.69.34.191               : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

非同期で Reboot 処理を実施する

以下の内容がこの処理に対応します。

    - name: Execute reboot
      shell:
        cmd: 'sleep 2 && reboot'
      async: 1
      poll: 0

通常、Playbook に記載された一連のタスクは、1つのタスクが完了したら次のタスクを実行する、といったように順次実行されますが、Reboot 開始直後に次の「ssh ポートの down を待つ」処理に移りたいため、以下のオプションを記載しています。

  • async: 1
    • 処理終了を待つ時間を意味する
  • poll: 0
    • 処理終了を確認する間隔を意味する

上記を記載することで、非同期処理となりタスクの終了を待たずに次のタスクを実行することができます。

  • cmd: ‘sleep 2 && reboot’

実行コマンドを単に reboot とすると、Ansible 処理が UNREACHABLE! エラーとなり停止してしまう可能性があるため、sleep を入れたほうが良いようです。

対象機器の ssh ポートが down するのを待つ

以下の内容がこの処理に対応します。

    - name: Wait for SSH port down
      become: no
      wait_for:
        host: '{{ inventory_hostname }}'
        port: '{{ ansible_ssh_port }}'
        state: stopped
      delegate_to: 127.0.0.1

wait_for モジュールで指定の状態となるまで待機する

■ wait_for モジュールのパラメータ

  • host: ‘{{ inventory_hostname }}’
    • モニタリング対象ホストのIPアドレスを指定
    • インベントリに記載した対象機器のIPアドレスを指定している
  • port: ‘{{ ansible_ssh_port }}’
    • モニタリング対象のポート番号を指定
    • インベントリに記載した ssh ポートを指定している
  • state: stopped
    • モニタリング対象の状態を指定
    • stopped ⇒ モニタリング対象が停止するまで待つ

■ オプションについて

  • become: no
    • sudo で実行するとエラーとなるため no を指定
  • delegate_to: 127.0.0.1
    • 処理委任対象を指定している
    • 再起動するリモート側ではなくローカル側で処理するために 127.0.0.1 と指定している

対象機器の ssh ポートが up するのを待つ

以下の内容がこの処理に対応します。

    - name: Wait for SSH port up
      become: no
      wait_for:
        host: '{{ inventory_hostname }}'
        port: '{{ ansible_ssh_port }}'
        state: started
      delegate_to: 127.0.0.1

ポート down を待つ場合と比較して wait_for モジュールの state の値を started に変えた内容となります。

【参考】公式ドキュメント

Asynchronous actions and polling — Ansible Documentation
ansible.builtin.wait_for – Waits for a condition before continuing — Ansible Documentation
Controlling where tasks run: delegation and local actions — Ansible Documentation

―――――――――――――

タイトルとURLをコピーしました