てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] cisco.ios.ios_config モジュールの冪等性に関する警告 "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" について

はじめに

Cisco IOS のネットワーク機器に任意のコンフィグを投入する、cisco.ios.ios_config というモジュールがあります。

本モジュールを使ったPlaybookを実行して changed になると、以下のような冪等性に関する警告が表示されます。

% ansible-playbook -i inventory.ini test_ios_config.yml

PLAY [ios01] **********************************************************************

TASK [ios_config test] ************************************************************
[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
changed: [ios01]

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

こちらについて説明します。

警告の意味

この警告は、冪等性を確保するために、各オプションで指定するコマンドは、機器の show running-config で表示される形式と同じにしてくださいね、いう警告です。

(仮に同じ形式にしてもこの警告は表示されます)

cisco.ios.ios_config モジュールの Notes に同じようなことが書かれています。

To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they appear if present in the running configuration on device including the indentation.

他、*_config モジュール共通の仕様として、FAQ にも関連の項目 "Why do the *_config modules always return changed=true with abbreviated commands?" があります。

本モジュールは、まず linessrcparents オプションに与えられるコンフィグの内容と、機器側の show running-config の内容を比較して、実際に投入が必要なコンフィグ差分を求めてから、コンフィグを生成、投入する動作です。

この比較は文字列の比較のため、フル表記と省略表記、大文字小文字違い、スペース有無の違いなどは別物として扱われます。

たとえば、以下のとおりです。

  • interface GigabitEthernet0/0int Gi0/0 は別物
    • 省略してしまっている
  • interface GigabitEthernet0/0interface gigabitethernet0/0 は別物
    • 大文字のところが小文字になっている
  • interface GigabitEthernet0/0interface GigabitEthernet 0/0 は別物
    • スペースが空いている

※ 本警告は、cisco.ios コレクション 1.3.0 から表示されるようになりました。しばらくは changed でも ok でも表示される仕様でした。cisco.ios コレクション 2.3.0 で、changed のときのみ表示されるように変更されました。

合わせないと毎回 changed になる

実際は、show running-config の内容と異なる形式でもコマンドとして有効な場合は、エラーにならずにコマンド自体は実行できます。しかし、同じPlaybookをもう一度実行すると、また差分ありと判断され、またコンフィグを投入します。

結果的に、毎回 changed になります。2回目の実行以降、設定が実質的に変わらないのに changed になってしまうのは少し混乱の元ですね。

具体的にどう指定するのが良いのか

たとえば、show running-config 上、

interface GigabitEthernet0/0

とあったら、Playbook 上も以下のように表記を合わせます。

- name: ios_config test
  cisco.ios.ios_config:
    lines:
      - description kingyo
    parents:
      - interface GigabitEthernet0/0    # 表記を合わせる

src オプション利用時は、インデントの数も合わせる必要があります。詳細は以下の記事を参照してください。

https://tekunabe.hatenablog.jp/entry/2018/12/22/ansible_ios_config_src_needs_indents

なお、このように表記を合わせても、changed の場合は警告自体は表示されます。Ansibleとしては「changed になったけど意図通りですか?冪等性保つためにこうしてくださいね」という親切心からの警告なのだと思います。

どうしても警告を非表示したいときは、ansible.cfg[defaults] セクションで action_warnings=False を指定するという対策もありますが、他の警告も無効にしてしまうので注意が必要です。

駄目なパターン

だめな例1: 省略表記にしてしまっている

- name: ios_config test
  cisco.ios.ios_config:
    lines:
      - description kingyo
    parents:
      - iint Gi0/0    # 表記があってない

だめな例2: 小文字になってしまっている

- name: ios_config test
  cisco.ios.ios_config:
    lines:
      - description kingyo
    parents:
      - interface gigabitethernet0/0    # 表記があってない

だめな例3: スペースが入ってしまっている

- name: ios_config test
  cisco.ios.ios_config:
    lines:
      - description kingyo
    parents:
      - interface GigabitEthernet 0/0    # 表記があってない

だめな例4: lines で省略表記にしてしまっている

事情は lines オプションでも同様です。

- name: ios_config test
  cisco.ios.ios_config:
    lines:
      - desc kingyo  # ここがあっていない
    parents:
      - interface GigabitEthernet0/0    # ここはあってても

ほか、デフォルトのコンフィグを投入する場合も注意が必要です。たとえば、no shutdown がデフォルトな機器に対して no shutdown を実行するのも、やはり毎回 changed になってしまいます。show running-config 上に no shutdown がデフォルトのため存在しなく、Ansible が投入が必要だと判断するためです。この場合については、cisco.ios.ios_interfacesモジュールの enabled オプションで制御するほうが良いです。毎回 changed にならない仕様になってます。

参考: 専用モジュールだと

本警告はあくまでも cisco.ios.ios_config モジュールによるものです。

ここまでの例で出した、インターフェースの description の設定であれば、インターフェースの基本設定の専用モジュール cisco.ios.ios_interfacesでもできます。cisco.ios.ios_interfaces モジュールの場合は、以下のようにインターフェース名が show running-config の表記とあっていなくても、冪等性が担保されます。内部でノーマライズされるようです。

- name: ios_interfaces test
  cisco.ios.ios_interfaces:
    config:
      - name: Gi 0/0  # 省略してる上にスペースが余分
        description: kingyo

ただ、省略の仕方にはばらつきがあるので、やはりshow running-config と合わせるほうが丁寧で良いかなと思います。

おわりに

手動の場合は、省略形のまま実行したり、大文字小文字も気にせずコマンドを実行することも多いと思います。

本モジュール利用時は、手癖や習慣にとらわれず、実機を確認するのが良さそうです。