てくなべ (tekunabe)

ansible / network automation / 学習メモ

【Ansible】--tags オプションを複数した時にタグをマージするバージョンとしないバージョンがある

■ はじめに

Ansible 2.7 への ポーティングガイドを眺めていたら、このような記載がありました。

If you specify --tags or --skip-tags multiple times on the command line, Ansible will merge the specified tags together. In previous versions of Ansible, you could set merge_multiple_cli_tags to False if you wanted to keep only the last-specified --tags. This config option existed for backwards compatibility. The overwriting behavior was deprecated in 2.3 and the default behavior was changed in 2.4. Ansible-2.7 removes the config option; multiple --tags are now always merged.

ansible-playbook コマンドには実行したいタスク、したくないタスクをタグで指定する --tags--skip-tags オプションがあります。知らなかったのですが、 --tags--skip-tags オプションを複数指定したときの挙動を設定によって変更できたようです。

デフォルトの挙動も変更されていて、

  • Ansible 2.3 までは、最後に指定されたオプションのみ有効
  • Ansible 2.4 から、マージする

になったようです。そして、Ansible 2.7 から挙動を変更する設定項目自体なくるようです。

この記事では、バージョンによってデフォルトの挙動に差分があることを試した結果を記載します。

■ 検証

共通 Playbook

3つのタスクにそれぞれタグをつけたPlaybookを用意します。

---
- hosts: all
  gather_facts: no

  tasks:
    - name: task1
      debug:
        msg: "task1"
      tags:
        - t1

    - name: task2
      debug:
        msg: "task2"
      tags:
        - t2

    - name: task3
      debug:
        msg: "task3"
      tags:
        - t3

Assible 2.3

--tags=t1 --tags=t3 のように複数の指定をして実行します。

$ ansible --version
ansible 2.3.3.0
(...略...)
$ ansible-playbook -i localhost, tagtest.yml --tags=t1 --tags=t3
[DEPRECATION WARNING]: Specifying --tags multiple times on the command line currently uses the last
specified value. In 2.4, values will be merged instead.  Set merge_multiple_cli_tags=True in ansible.cfg to
 get this behavior now..
This feature will be removed in version 2.5. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.

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

TASK [task3] ***********************************************************************************************
ok: [localhost] => {
    "msg": "task3"
}

PLAY RECAP *************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

DEPRECATION WARNING とともに、t3 というタグが付けられたタスク tasks3 のみが実行されました。最後に指定した --tags=t3 のみが有効であることが分かります。

Assible 2.6

おなじく、--tags=t1 --tags=t3 のように複数の指定をして実行します。

$ ansible --version
ansible 2.6.3
(...略...)

$ ansible-playbook -i localhost, tagtest.yml --tags=t1 --tags=t3

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

TASK [task1] ***********************************************************************************************
ok: [localhost] => {
    "msg": "task1"
}

TASK [task3] ***********************************************************************************************
ok: [localhost] => {
    "msg": "task3"
}

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

今度は、t1t3 のタグが付けられたタスク task1task3 が実行されました。 --tags=t1 --tags=t3 という複数の指定がマージされたことが分かりました。

なお、--list-tags オプションを付けると実際にタスクを実行することなく、対象タグを確認できます。

$ ansible-playbook -i localhost, tagtest.yml --tags=t1 --tags=t3 --list-tags

playbook: tagtest.yml

  play #1 (all): all    TAGS: []
      TASK TAGS: [t1, t3]     ←★

■ まとめ

あまり、複数の --tags --skip-tags をオプションを付けて実行することは無いかもしれませんが、

  • Ansible 2.3 まではデフォルトで最後に指定されたオプションのみ有効。
  • Ansible 2.4 からデフォルトでマージされるようになった。設定で変更可能。
  • Ansible 2.7 では設定でも変更できなくなる。

という点は一応覚えておいたほうが良いかもしれません。

【Ansible】インベントリファイルのグループ親子関係の確認には ansible-inventory コマンドの --graph オプションが便利

Ansible には インベントリファイル の情報を表示するansible-inventory コマンドがあります。グループの親子関係を階層化して表示する--graph オプションが便利なのでご紹介します。

インベントリファイル

8個のホストを、種別(web/router)や地域、東日本、西日本のグループでに所属させています。

[sendai]
sendai-web01
sendai-rt01

[tokyo]
tokyo-web01
tokyo-rt01

[nagoya]
nagoya-web01
nagoya-rt01

[osaka]
osaka-web01
osaka-rt01


[east:children]
sendai
tokyo

[west:children]
nagoya
osaka


[web]
sendai-web01
tokyo-web01
nagoya-web01
osaka-web01

[router]
sendai-rt01
tokyo-rt01
nagoya-rt01
osaka-rt01

ansible-inventory コマンド実行(with --graph)

このように、ネストさせた親子関係も分かりやすく表示されます。

(a) [vagrant@centos7 demo]$ ansible-inventory -i inventory --graph
@all:
  |--@east:
  |  |--@sendai:
  |  |  |--sendai-rt01
  |  |  |--sendai-web01
  |  |--@tokyo:
  |  |  |--tokyo-rt01
  |  |  |--tokyo-web01
  |--@router:
  |  |--nagoya-rt01
  |  |--osaka-rt01
  |  |--sendai-rt01
  |  |--tokyo-rt01
  |--@ungrouped:
  |--@web:
  |  |--nagoya-web01
  |  |--osaka-web01
  |  |--sendai-web01
  |  |--tokyo-web01
  |--@west:
  |  |--@nagoya:
  |  |  |--nagoya-rt01
  |  |  |--nagoya-web01
  |  |--@osaka:
  |  |  |--osaka-rt01
  |  |  |--osaka-web01

【Ansible】ios_command / ios_config モジュールでエラー "unable to set terminal parameters" が表示される場合の対処

■ はじめに

検証環境で、ios_command モジュールや、ios_config モジュールを利用した Playbook 実行時に、以下のようなエラーメッセージに遭遇しました。

fatal: [172.16.0.2]: FAILED! => {"msg": "unable to set terminal parameters"}

自分が調べた方法と対処方法をご紹介します。

  • 確認環境: Ansible 2.6.2

■ エラーの原因

-vvv オプションを付けて Playbook を実行すると、plugins/terminal/ios.py の以下のコード分で例外が発生していることが分かりました。

    def on_open_shell(self):
        try:
            for cmd in (b'terminal length 0', b'terminal width 512'):
                self._exec_cli_command(cmd)
        except AnsibleConnectionFailure:
            raise AnsibleConnectionFailure('unable to set terminal parameters')  # ここ

つまり、ネットワーク機器にログイン後、terminal length 0 または terminal width 512 コマンドの実行に失敗していることになります。 一般ユーザーであっても、 terminal length 0 といったコマンドは実行できるはずだと思ったのですが、念のため手動でSSHでログインして terminal length 0 コマンドを実行しようとしたところエラーになってしまいました。

ip-172-31-15-25>ter len 0
                ^
% Invalid input detected at '^' marker.

おやおやと思って、コンフィグを見直すと

username testuser privilege 0  ...略...

のように権限を低くしすぎる設定誤りをしていました。 このため、terminal length 0 も実行できない状態となっていました。

■ 対処

ネットワーク機器側で

username testuser privilege 1   ...略...

username testuser privilege 15  ...略...

のように権限を変更したら解決しました。

(2018/08/30 追記)

issue があげられていました。 github.com

(2019/06/06 追記)

関連していそうなプルリクが Ansible 2.8 にマージされているようです。 github.com

カイゼン・ジャーニー・カンファレンスの資料まとめ

はじめに

2018/08/18 に開催された、カイゼン・ジャーニー・カンファレンスの登壇者の皆様資料を、私が見つけた範囲でまとめます。登壇者のみなさまありがとうございました。 もし他にもありましたら、 @akira6592 まで教えていたけると助かります。更新いたします。

devlove.doorkeeper.jp

togetter.com

■ 第1部

白子 佳孝 さん

www.slideshare.net

石垣雅人 さん

www.slideshare.net

佐藤彩子 さん

www.slideshare.net

hiroshi.takeda さん

加藤翼 さん

横地晃(私です)

www.slideshare.net



■ 第2部: A列車

takarada masafumi さん

www.slideshare.net

新田智啓 さん

Kenta Sasa さん

山田哲寛 さん

カイゼン・ジャーニーの謎 その1 ~『それぞれの持ち場で。がんばる』ための『前線基地』~)



■ 第2部: B列車

UGA さん

Tetsuro Machida さん

(自然発生型リーダーにtryする)

スガサワ さん

-

はち さん

www.slideshare.net

森一樹 さん

参加者によるレポート

qiita.com

Ansible 2.7 で導入予定のネットワークモジュール cli_configを試す

■ はじめに

現在開発中の Ansible 2.7 (develブランチ) で、ネットワーク機器への 設定系 コマンドを投入するモジュール cli_config が登場しました。

なお、同じく Ansible 2.7 で開発中の 参照系 コマンドを実行するモジュール cli_command については過去記事「Ansible 2.7 で導入予定のネットワークモジュール cli_configを試す」をご参照ください。

この記事では、Junos で試した結果を記載します。

基本情報

cli_config モジュール 公式ドキュメント

cli_config - Push text based configuration to network devices over network_cli — Ansible Documentation

コード (cli_config.py)

ansible/cli_config.py at devel · ansible/ansible · GitHub

※現在(2018/8/14)開発中のため、仕様が変わる可能性があります。


■ 準備(開発版 Ansible のインストール)

pip install git+https://github.com/ansible/ansible.git@devel

現在、これで開発中の Ansible 2.7 がインストールされます。



■ Juniper Junos で試す

インベントリファイル

以下のインベントリファイルを用意します。今回は各変数は Playbook 内で定義することにします。

[junos]
172.16.0.1

Playbook(netconf指定で失敗パターン)

今回は、単純に set system ntp server 10.0.0.123 の1行を投入する Playbook を試すことにします。 junos_config モジュールの lines オプションはリストで指定できるのに対して、 cli_config モジュールの config オプションは文字列での指定になる点は注意が必要です。

コネクションプラグインには、junos_config モジュールと同じ調子で netconf を試してみます。(後述しますが失敗します)

- hosts: junos
  gather_facts: no

  tasks:
    - name: config test
      cli_config:
        config: set system ntp server 10.0.0.123

  vars:
    ansible_connection: netconf
    ansible_network_os: junos
    ansible_user: testuser
    ansible_ssh_pass: testuserpsss

実行(netconf指定で失敗パターン)

おっと、エラーになってしまいました。

(ansibledev) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory cli_config.yml

PLAY [junos] **********************************************************************************************

TASK [config test] ****************************************************************************************
fatal: [172.16.0.1]: FAILED! => {"changed": false, "msg": "Connection type netconf is not valid for cli_config module"}
        to retry, use: --limit @/vagrant/cli_config.retry

PLAY RECAP ************************************************************************************************
172.16.0.1                 : ok=0    changed=0    unreachable=0    failed=1

どうやら、このモジュールは netconf コネクションプラグインは対応していないようです。

後で気がついたのですが、ドキュメントにきちんと

This module provides platform agnostic way of pushing text based configuration to network devices over network_cli connection plugin.

という記載がありました。

となれば、次に試すべきは network_cli コネクションプラグインなので試してみます。

Playbook(network_cli指定で成功パターン)

- hosts: junos
  gather_facts: no

  tasks:
    - name: config test
      cli_config:
        config: set system ntp server 10.0.0.123

  vars:
    ansible_connection: network_cli    # network_cli にしてみる
    ansible_network_os: junos
    ansible_user: testuser
    ansible_ssh_pass: testuserpsss

実行(network_cli指定で成功パターン)

今度は正常に完了しました。

(ansibledev) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory cli_config.yml

PLAY [junos] **********************************************************************************************

TASK [config test] ****************************************************************************************
changed: [172.16.0.1]

PLAY RECAP ************************************************************************************************
172.16.0.1                 : ok=1    changed=1    unreachable=0    failed=0

念の為、Junos側で設定が入ったことを確認します。

root@vsrx1# show system ntp | display set
set system ntp server 10.0.0.123

無事に入りました。


■ まとめ

簡単ですが、 cli_config モジュールの動作を確認しました。 最近のネットワークモジュールは、プラットフォームに依存しないタイプ(内部で ansible_network_os変数を見てプラットフォーム固有モジュールを呼ぶ?)も増えてきており、 cli_config モジュールもその流れだと思います。

ネットワークモジュールとしては、cli_configcli_command モジュールの登場が Ansible 2.7 の特徴の一つと言えるでしょう。

【Ansible】ping 系モジュールまとめ(ping/win_ping/ios_ping/nxos_ping/net_ping)

Ansible には ping モジュールや net_ping モジュールなど、モジュール名に ping が含まれるものがいくつかあります。 名前は似ていますが、どこからどこへの ping なのか、何のプロトコルを使うのか、などの点で性質が異なります。

例えば、 公式ドキュメントの ping モジュールの説明には

For Network targets, use the net_ping module instead.

とありますが、net_ping モジュールは ping モジュールとは用途や性質が異なり、代わりにはならず混乱してしまうのではないかと思い、一旦以下にまとめます。

モジュール名 from to プロトコル 補足
ping コントロールホスト ターゲットホスト コネクションプラグインに依存(*1)
win_ping コントロールホスト ターゲットホスト WinRM
ios_ping ターゲットホスト dest オプション指定先 ICMP Cisco IOSping コマンドを生成して、ターゲットホスト上で実行する
nxos_ping ターゲットホスト dest オプション指定先 ICMP Cisco NX-OS の ping コマンドを生成して、ターゲットホスト上で実行する
net_ping ターゲットホスト dest オプション指定先 ICMP ansible_network_os 変数に応じて、ios_pingnxos_ping モジュールを利用する
  • *1 : ping モジュールのプロトコルについて
    • 利用するコネクションプラグインに依存します
      • ssh / paramiko: sshPython スクリプトを送って実行できるか
      • network_cli: SSH でネットワーク機器に接続できるか
      • netconf: NETCONF でネットワーク機器に接続できるか

[2020/01/05 追記] network_clinetconf についての上記の挙動は Ansible 2.8 までです。Ansible 2.9 では、ネットワーク機器に接続しない仕様に変更されました。

[Ansible] ネットワーク機器に接続する条件はバージョンやコネクションブラグインによって異なる - てくなべ (tekunabe)

参考

【Ansible】when はタスクの最後に指定しなくても良い

(このツイートのブログ版です)

■ はじめに

Ansible の Playbook では、特定の条件を満たすときのみそのタスクを実行するという指定に when が利用できます。

上記のサンプルでもタスクの最後に when を指定していて、Web上などの他のサンプルでも最後に指定しているものが多い印象があります。 ですが、実際は YAML 的にはマッピング(ディクショナリ)なので、順番にどこでも大丈夫です。以下にパターンを記載します。

■ タスクの最後に when を指定する例

よくあるパターンです。大丈夫です。

---
- hosts: junos
  gather_facts: no

  tasks:
    - junos_command:
        commands:
          - show version
      when: true == true    # ここに書くサンプルが多い

■ タスクの最初に when を指定する例

---
- hosts: junos
  gather_facts: no

  tasks:
    - when: true == true    # ここでもOK
      junos_command:
        commands:
          - show version

コードの if分のイメージに近いでしょうか。

if true == true:
  do_something()

■ タスクの途中に when を指定する例

途中でも大丈夫です。

- hosts: junos
  gather_facts: no

  tasks:
    - name: commandtest
      when: true == true    # ここでもOK
      junos_command:
        commands:
          - show version

■ 注意点

この記事は「こう書いても動く」ということを示すのみであり、特にどれが推奨という意図はありません。 プロジェクト指定の書き方や、慣例に合わせるなどの事情に従っていただければと思います。