＜Ansible＞「delegate_to」ディレクティブの使い方

#概要
この記事は、タスク単位で対象ホストを指定できる「delegate_to」ディレクティブの使い方を説明することが目的です。
公式ドキュメントでは、以下に示した値を「delegate_to」ディレクティブで使用できると説明しています。

◎単体ホストを対象とする場合
　・IPアドレス
　・hostname
◎インベントリで定義された特定のグループを対象とする場合
　・item変数（グループに属するホストをループする）

今回は以下の4パターンに分けて、公式ドキュメントに記載してある「delegate_to」ディレクティブの全機能を説明します。
①値にIPアドレスを指定した場合
②値にhostnameを指定した場合（グループ内の一ホスト）
③値にhostnameを指定した場合（localhost）
④インベントリで定義された特定のグループを指定した場合

公式ドキュメントは以下から確認できます。
・[delegate_to](https://docs.ansible.com/ansible/latest/user_guide/playbooks_delegation.html#id7)

インベントリは、以下のとおりです。
#####インベントリ

```
[group1]
192.168.101.1
192.168.101.2

[group2]
192.168.102.1
192.168.102.2

[group3]
192.168.103.1
```

それでは、①から順に説明していきます。
#①値にIPアドレスを指定した場合
インベントリで定義されたターゲットノードの中から、『192.168.101.1』を指定します。
Playbookは以下のとおりです。
#####Playbook

```
---
- hosts: all
  become: yes
  gather_facts: False

  tasks:
    - name: Create a directory
      file:
        path: /tmp/dir
        state: directory

    - name: Copy file
      copy:
        src: /etc/ansible/qiita.txt
        dest: /tmp/dir
      delegate_to: 192.168.101.1

    - name: Compress directory
      archive:
        path: /tmp
        dest: /tmp/archive.tgz
...
```

そうすることで、タスク「Copy file」は、『192.168.101.1』だけに対して実行されることになります。
結果は以下のとおりです。

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

TASK [Create a directory] **********************************************************************************************************************************************
 [WARNING]: Platform linux on host 192.168.102.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.2]
 [WARNING]: Platform linux on host 192.168.102.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.1]
 [WARNING]: Platform linux on host 192.168.101.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.2]
 [WARNING]: Platform linux on host 192.168.103.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.103.1]
 [WARNING]: Platform linux on host 192.168.101.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.1]

TASK [Copy file] *******************************************************************************************************************************************************
changed: [192.168.101.2 -> 192.168.101.1]
ok: [192.168.102.1 -> 192.168.101.1]
ok: [192.168.102.2 -> 192.168.101.1]
ok: [192.168.101.1 -> 192.168.101.1]
ok: [192.168.103.1 -> 192.168.101.1]

TASK [Compress directory] **********************************************************************************************************************************************
changed: [192.168.102.1]
changed: [192.168.103.1]
changed: [192.168.101.1]
changed: [192.168.101.2]
changed: [192.168.102.2]

PLAY RECAP *************************************************************************************************************************************************************
192.168.101.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.101.2                 : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.2                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.103.1                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

#②値にhostnameを指定した場合（グループ内の一ホスト）
「delegate_to」ディレクティブの値に、hostname『ec2-user@ip-192-168-101-1』を指定します。
Playbook、結果は以下のとおりです。
#####Playbook

```
---
- hosts: all
  become: yes
  gather_facts: False

  tasks:
    - name: Create a directory
      file:
        path: /tmp/dir
        state: directory

    - name: Copy file
      copy:
        src: /etc/ansible/qiita.txt
        dest: /tmp/dir
      delegate_to: ec2-user@ip-192-168-101-1

    - name: Compress directory
      archive:
        path: /tmp
        dest: /tmp/archive.tgz
...
```

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

TASK [Create a directory] **********************************************************************************************************************************************
 [WARNING]: Platform linux on host 192.168.102.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.1]
 [WARNING]: Platform linux on host 192.168.103.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.103.1]
 [WARNING]: Platform linux on host 192.168.101.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.1]
 [WARNING]: Platform linux on host 192.168.101.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.2]
 [WARNING]: Platform linux on host 192.168.102.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.2]

TASK [Copy file] *******************************************************************************************************************************************************
changed: [192.168.102.2 -> ec2-user@ip-192-168-101-1]
ok: [192.168.103.1 -> ec2-user@ip-192-168-101-1]
ok: [192.168.101.2 -> ec2-user@ip-192-168-101-1]
ok: [192.168.102.1 -> ec2-user@ip-192-168-101-1]
ok: [192.168.101.1 -> ec2-user@ip-192-168-101-1]

TASK [Compress directory] **********************************************************************************************************************************************
changed: [192.168.103.1]
changed: [192.168.101.1]
changed: [192.168.101.2]
changed: [192.168.102.1]
changed: [192.168.102.2]

PLAY RECAP *************************************************************************************************************************************************************
192.168.102.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.103.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.101.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.101.2                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.2                  : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

#③値にhostnameを指定した場合（localhost）
「delegate_to」ディレクティブの値を『localhost』にすることで、そのタスクをコントロールノードに対して実行します。
Playbook、結果は以下のとおりです。
#####Playbook

```
---
- hosts: all
  become: yes
  gather_facts: False

  tasks:
    - name: Create a directory
      file:
        path: /tmp/dir
        state: directory

    - name: Copy file
      copy:
        src: /etc/ansible/qiita.txt
        dest: /tmp/dir
      delegate_to: localhost

    - name: Compress directory
      archive:
        path: /tmp
        dest: /tmp/archive.tgz
...
```

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

TASK [Create a directory] **********************************************************************************************************************************************
 [WARNING]: Platform linux on host 192.168.101.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.1]
 [WARNING]: Platform linux on host 192.168.101.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.2]
 [WARNING]: Platform linux on host 192.168.103.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.103.1]
 [WARNING]: Platform linux on host 192.168.102.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.2]
 [WARNING]: Platform linux on host 192.168.102.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.1]

TASK [Copy file] *******************************************************************************************************************************************************
changed: [192.168.102.2 -> localhost]
changed: [192.168.103.1 -> localhost]
changed: [192.168.101.1 -> localhost]
changed: [192.168.102.1 -> localhost]
changed: [192.168.101.2 -> localhost]

TASK [Compress directory] **********************************************************************************************************************************************
changed: [192.168.102.1]
changed: [192.168.101.2]
changed: [192.168.103.1]
changed: [192.168.102.2]
changed: [192.168.101.1]

PLAY RECAP *************************************************************************************************************************************************************
192.168.101.1                 : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.101.2                 : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.1                 : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.2                  : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.103.1                  : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

値を『127.0.0.1』と指定した場合も、『localhost』という表示が『127.0.0.1』となるだけで、同様の動作をします。
#④インベントリで定義された特定のグループを指定した場合
Playbookは以下のとおりです。
#####Playbook

```
---
- hosts: all
  become: yes
  gather_facts: False

  tasks:
    - name: Create a directory
      file:
        path: /tmp/dir
        state: directory

    - name: Copy file
      copy:
        src: /etc/ansible/qiita.txt
        dest: /tmp/dir
      delegate_to: "{{ item }}"
      loop: "{{ groups['group2'] }}"

    - name: Compress directory
      archive:
        path: /tmp
        dest: /tmp/archive.tgz
...
```

「loop」ディレクティブで、インベントリで定義されたグループ『group2』内のホストをループします。「item」という変数には、『group2』内のホストのIPアドレスが格納されているので、「delegate_to」の値を「item」とします。
このようにすることで、インベントリで定義されたグループに対して処理を実行できます。

結果は以下のとおりです。

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

TASK [Create a directory] **********************************************************************************************************************************************
 [WARNING]: Platform linux on host 192.168.102.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.1]
 [WARNING]: Platform linux on host 192.168.101.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.2]
 [WARNING]: Platform linux on host 192.168.102.2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter
could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.102.2]
 [WARNING]: Platform linux on host 192.168.103.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.103.1]
 [WARNING]: Platform linux on host 192.168.101.1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

changed: [192.168.101.1]

TASK [Copy file] *******************************************************************************************************************************************************
changed: [192.168.102.2 -> 192.168.102.1] => (item=192.168.102.1)
ok: [192.168.103.1 -> 192.168.102.1] => (item=192.168.102.1)
ok: [192.168.101.1 -> 192.168.102.1] => (item=192.168.102.1)
ok: [192.168.101.2 -> 192.168.102.1] => (item=192.168.102.1)
ok: [192.168.102.1 -> 192.168.102.1] => (item=192.168.102.1)
changed: [192.168.102.2 -> 192.168.102.2] => (item=192.168.102.2)
ok: [192.168.103.1 -> 192.168.102.2] => (item=192.168.102.2)
ok: [192.168.101.2 -> 192.168.102.2] => (item=192.168.102.2)
ok: [192.168.102.1 -> 192.168.102.2] => (item=192.168.102.2)
ok: [192.168.101.1 -> 192.168.102.2] => (item=192.168.102.2)

TASK [Compress directory] **********************************************************************************************************************************************
changed: [192.168.103.1]
changed: [192.168.102.1]
changed: [192.168.102.2]
changed: [192.168.101.2]
changed: [192.168.101.1]

PLAY RECAP *************************************************************************************************************************************************************
192.168.101.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.101.2                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.1                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.102.2                  : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.103.1                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

『group2』内のホストのIPアドレスである『192.168.102.1』と『192.168.102.2』だけに対して、タスク「Copy file」が実行されていることを確認できました。
「loop」ディレクティブを「with_items」ディレクティブに変えても、同様の動作をします。