てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] ホストを動的にグループ化する group_by モジュール

はじめに

group_by モジュールは、Playbook 実行中に動的にグループ化できます。

用途は色々考えられますが、この記事では、複数台の Cisco IOS 機器のバージョンを収集した上で、特定のバージョン飲みを対象とする Play を実行する例をご紹介します。

  • 環境
    • ansible 2.9.14


インベントリファイル

以下の3台です。参考までに各機器のバージョンをコメントで記載します(変数ではありません)。

[cml]
ios01 ansible_host=192.168.1.11     # 15.9(3)M2
ios02 ansible_host=192.168.1.12     # 15.9(3)M2
iosxe01 ansible_host=192.168.1.13   # 17.03.01a

この3台の中で、17系である、iosxe01 に絞る Playbook を作ります。

Playbook

最初の Play で facts を収集して、その中の ansible_facts.net_version をキーにしてグループ化します。 次の Playbook で グループ ios17 のみを対象としたタスクを実行します。ここではただ facts を表示するだけです。

バージョンは 17.03.01a であれば 1715.9(3)M2 であれば 15 のように、系で扱うことにします。

---
- hosts: cml
  gather_facts: false

  tasks:
    # facts の収集、対象は最小限に
    - name: gather facts
      ios_facts:    # gather_facts: true でも代用可
        gather_subset:
          - min

    # バージョンでグループ化
    - name: group by verion
      group_by:
        key: "ios{{ ansible_facts.net_version | regex_replace('^([0-9]+)\\..+$', '\\1') }}"

# 特定のグループのみを対象とした Play
- hosts: ios17
  gather_facts: false

  tasks:
    # デバッグ
    - debug:
        msg: "{{ ansible_facts }}"


実行

Playbook を実行します。2つめの Playbook で 17 系である iosxe01 のみが実行対象になっていることが分かります。

$ ansible-playbook -i inventory.ini group_by.yml

PLAY [cml] ***********************************************************************************************

TASK [gather facts] **************************************************************************************
[WARNING]: default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards
ok: [iosxe01]
ok: [ios01]
ok: [ios02]

TASK [group by verion] ***********************************************************************************
changed: [ios01]
changed: [ios02]
changed: [iosxe01]

PLAY [ios17] *********************************************************************************************

TASK [debug] *********************************************************************************************
ok: [iosxe01] => {
    "msg": {
        "net_api": "cliconf",
        "net_gather_network_resources": [],
        "net_gather_subset": [
            "default"
        ],
        "net_hostname": "iosxe01",
        "net_image": "bootflash:packages.conf",
        "net_iostype": "IOS-XE",
        "net_model": "CSR1000V",
        "net_python_version": "3.6.7",
        "net_serialnum": "XXXXXXXX",
        "net_system": "ios",
        "net_version": "17.03.01a",
        "network_resources": {}
    }
}

PLAY RECAP ***********************************************************************************************
ios01           : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ios02           : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
iosxe01         : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

なお、ansible-playbook コマンドに -v をつけて実行すると、group_by モジュールどのようにグループ化された確認できます。

TASK [group by verion] **********************************************************************
changed: [ios01] => {"add_group": "ios15", "changed": true, "parent_groups": ["all"]}
changed: [iosxe01] => {"add_group": "ios17", "changed": true, "parent_groups": ["all"]}
changed: [ios02] => {"add_group": "ios15", "changed": true, "parent_groups": ["all"]}


おわりに

対象ホストを絞るときに、when で条件を付けることがあると思いますが、場合によってはこのように動的にグループ化して Play を分けたほうがよいケースもあるかもしれません。