📝

Ansibleを試してみた(jinja2編)

2024/12/31に公開

設定変更をするのにワンラインなんてことはないわけで複数の設定変更ってのを試してみた

cli_config

cli_configを使った複数設定変更
これは単純に1行ずつベタ書きするだけなのでAnsibleに詳しくなくても比較的容易にメンテ出来る
保守容易性ってのが優れていると言うのか

新たにset_ntp_jのroleを作ってやってみる

構成

ban@UoVb:~/ansible$ tree --charset=C
.
|-- after
|-- ansible.cfg
|-- before
|-- group_vars
|-- inventory.ini
|-- junos_config.yml
|-- log
`-- roles
    |-- set_int_j
    |   |-- tasks
    |   |   `-- main.yml
    |   `-- vars
    |       `-- main.yml
    |-- set_ntp_j
    |   |-- tasks
    |   |   `-- main.yml
    |   `-- vars
    |       `-- main.yml
    |-- show_conf_j
    |   |-- tasks
    |   |   `-- main.yml
    |   `-- vars
    |       `-- main.yml
    `-- show_ver_j
        |-- tasks
        |   `-- main.yml
        `-- vars
            `-- main.yml

17 directories, 11 files
ban@UoVb:~/ansible$

ファイルの中身

  • roles/set_ntp_j/tasks/main.yml
    • 複数行のコマンドを実行したい時は先頭に | (パイプ)を入れて繋げるとうまくいく
ban@UoVb:~/ansible$ cat roles/set_ntp_j/tasks/main.yml
---
- name: config interface
  cli_config:
          config: |
                  set system ntp server 1.1.1.1
                  set system ntp server 1.1.1.2
                  set system ntp server 1.1.1.3
          backup: yes
          backup_options:
                  filename: "{{ inventory_hostname }}_before_{{ lookup('pipe', 'date +%Y%m%d%H%M') }}"
                  dir_path: /home/ban/ansible/before

ban@UoVb:~/ansible$
  • roles/set_ntp_j/vars/main.yml
ban@UoVb:~/ansible$ cat roles/set_ntp_j/vars/main.yml
---
ansible_become: true
ansible_become_method: enable
ansible_network_os: junos
ansible_password: ****
ansible_user: ban
ansible_connection: network_cli

ban@UoVb:~/ansible$

ansible実行前

ban@vsrx1> show configuration system ntp

ban@vsrx1>
ban@vsrx2> show configuration system ntp

ban@vsrx2>

ansible実行

ban@UoVb:~/ansible$ ansible-playbook -i inventory.ini junos_config.yml --tags set_ntp_j

PLAY [Junos Configure] ******************************************************************************************************************

TASK [set_ntp_j : config interface] *****************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the
running configuration on device including the indentation
changed: [vsrx2]
changed: [vsrx1]

PLAY RECAP ******************************************************************************************************************************
vsrx1                      : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
vsrx2                      : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

ban@UoVb:~/ansible$

ansible実行後

ban@vsrx1> show configuration system ntp
server 1.1.1.1;
server 1.1.1.2;
server 1.1.1.3;

ban@vsrx1>
ban@vsrx2> show configuration system ntp
server 1.1.1.1;
server 1.1.1.2;
server 1.1.1.3;

ban@vsrx2>

ただ、世のトレンドはjinja2らしいのでせっかくなのでやってみる
伝統的なコア-ディストリビューション-エッジよりもリーフ-スパインが主流になってるんでact/stnadbyではなくleaf/spineを想定してinventoryを↓に修正

  • 修正前
ban@UoVb:~/ansible$ cat inventory.ini
[junos]
vsrx1 ansible_host=10.0.2.110
vsrx2 ansible_host=10.0.3.110

[junosact]
vsrx1 ansible_host=10.0.2.110

[junosstby]
vsrx2 ansible_host=10.0.3.110

[cisco]
cisco1 ansible_host=10.0.2.210
cisco2 ansible_host=10.0.3.210
ban@UoVb:~/ansible$
  • 修正後
ban@UoVb:~/ansible$ cat inventory.ini
[junosall]
vsrx1 ansible_host=10.0.2.110
vsrx2 ansible_host=10.0.3.110

[junospine]
vsrx1 ansible_host=10.0.2.110

[junosleaf]
vsrx2 ansible_host=10.0.3.110

[cisco]
cisco1 ansible_host=10.0.2.210
cisco2 ansible_host=10.0.3.210
ban@UoVb:~/ansible$

jinja2

jinja2だとtemplatesディレクトリ作ってテンプレートを作成しておかなきゃいけないのと、テンプレートに埋め込むパラメータが必要になるのでこんな感じにしてみた

構成

ban@UoVb:~/ansible$ tree --charset=C
.
|-- after
|-- ansible.cfg
|-- before
|-- group_vars #こいつを新しく作った
|   |-- junosleaf.yml #こいつを新しく作った
|   `-- junosspine.yml #こいつを新しく作った
|-- inventory.ini #こいつは中身を編集した
|-- junos_config.yml
|-- log
`-- roles
    |-- set_int_j
    |   |-- tasks
    |   |   `-- main.yml #こいつは中身を編集した
    |   |-- templates #こいつを新しく作った
    |   |   `-- config.j2 #こいつを新しく作った
    |   `-- vars
    |       `-- main.yml
    |-- set_ntp_j
    |   |-- tasks
    |   |   `-- main.yml
    |   |-- templates #こいつを新しく作った
    |   |   `-- config.j2 #こいつを新しく作った
    |   `-- vars
    |       `-- main.yml
    |-- show_conf_j
    |   |-- tasks
    |   |   `-- main.yml
    |   `-- vars
    |       `-- main.yml
    `-- show_ver_j
        |-- tasks
        |   `-- main.yml
        `-- vars
            `-- main.yml

18 directories, 14 files
ban@UoVb:~/ansible$

編集したものたち

  • inventory.ini
    • グループ名を変更した
    • 別にact/stbyのままでも良かったけれども・・・
ban@UoVb:~/ansible$ cat inventory.ini
[junosall]
vsrx1 ansible_host=10.0.2.110
vsrx2 ansible_host=10.0.3.110

[junosspine]
vsrx1 ansible_host=10.0.2.110

[junosleaf]
vsrx2 ansible_host=10.0.3.110

[cisco]
cisco1 ansible_host=10.0.2.210
cisco2 ansible_host=10.0.3.210
ban@UoVb:~/ansible$
  • role/set_int_j/tasks/main.yml
    • 1行ずつコマンドラインを打ち込む形式からjinja2テンプレートを参照する方式に変更
ban@UoVb:~/ansible$ cat roles/set_int_j/tasks/main.yml
---
- name: config template
  cli_config:
         config: "{{ lookup('template', '/home/ban/ansible/roles/set_int_j/templates/config.j2') }}"
         backup: yes
         backup_options:
                 filename: "{{ inventory_hostname }}_before_{{ lookup('pipe', 'date +%Y%m%d%H%M') }}"
                 dir_path: /home/ban/ansible/before

ban@UoVb:~/ansible$

新しくつくったものたち

  • group_vars
    • inventoryのグループごとにjinja2のパラメータをまとめている
  • group_vars/junosspine.yml
    • 基本的に後述のconfig.j2の変数と同じ名前にしてればおk
    • 最後のパラメータのstatusは設定追加する時(junosではset)の時はadd、削除する時(junosではdelete)の時はdeleteとするとテンプレートから自動選択できるようにしたかっただけ
    • #でコメントアウトしなくても毎回statusのパラメータをadd or deleteにすれば別に2行書かなくてもいいからそっちの方がばっちくないかも
ban@UoVb:~/ansible$ cat group_vars/junosspine.yml
---
set_int_j_conf:
#        - { ifname: ge-0/0/3, desc: fromSPINEtoLEAF, status: add }
        - { ifname: ge-0/0/3, desc: "", status: delete }

set_ntp_j_conf:
        - { name: "", ipaddr: 1.1.1.1, status: add }
        - { name: "", ipaddr: 1.1.1.2, status: add }
        - { name: "", ipaddr: 1.1.1.3, status: add }
#        - { name: "", ipaddr: 1.1.1.1, status: delete }
#        - { name: "", ipaddr: 1.1.1.2, status: delete }
#        - { name: "", ipaddr: 1.1.1.3, status: delete }
ban@UoVb:~/ansible$
  • group_vars/junosleaf.yml
    • junosspine.ymlと書き方は変わらない
    • 今回はちゃんと別々のパラメータを読み込んでいるか(vsrx1はgroup/vars/junosspine.yml、vsrx2はgroup_vars/junosleaf.yml)確認するためにdescriptionの名前とntpサーバのアドレスを敢えて違うやつにしている
    • spaineとleafで機能差分がありそうだったから分けただけ
      • 例えば、spineの方にはL3の設定をすることが多ければjunosspine.ymlの方にL3の設定変更のパラメータばっかり書いておいて、leafの方にはL2の設定をすることが多ければjunosleaf.ymlの方にはL2の設定変更のパラメータばっかり書いておくとか
ban@UoVb:~/ansible$ cat group_vars/junosleaf.yml
---
set_int_j_conf:
        - { ifname: ge-0/0/3, desc: fromLEAFtoSPINE, status: add }
#        - { ifname: ge-0/0/3, desc: "", status: delete }

set_ntp_j_conf:
        - { name: "", ipaddr: 1.1.2.1, status: add }
        - { name: "", ipaddr: 1.1.2.2, status: add }
        - { name: "", ipaddr: 1.1.2.3, status: add }
#        - { name: "", ipaddr: 1.1.2.1, status: delete }
#        - { name: "", ipaddr: 1.1.2.2, status: delete }
#        - { name: "", ipaddr: 1.1.2.3, status: delete }
ban@UoVb:~/ansible$
  • role/set_int_j/templates
    • jinja2のテンプレートを格納しておくディレクトリ
  • role/set_int_j/templates/config.j2
    • テンプレートファイル
    • junosへのコマンドラインを書いて可変部分に変数を設定するだけ
    • if分が普通に使えるのでadd=set、delete=deleteにしている
ban@UoVb:~/ansible$ cat roles/set_int_j/templates/config.j2
{% for setint in set_int_j_conf %}
{% if setint.status == "add" %}
        set interfaces {{ setint.ifname }} description {{ setint.desc }}
{% elif setint.status == "delete" %}
        delete interfaces {{ setint.ifname }} description {{ setint.desc }}
{% endif %}
{% endfor %}

ban@UoVb:~/ansible$
  • role/set_ntp_j/templates
    • jinja2のテンプレートを格納しておくディレクトリ
  • role/set_ntp_j/templates/config.j2
    • テンプレートファイル
    • junosへのコマンドラインを書いて可変部分に変数を設定するだけ
    • if分が普通に使えるのでadd=set、delete=deleteにしている
ban@UoVb:~/ansible$ cat roles/set_ntp_j/templates/config.j2
{% for setint in set_ntp_j_conf %}
{% if setint.status == "add" %}
        set system ntp server {{ setint.ipaddr }}
{% elif setint.status == "delete" %}
        delete system ntp server {{ setint.ipaddr }}
{% endif %}
{% endfor %}

ban@UoVb:~/ansible$

jinja2でAnsibleを試してみた

実行してみる

実行前

  • junos_config.yml
ban@UoVb:~/ansible$ cat junos_config.yml
---
- name: Junos Configure
  hosts: junosall
  strategy: free
  gather_facts: no

  roles:
          - { role: show_conf_j, tags: show_conf_j }
          - { role: show_ver_j, tags: show_ver_j }
          - { role: set_int_j, tags: set_int_j }
          - { role: set_ntp_j, tags: set_ntp_j}

ban@UoVb:~/ansible$
  • vsrxたち
ban@vsrx1> show interfaces descriptions

ban@vsrx1>

ban@vsrx1> show configuration system ntp

ban@vsrx1>
ban@vsrx2> show interfaces descriptions

ban@vsrx2>

ban@vsrx2> show configuration system ntp

ban@vsrx2>

ansible実行

ban@UoVb:~/ansible$ ansible-playbook -i inventory.ini junos_config.yml --tags set_int_j,set_ntp_j

PLAY [Junos Configure] ******************************************************************************************************************************************

TASK [set_int_j : config template] ******************************************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on
device including the indentation
changed: [vsrx2]
changed: [vsrx1]

TASK [set_ntp_j : config template] ******************************************************************************************************************************
changed: [vsrx2]
changed: [vsrx1]

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

ban@UoVb:~/ansible$

実行後

  • ちゃんとvsrx1(junosspine)とvsrx2(junosleaf)で正しいパラメータを読み込みんでいる
ban@vsrx1> show interfaces descriptions
Interface       Admin Link Description
ge-0/0/3        up    up   fromSPINEtoLEAF

ban@vsrx1>

ban@vsrx1> show configuration system ntp
server 1.1.1.1;
server 1.1.1.2;
server 1.1.1.3;

ban@vsrx1>
ban@vsrx2> show interfaces descriptions
Interface       Admin Link Description
ge-0/0/3        up    up   fromLEAFtoSPINE

ban@vsrx2>

ban@vsrx2> show configuration system ntp
server 1.1.2.1;
server 1.1.2.2;
server 1.1.2.3;

ban@vsrx2>

Discussion