web-dev-qa-db-ja.com

Ansibleを使用してサーバーの再起動を待つ方法は?

私はこれを使用してサーバーを再起動してから待機しようとしています:

- name: Restart server
  Shell: reboot

- name: Wait for server to restart
  wait_for:
    port=22
    delay=1
    timeout=300

しかし、私はこのエラーを受け取ります:

TASK: [iptables | Wait for server to restart] ********************************* 
fatal: [example.com] => failed to transfer file to /root/.ansible/tmp/ansible-tmp-1401138291.69-222045017562709/wait_for:
sftp> put /tmp/tmpApPR8k /root/.ansible/tmp/ansible-tmp-1401138291.69-222045017562709/wait_for

Connected to example.com.
Connection closed
42
ChocoDeveloper

Wait_forタスクを local_action として実行するように変更し、待機しているホストを指定する必要があります。例えば:

- name: Wait for server to restart
  local_action:
    module: wait_for
      Host=192.168.50.4
      port=22
      delay=1
      timeout=300
34
Shahar

Ansible> = 2.7(2018年10月にリリース)

新しい reboot モジュールを使用します。

Ansible <2.7

タスクとして再起動

- name: restart server
  Shell: 'sleep 1 && shutdown -r now "Reboot triggered by Ansible" && sleep 1'
  async: 1
  poll: 0
  become: true

これにより、シェルコマンドが 非同期タスク として実行されるため、Ansibleはコマンドの終了を待機しません。通常、async paramはタスクの最大時間を提供しますが、pollが0に設定されているため、コマンドが終了した場合、Ansibleは決してポーリングしません。 shutdownの前後でスリープするのは、Ansibleがリモートホストに接続されている間に再起動中にSSH接続が切断されるのを防ぐためです。

タスクとして待つ

あなただけを使用することができます:

- name: Wait for server to restart
  local_action:
    module: wait_for
      Host={{ inventory_hostname }}
      port=22
      delay=10
    become: false

..しかし、{{ ansible_ssh_Host }}変数はホスト名および/または{{ ansible_ssh_port }}次のようなエントリを使用する場合、SSHホストおよびポートとして:

hostname         ansible_ssh_Host=some.other.name.com ansible_ssh_port=2222 

..インベントリ内(Ansible hostsファイル)。

これは wait_for タスクを実行します Ansibleを実行しているマシン上 。このタスクは、リモートホストでポート22が開くまで待機し、10秒遅れて開始します。

再起動してハンドラーとして待機する

ただし、これらの両方をタスクではなくハンドラーとして使用することをお勧めします。

これを行う主な理由は2つあります。

  • コードの再利用-ハンドラを多くのタスクに使用できます。 例:トリガーサーバーの再起動 タイムゾーンの変更後 およびカーネルの変更後、

  • 一度だけトリガーする-いくつかのタスクにハンドラーを使用し、それらの2つ以上が何らかの変更を行う=>ハンドラーをトリガーする場合、ハンドラーが行うことは一度だけ行われます。 例:httpdの設定変更とSSL証明書の更新にhttpd再起動ハンドラーが接続されている場合、設定とSSL証明書の両方が変更された場合、httpdが再起動されます1回だけ。

ハンドラーについて詳しく読む here

ハンドラーとしての再起動と再起動の待機:

  handlers:

    - name: Restart server
      command: 'sleep 1 && shutdown -r now "Reboot triggered by Ansible" && sleep 1'
      async: 1
      poll: 0
      ignore_errors: true
      become: true

    - name: Wait for server to restart
      local_action:
        module: wait_for
          Host={{ inventory_hostname }}
          port=22
          delay=10
        become: false

..そしてタスクシーケンスで次のように使用します。ここでは、サーバーハンドラーの再起動と組み合わせます。

  tasks:
    - name: Set hostname
        hostname: name=somename
        notify:
          - Restart server
          - Wait for server to restart

ハンドラはnotifyにリストされている順序ではなく、定義された順序で実行されます

53
Greg Dubicki

私が持っている1.9.4で最も信頼性が高い(これは更新され、元のバージョンは下部にあります):

- name: Example ansible play that requires reboot
  Sudo: yes
  gather_facts: no
  hosts:
    - myhosts
  tasks:
    - name: example task that requires reboot
      yum: name=* state=latest
      notify: reboot sequence
  handlers:
    - name: reboot sequence
      changed_when: "true"
      debug: msg='trigger machine reboot sequence'
      notify:
        - get current time
        - reboot system
        - waiting for server to come back
        - verify a reboot was actually initiated
    - name: get current time
      command: /bin/date +%s
      register: before_reboot
      Sudo: false
    - name: reboot system
      Shell: sleep 2 && shutdown -r now "Ansible package updates triggered"
      async: 1
      poll: 0
      ignore_errors: true
    - name: waiting for server to come back
      local_action: wait_for Host={{ inventory_hostname }} state=started delay=30 timeout=220
      Sudo: false
    - name: verify a reboot was actually initiated
      # machine should have started after it has been rebooted
      Shell: (( `date +%s` - `awk -F . '{print $1}' /proc/uptime` > {{ before_reboot.stdout }} ))
      Sudo: false

asyncオプションに注意してください。 1.8および2.0は0しかし1.9はそれを望んでいる1。上記では、マシンが実際にリブートされたかどうかも確認します。再起動に失敗したタイプミスがあり、失敗の兆候がないため、これは良いことです。

大きな問題は、マシンが起動するのを待っていることです。このバージョンは、330秒間そこにとどまり、それ以前にホストにアクセスしようとしません。他のいくつかの回答では、ポート22の使用が推奨されています。これらの両方が当てはまる場合、これは適切です。

  • マシンに直接アクセスできます
  • ポート22が開いた直後にマシンにアクセスできる

これらは常に真実とは限らないので、5分の計算時間を浪費することにしました。

ところで、ハンドラーを使用することを提案する答えは素晴らしいです。私からのハンドラーに対して+1(およびハンドラーを使用するように回答を更新しました)。

元のバージョンはここにありますが、それほど良くなく、それほど信頼できません。

- name: Reboot
  Sudo: yes
  gather_facts: no
  hosts:
    - OSEv3:children
  tasks:
    - name: get current uptime
      Shell: cat /proc/uptime | awk -F . '{print $1}'
      register: uptime
      Sudo: false
    - name: reboot system
      Shell: sleep 2 && shutdown -r now "Ansible package updates triggered"
      async: 1
      poll: 0
      ignore_errors: true
    - name: waiting for server to come back
      local_action: wait_for Host={{ inventory_hostname }} state=started delay=30 timeout=300
      Sudo: false
    - name: verify a reboot was actually initiated
      # uptime after reboot should be smaller than before reboot
      Shell: (( `cat /proc/uptime | awk -F . '{print $1}'` < {{ uptime.stdout }} ))
      Sudo: false
10
akostadinov

2018アップデート

2.3の時点で、Ansibleはwait_for_connectionモジュール。これはまさにこの目的に使用できます。

#
## Reboot
#

- name: (reboot) Reboot triggered
  command: /sbin/shutdown -r +1 "Ansible-triggered Reboot"
  async: 0
  poll: 0

- name: (reboot) Wait for server to restart
  wait_for_connection:
    delay: 75

Shutdown -r +1は、戻りコード1が戻されないようにし、タスクを失敗させる可能性があります。シャットダウンは非同期タスクとして実行されるため、wait_for_connectionタスクは少なくとも60秒。 75は、これらのスノーフレークケース用のバッファーを提供します。

wait_for_connection-リモートシステムが到達可能/使用可能になるまで待機

8
infrascripting

Shaharの投稿にコメントしたかったのですが、ハードコードされたホストアドレスを使用している方が、現在のホストansibleが{{inventory_hostname}}を構成していることを参照する変数を持っているため、彼のコードは次のようになります:

- name: Wait for server to restart
  local_action:
    module: wait_for
     Host={{ inventory_hostname }}
     port=22
     delay=1
     timeout=300
6
Walid

Ansibleの新しいバージョン(私の場合は1.9.1)では、pollおよびasyncパラメーターを0に設定するだけでは十分でない場合があります(どのディストリビューションがansibleにセットアップされているかによって異なります)。 https://github.com/ansible/ansible/issues/10616 で説明されているように、1つの回避策は次のとおりです。

- name: Reboot
  Shell: sleep 2 && shutdown -r now "Ansible updates triggered"
  async: 1
  poll: 0
  ignore_errors: true

そして、このページの多くの回答で説明されているように、再起動が完了するまで待ちます。

5
amichaud

試行錯誤と多くの読み物を通して、これが最終的にAnsibleの2.0バージョンを使用して私にとってうまくいったことです:

$ ansible --version
ansible 2.0.0 (devel 974b69d236) last updated 2015/09/01 13:37:26 (GMT -400)
  lib/ansible/modules/core: (detached HEAD bbcfb1092a) last updated 2015/09/01 13:37:29 (GMT -400)
  lib/ansible/modules/extras: (detached HEAD b8803306d1) last updated 2015/09/01 13:37:29 (GMT -400)
  config file = /Users/sammingolelli/projects/git_repos/devops/ansible/playbooks/test-2/ansible.cfg
  configured module search path = None

SELinuxを無効にし、必要なときにノードを再起動するための私のソリューション:

---
- name: disable SELinux
  selinux: state=disabled
  register: st

- name: reboot if SELinux changed
  Shell: shutdown -r now "Ansible updates triggered"
  async: 0
  poll: 0
  ignore_errors: true
  when: st.changed

- name: waiting for server to reboot
  wait_for: Host="{{ ansible_ssh_Host | default(inventory_hostname) }}" port={{ ansible_ssh_port | default(22) }} search_regex=OpenSSH delay=30 timeout=120
  connection: local
  Sudo: false
  when: st.changed

# vim:ft=ansible:
4
slm

私は、他のロールから動的に呼び出されるreboot_server ansibleロールを作成しました:

- name: Reboot server if needed
  include_role:
    name: reboot_server
  vars:
    reboot_force: false

役割の内容は次のとおりです。

- name: Check if server restart is necessary
  stat:
    path: /var/run/reboot-required
  register: reboot_required

- name: Debug reboot_required
  debug: var=reboot_required

- name: Restart if it is needed
  Shell: |
    sleep 2 && /sbin/shutdown -r now "Reboot triggered by Ansible"
  async: 1
  poll: 0
  ignore_errors: true
  when: reboot_required.stat.exists == true
  register: reboot
  become: true

- name: Force Restart
  Shell: |
    sleep 2 && /sbin/shutdown -r now "Reboot triggered by Ansible"
  async: 1
  poll: 0
  ignore_errors: true
  when: reboot_force|default(false)|bool
  register: forced_reboot
  become: true

# # Debug reboot execution
# - name: Debug reboot var
#   debug: var=reboot

# - name: Debug forced_reboot var
#   debug: var=forced_reboot

# Don't assume the inventory_hostname is resolvable and delay 10 seconds at start
- name: Wait 300 seconds for port 22 to become open and contain "OpenSSH"
  wait_for:
    port: 22
    Host: '{{ (ansible_ssh_Host|default(ansible_Host))|default(inventory_hostname) }}'
    search_regex: OpenSSH
    delay: 10
  connection: local
  when: reboot.changed or forced_reboot.changed

これはもともとUbuntu OSで動作するように設計されました。

0
Gio Salvador

これについてはあまり目立ちませんが、最近の変更( https://github.com/ansible/ansible/pull/43857 )に「ignore_unreachable」キーワードが追加されました。これにより、次のようなことができます。

- name: restart server
  Shell: reboot
  ignore_unreachable: true

- name: wait for server to come back
  wait_for_connection: 
      timeout: 120

- name: the next action
  ...
0
bagelbyte

リモートサーバーのDNSセットアップがまだない場合は、変数ホスト名の代わりにIPアドレスを渡すことができます。

- name: Restart server
  command: shutdown -r now

- name: Wait for server to restart successfully
  local_action:
    module: wait_for
      Host={{ ansible_default_ipv4.address }}
      port=22
      delay=1
      timeout=120

ansible-swap playbook (新しいDigital Oceanドロップレットに4GBのスワップをインストールするため)の最後に追加した2つのタスクです。

0
Aaron Tribou
- wait_for:
    port: 22
    Host: "{{ inventory_hostname }}"
  delegate_to: 127.0.0.1
0
Moriarty