handlers セクション

2019/05/05

Ansible

 Ansible Documentation

Handlers: Running Operations On Change

 機能

  • タスクを実行した結果、対象ホストの状態が変更になった( = changed )ときに一度だけ実行する処理(タスク)
  •  tasks セクション内の複数のタスクから呼び出された場合でも、handlers セクション内のタスクは一度だけ実行する
  •  play 内の tasks セクションに含まれるすべてのタスクの実行終了後、handlers セクション内のタスクが一度だけ実行される
  •  handlers セクション内に複数のタスクが定義されている場合、定義されている順番に実行される

 構造

シナリオ:CentOS7.6.1810 を minimal インストールしたサーバーの初期設定」で使用した play です。
---
- hosts: all
  gather_facts: no
  
  vars_files:
    - accounts.yml
    - packages.yml

  tasks:
      - name: グループを作成
        group:
          name: "{{ item.gname }}"
          gid: "{{ item.gid }}"
          state: present
        loop:
          "{{ accounts }}"
      - name: ユーザーの作成
        user:
          name: "{{ item.uname }}"
          uid: "{{ item.uid }}"
          group: "{{ item.gname }}"
          password: "{{ item.password | password_hash('sha512') }}"
          state: present
        loop:
          "{{ accounts }}"
      - name: sudoers の設定
        template:
          src: ./sudoers.j2
          dest: /etc/sudoers.d/{{ item.uname }}
          mode: 0440
          owner: root
          group: root
          validate: '/usr/sbin/visudo -cf %s'
        loop:
          "{{ accounts }}"
      - name: 追加パッケージのインストール
        yum:
          name: "{{ item }}"
          state: latest
        loop:
          "{{ packages }}"
      - name: 既存パッケージの更新
        yum:
          name: '*'
          state: latest
      - name: 再起動
        reboot: 
 play の最後に reboot モジュールで対象ホストを再起動しています。再起動が必要なのは
  • 追加パッケージのインストール
  • 既存パッケージの更新
の実行結果が changed のときです。
  • グループの作成
  • ユーザーの作成
  • sudoers の設定
上記の 3 つの処理の結果が ok / changed のどちらであっても再起動は不要です。 handlers セクションを使用して play を書き直します。
---
- hosts: all
  gather_facts: no
  
  vars_files:
    - accounts.yml
    - packages.yml

  handlers:
      - name: 再起動
        reboot: 
        listen: "Managed Node Reboot"

  tasks:
      - name: グループを作成
        group:
          name: "{{ item.gname }}"
          gid: "{{ item.gid }}"
          state: present
        loop:
          "{{ accounts }}"
      - name: ユーザーの作成
        user:
          name: "{{ item.uname }}"
          uid: "{{ item.uid }}"
          group: "{{ item.gname }}"
          password: "{{ item.password | password_hash('sha512') }}"
          state: present
        loop:
          "{{ accounts }}"
      - name: sudoers の設定
        template:
          src: ./sudoers.j2
          dest: /etc/sudoers.d/{{ item.uname }}
          mode: 0440
          owner: root
          group: root
          validate: '/usr/sbin/visudo -cf %s'
        loop:
          "{{ accounts }}"
      - name: 追加パッケージのインストール
        yum:
          name: "{{ item }}"
          state: latest
        loop:
          "{{ packages }}"
        notify: "Managed Node Reboot" 
      - name: 既存パッケージの更新
        yum:
          name: '*'
          state: latest
        notify: "Managed Node Reboot" 
 tasks セクションと handlers セクションのタスクは notify: と listen: で関連付けします。 notify: でタスクの実行結果が changed のときに実行する handlers セクション内のタスクを指定します。上記の play の実行結果です。
[ansibleman@ansiblesv ansible]$ ansible-playbook -i hosts.yml site.yml

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

TASK [グループを作成] *****************************************************************
changed: [node-c0706] => (item={u'uname': u'workman', u'password': u'workman@node_c0706', u'gid': 1000, u'uid': 1001, u'gname': u'staff'})

TASK [ユーザーの作成] *****************************************************************
changed: [node-c0706] => (item={u'uname': u'workman', u'password': u'workman@node_c0706', u'gid': 1000, u'uid': 1001, u'gname': u'staff'})

TASK [sudoers の設定] *************************************************************
changed: [node-c0706] => (item={u'uname': u'workman', u'password': u'workman@node_c0706', u'gid': 1000, u'uid': 1001, u'gname': u'staff'})

TASK [追加パッケージのインストール] **********************************************************
changed: [node-c0706] => (item=open-vm-tools)

TASK [既存パッケージの更新] **************************************************************
changed: [node-c0706]

RUNNING HANDLER [再起動] **********************************************************
changed: [node-c0706]

PLAY RECAP *********************************************************************
node-c0706                 : ok=6    changed=6    unreachable=0    failed=0   

[ansibleman@ansiblesv ansible]$
 handlers セクションは何回呼び出されても実行は一度だけです。「追加パッケージのインストール」と「既存パッケージの更新」で handlers セクション内のタスクを呼び出していますが、「再起動」は 1 回だけ実行しています。 次は Ansible Documentaion に記載されている例です。
handlers:
    - name: restart memcached
      service:
        name: memcached
        state: restarted
      listen: "restart web services"
    - name: restart apache
      service:
        name: apache
        state:restarted
      listen: "restart web services"

tasks:
    - name: restart everything
      command: echo "this task will restart the web services"
      notify: "restart web services"
この例は tasks セクションの「 restart everything 」の実行結果が changed の場合、handlers セクション内の「 restart memcached 」と「 restart apache 」の 2 つのタスクを実行します。このように tasks セクションと handlers セクションのタスクの組み合わせは 1 : 1 、1 : n 、n : 1 のいずれでも可能です。

カテゴリー

目次

QooQ