ansible で対象サーバを再起動する

ansible で対象サーバを再起動する方法を調べてみた。

Ansibleの事例とちょっとしたTips」を参考に、というか答え丸写しなのだが、いろいろなテクニックが使われている。

プレイブック作成

reboot.os.yml を作成する。

---
- hosts: '{{ hosts }}'
  tasks:
    - name: test connection (before reboot)
      ping:

    - name: reboot!
      command: shutdown -r now

    - name: wait for SSH port down
      local_action: wait_for host={{ inventory_hostname }} port=22 state=stopped

    - name: wait for SSH port up
      wait_for: host={{ inventory_hostname }} port=22 state=started delay=30
      delegate_to: 127.0.0.1

    - name: test connection (after reboot)
      ping:

このプレイブックを書いて学習できるポイントは以下の3点。

  1. wait_for モジュールの使い方
  2. local_action / delegate_to: 127.0.0.1 の使い方
  3. inventory_hostname 変数の使い方
wait_for モジュールの使い方
waitfor: host={{ inventory_hostname }} port=22 state=started delay=30

30秒待ってから、指定ホスト(inventory_hostname)の22番ポートがオープンするまで待機する。
30秒後からの確認間隔は1秒ごとで、デフォルトのタイムアウトは300秒。

リブートの場合は、一旦ポートが閉じたことを確認し、その後オープンするまで待つことで再起動したことを確認している。

local_action / delegate_to: 127.0.0.1 の使い方

local_action は ansible 実行ホスト上でモジュールを実行することの指示になる。文字通りローカルで実行する。
delegate_to は指定のホスト上でモジュールを実行することの指示になる。delegate_to の特殊ケース(127.0.0.1を指定した場合)が local_action ということになる。reboot.os.yaml では 2 回の wait_for でそれぞれ使い分けているが、深い意味は無い。

local_action や delegate_to の詳細は「Delegation, Rolling Updates, and Local Actions」を参照。

inventory_hostname 変数の使い方

プレイブック中で複数のサーバを対象にしていると、「対象」を指定する方法が欲しくなる。それが inventory_hostname 変数になる。

ただし、/etc/ansible/hosts で ansible_ssh_host=x.x.x.x の形でアドレス解決していて、OS の hosts に登録していないサーバを対象にする場合は注意すること。inventory_hostname は ansible_ssh_host が指定されている場合でもそのIPアドレスを表していない。よって、wait_for に渡すと、名前解決できないホスト名を渡すことになる。そうなるといつまでたってもポートのオープンを検知できないことになる(実はかなりハマった)。

動作確認

# ansible-playbook reboot.os.yml -e hosts=garnet-vm11

PLAY [garnet-vm11] ************************************************************ 

GATHERING FACTS *************************************************************** 
ok: [garnet-vm11]

TASK: [test connection (before reboot)] *************************************** 
ok: [garnet-vm11]

TASK: [reboot!] *************************************************************** 
changed: [garnet-vm11]

TASK: [wait for SSH port down] ************************************************ 
ok: [garnet-vm11 -> 127.0.0.1]

TASK: [wait for SSH port up] ************************************************** 
ok: [garnet-vm11 -> 127.0.0.1]

TASK: [test connection (after reboot)] **************************************** 
ok: [garnet-vm11]

PLAY RECAP ******************************************************************** 
garnet-vm11                : ok=6    changed=1    unreachable=0    failed=0