Ansible:with_itemsについて(Ansible 2.9.6)

インフラサーバ

作業環境

  • CentOS 8.0
  • Python 3.7.7
  • Ansible 2.9.6

同じ処理内容の繰り返し

一部入力パラメータが異なるが他の内容は同様の処理を繰り返し実行したい場合があります。

単純な記法

例えば、複数のサービスを起動させたい場合 Playbook に単純に記載すると以下のようになります。

■ Playbook 例1

- hosts: all
  become: yes
  tasks:
    - name: 'Start service: firewalld'
      service:
        name: firewalld
        state: started
    - name: 'Start service: rsyslog'
      service:
        name: rsyslog
        state: started
    - name: 'Start service: postfix'
      service:
        name: postfix
        state: started

対象サービスの数が増えると service モジュールの内容を何度も記載することになるため
Playbook の内容が長くなり、読みにくくなります。

with_items を使用した記法

Playbook 例1 を見ると、各タスク間での service モジュールのパラメータの差分は
 name だけです。

このような場合、with_items を用いて、以下のように書き換えることができます。

■ Playbook 例2

- hosts: all
  become: yes
  tasks:
    - name: 'Start services'
      service:
        name: '{{ item }}'
        state: started
      with_items:
        - firewalld
        - rsyslog
        - postfix

service モジュールへの入力の一部を変数にして、with_items で入力値のリストを記載しています。入力値を使用する箇所では ‘{{ item }}’ と記述します。
このように記述すると、with_items で記載した各入力値に対して順にモジュールが実行されることになります。

Playbook の内容が短くなり、読みやすくもなります。

Playbook 例2 を実行すると以下のような結果となります。

# ansible-playbook -i hosts playbook.yml

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

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

TASK [Start services] ***********************************************************************************************
ok: [localhost] => (item=firewalld)
ok: [localhost] => (item=rsyslog)
ok: [localhost] => (item=postfix)

PLAY RECAP **********************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

with_items で複数の値を指定する

Playbook 例2 では、サービス名だけを with_items で指定しましたが、
次に示すように複数の値を with_items で指定することもできます。

■ Playbook 例3

- hosts: all
  become: yes
  tasks:
    - name: 'Start services'
      service:
        name: '{{ item.name }}'
        state: started
        enabled: '{{ item.enabled }}'
      with_items:
        - name: firewalld
          enabled: yes
        - name: rsyslog
          enabled: no
        - name: postfix
          enabled: no

Playbook 例2 では、with_items で入力値のリストを記載しましたが、Playbook 例3 では入力値の組のリストを記載しています。

入力値の組のリストを記載する場合、with_items の中では 「項目名: 値」 の書式で記載し、
項目値を使用する部分では ‘{{ item.項目名 }}’ と記載します。

各入力値の組に対して、順にモジュールが実行されることになります。

Playbook 例3 を実行すると以下のような結果となります。

# ansible-playbook -i hosts playbook.yml

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

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

TASK [Start services] ***********************************************************************************************
ok: [localhost] => (item={'name': 'firewalld', 'enabled': True})
ok: [localhost] => (item={'name': 'rsyslog', 'enabled': False})
ok: [localhost] => (item={'name': 'postfix', 'enabled': False})

PLAY RECAP **********************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Loop に関する公式ドキュメント

Loops — Ansible Documentation

【参考】yum モジュールについて

yum モジュールで複数のパッケージをインストールすることもよくあると思います。

この場合も対象パッケージを変数として with_items を使用することが考えられますが、実際には yum に対しては with_items の使用は推奨されておらず、使用すると以下のような警告が表示されます。

[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via 
squash_actions is deprecated. Instead of using a loop to supply multiple items 
and specifying `name: {{ item }}`, please use `name: ['git', 'gcc']` and remove
 the loop. This feature will be removed in version 2.11. Deprecation warnings 
can be disabled by setting deprecation_warnings=False in ansible.cfg.

yum モジュールについては、以下のように name に対してリスト形式で記載することができるため、with_items は使用しない方が良さそうです。

  yum:
    name:
      - package1
      - package2
      - package3

※ with_items を使用した場合、内部的には上のように記述した場合と同じ処理となるように入力値をリスト化してモジュールに入力し、モジュールの実行を1度だけにしているようです

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

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