【注意】FortiGate ver.7.4.5 からすべてのモデルでファームウェア自動更新機能がデフォルト有効になりました> Membership

Ansible で Cisco IOS 機器の設定を行うための Playbook 作成ガイド

目次

本記事について

本記事では、Red Hat から提供されている構成管理ツールである Ansible を使用して、ネットワーク機器である Cisco IOS 機器を設定する方法の一例を説明します。

動作確認環境

本記事は以下の環境にて検証した結果に基づき作成されています。

  • Ansible 環境
    • CentOS Stream release 9
    • Python 3.12.6
    • pip 24.2
    • ansible-core 2.17.4
    • Ansible community version 10.4.0
    • cisco.ios 8.0.0
  • ターゲット機器環境
    • Cisco C891FJ-K9
      • Cisco IOS 15.8(3)M9
    • Cisco Catalyst2960-8TC-L
      • Cisco IOS 12.2(55)SE12

前提

本記事では、Cisco IOS 機器を Ansible を使用して設定する方法について記載します。Ansible でターゲット機器を操作するためには、Ansible からターゲット機器に対して、SSH 接続できる必要があります。このため、Cisco IOS 機器側では以下の最低限の設定がされていることを前提とします。

Cisco IOS 機器側で前提となる設定
  • ホスト名設定
  • ドメイン名設定
  • RSA鍵の作成
  • SSHログイン用ユーザの設定
  • enableパスワードの設定
  • SSH接続を受け付けるインターフェースのIPアドレス設定
  • ルーティング設定(必要な場合)
  • line vty の設定
    • login local
    • transport input ssh/all

ここでは Cisco IOS 機器を対象としています。同じ Cisco 機器でも OS の異なる Nexus や ASA 等は対象外となります。

また Ansible では Cisco IOS 機器に SSH 接続するための初期設定が完了していることを前提とします。

CentOS Stream 9 での Ansible のインストール方法についてはこちらの記事を参照してください。

想定するネットワーク構成

ここでは以下のようにターゲットとなる Cisco IOS 機器と Ansible マシンが L2 ネットワークで接続されている環境で操作を行うことを想定します。

使用する Ansible コレクション及びモジュール

本記事では Cisco IOS 機器を設定するために、cisco.ios コレクションの ios_config モジュールを使用します。

cisco.ios コレクションは、ansible パッケージをインストールするとデフォルトで含まれています。

cisco.ios コレクションがインストールされているかどうかはansible-galaxy collection listコマンドで確認できます。以下のようにcisco.iosが表示されていればインストールされています。

(venv) [root@CentOSST9 ~]# ansible-galaxy collection list

# /root/venv/lib/python3.12/site-packages/ansible_collections
Collection                               Version
---------------------------------------- -------
amazon.aws                               8.2.1
ansible.netcommon                        6.1.3
ansible.posix                            1.5.4
ansible.utils                            4.1.0
ansible.windows                          2.5.0
(中略)
cisco.aci                                2.10.1
cisco.asa                                5.0.1
cisco.dnac                               6.18.0
cisco.intersight                         2.0.17
cisco.ios                                8.0.0
cisco.iosxr                              9.0.0
cisco.ise                                2.9.3
(以下略)

なお、cisco.ios コレクションには Cisco IOS の特定コンフィグ項目を設定することに特化したモジュールがいくつかありますが、一般的なネットワーク構築案件にてキッティングを行う場合コンフィグを丸ごと設定するため、特定のコンフィグ項目を対象としたモジュールを使用することは効率の面でメリットがありません。

本記事では、インプット情報として設定投入に使える機器コンフィグ全体があることを前提として、そのコンフィグを単純にそのまますべて機器に投入する方式を取ることとします。このためには ios_config モジュールを使用します。

インベントリの作成

ターゲット機器の情報を記載したインベントリファイルを作成します。

本記事では hosts という名前で以下内容のファイルを作成します。

[ios]
RT01 ansible_host=10.1.1.1 ansible_user=admin ansible_password=admin ansible_become_password=admin configfile=rt.conf
SW01 ansible_host=10.1.1.50 ansible_user=admin ansible_password=adminadmin ansible_become_password=admin configfile=sw.conf

[ios:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=cisco.ios.ios
ansible_become=yes
ansible_become_method=enable
  • [ios]
    • iosという名前のターゲット機器グループを定義し、RT01 と SW01 という名前のメンバーを定義すると同時に機器固有の変数を定義。変数は半角スペース区切りで複数設定できます
      • ansible_host:ターゲット機器のIPアドレス
      • ansible_user:SSH ログインユーザ名。変数名変更不可
      • ansible_password:SSH ログインユーザパスワード。変数名変更不可
      • ansible_become_password:Cisco IOS の enable パスワード。変数名変更不可
      • configfile:設定するコンフィグを記載したファイル。変数名変更可能(後に作成するPlaybook内で変数名を使用)
  • [ios:vars]
    • iosグループ内の共通変数を定義
    • ansible_connection
      • ターゲット機器への接続方法の設定
      • ターゲット機器が Cisco IOS 機器の場合 ansible.netcommon.network_cli を指定
    • ansible_network_os
      • ターゲット機器がどのネットワークプラットフォームに対応しているかの設定
      • ターゲット機器が Cisco IOS 機器の場合 cisco.ios.ios を指定
    • ansible_become=yes
      • Cisco IOS 機器で特権モードに移行するために必要
    • ansible_become_method=enable
      • Cisco IOS 機器で特権モードに移行するために必要

Playbook の作成

Cisco IOS 機器を設定変更するための Playbook を作成します。

コンフィグファイルの用意

本記事ではあらかじめ用意しておいた投入コマンドを記載したコンフィグファイルを Playbook から読み込む方式とするため、コンフィグファイルをインベントリに記載した変数 configfile で指定したファイル名で用意します。

本記事の例ではルータ用のコンフィグファイルとして「rt.conf」、スイッチ用のコンフィグファイルとして「sw.conf」を用意します。

version 15.8
service timestamps debug datetime msec
service timestamps log datetime msec localtime show-timezone year
no service password-encryption
!
hostname Router01

(中略)

!
!
end
version 12.2
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname Switch01

(中略)

line vty 5 15
 login local
 transport input all
!
end

本記事では設定後の想定コンフィグをそのまま投入コンフィグとして使用します。このコンフィグファイルは、設定後の差分確認処理でも使用します。

Playbook の作成

本記事では ios_configure.yml というファイル名で Playbook を作成します。

Playbook の処理内容は以下の通りとします。

  • cisco.ios.ios_config モジュールを使用して設定変更
    • src オプションを使用して外部のコンフィグファイルを読み込みます
  • cisco.ios.ios_config モジュールを使用して設定後のコンフィグと想定コンフィグの差分確認
    • diff_againstintended_config オプションを使用します
  • cisco.ios.ios_config モジュールを使用して startup-config に設定を保存します
    • save_when: always オプションを使用します

作成する Playbook の内容は以下の通りです。

- name: Playbook Test
  hosts: ios
  gather_facts: no

  tasks:
    - name: Configure IOS
      cisco.ios.ios_config:
        src: "{{ configfile }}"
    - name: Check the running-config against master config
      cisco.ios.ios_config:
        diff_against: intended
        intended_config: "{{ lookup('file', '{{ configfile }}') }}"
      diff: yes
    - name: Save running to startup
      cisco.ios.ios_config:
        save_when: always
  • hosts: ios
    • ターゲット機器として ios グループを指定しています
  • src: “{{ configfile }}”
    • 設定変更で使用するコンフィグファイルとして対象機器の変数 configfile で指定したファイルを使用します
  • diff_against: intended
    • 外部ファイルとのコンフィグ比較をする場合に指定します
  • intended_config: “{{ lookup(‘file’, ‘{{ configfile }}’) }}”
    • 比較で使用するファイルとして対象機器の変数 configfile で指定したファイルを使用します
  • diff: yes
    • コンフィグ比較を行うためにモジュール単位で diff を有効化します
  • save_when: always
    • cisco.ios.ios_config モジュールで設定を保存する場合はこのオプションを使用します

Playbook の実行

Playbook の実行コマンドは以下です。

Playbook の実行
  • ansible-playbook -i <インベントリ> <Playbook>

以下は実行例です。

(venv) [root@CentOSST9 ansible]# ansible-playbook -i hosts ios_configure.yml

PLAY [Playbook Test] ************************************************************************************************

TASK [Configure IOS] ************************************************************************************************
ok: [RT01]
ok: [SW01]

TASK [Check the running-config against master config] ***************************************************************
ok: [RT01]
ok: [SW01]

TASK [Save running to startup] **************************************************************************************
changed: [SW01]
changed: [RT01]

PLAY RECAP **********************************************************************************************************
RT01                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
SW01                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

2つ目のタスクの差分確認で差分が無かった場合上記例の様に単に ok と表示されますが、差分があった場合は以下のようにステータスが changed になり差分が表示されます。

(venv) [root@CentOSST9 ansible]# ansible-playbook -i hosts ios_configure.yml

PLAY [Playbook Test] ************************************************************************************************

TASK [Configure IOS] ************************************************************************************************
ok: [RT01]
ok: [SW01]

TASK [Check the running-config against master config] ***************************************************************
ok: [RT01]
--- before
+++ after
@@ -11,7 +11,6 @@
 no aaa new-model
 system mtu routing 1500
 vtp mode transparent
-no ip domain-lookup
 ip domain-name test.com
 spanning-tree mode pvst
 spanning-tree extend system-id
@@ -20,8 +19,6 @@
 vlan 10,20,30,179
 ip tftp source-interface Vlan1
 ip ssh version 2
-interface Loopback0
- ip address 2.2.2.2 255.255.255.255
 interface FastEthernet0/1
  switchport access vlan 10
  switchport mode access

changed: [SW01]

TASK [Save running to startup] **************************************************************************************
changed: [SW01]
changed: [RT01]

PLAY RECAP **********************************************************************************************************
RT01                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
SW01                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

事後コンフィグをファイルに保存する処理を追加する

設定変更後のコンフィグをファイルに保存したいということも考えられますので、以下の処理を Playbook に追加します。

  • cisco.ios.ios_facts モジュールでコンフィグ含む機器情報を取得する
  • copy モジュールで取得したコンフィグをファイルに保存する

更新後の Playbook の内容は以下の通りです。

- name: Playbook Test
  hosts: ios
  gather_facts: no

  tasks:
    - name: Configure IOS
      cisco.ios.ios_config:
        src: "{{ configfile }}"
    - name: Check the running-config against master config
      cisco.ios.ios_config:
        diff_against: intended
        intended_config: "{{ lookup('file', '{{ configfile }}') }}"
      diff: yes
    - name: Save running to startup
      cisco.ios.ios_config:
        save_when: always
    - name: Gather facts
      cisco.ios.ios_facts:
        gather_subset: config
    - name: save file
      copy:
        content: "{{ ansible_net_config }}"
        dest: ./config/{{ ansible_net_hostname }}_{{ now(False, '%Y%m%d') }}.txt

17行目以降が追加した内容です。

  • cisco.ios.ios_facts:Cisco 機器の様々な情報を取得できるモジュールです
    • gather_subset: config
      • running-config を含む情報を取得します
  • copy:指定した内容を指定したパスに保存するモジュールです
    • content: “{{ ansible_net_config }}”
      • 保存する内容を指定しています。ansible_net_configcisco.ios.ios_facts で取得した running-config が保存される変数です
    • dest:
      • 保存先ファイルパスを指定しています。上記例では Playbook と同フォルダ内にある config フォルダ配下のパスを指定しています
      • ansible_net_hostnamecisco.ios.ios_facts で取得したホスト名が保存される変数です
      • now(False, ‘%Y%m%d’) では現在の年月日を指定しています

以下は実行結果です。

(venv) [root@CentOSST9 ansible]# ansible-playbook -i hosts ios_configure.yml

PLAY [Playbook Test] ************************************************************************************************

TASK [Configure IOS] ************************************************************************************************
ok: [RT01]
ok: [SW01]

TASK [Check the running-config against master config] ***************************************************************
ok: [RT01]
ok: [SW01]

TASK [Save running to startup] **************************************************************************************
changed: [SW01]
changed: [RT01]

TASK [Gather facts] *************************************************************************************************
ok: [RT01]
ok: [SW01]

TASK [save file] ****************************************************************************************************
changed: [SW01]
changed: [RT01]

PLAY RECAP **********************************************************************************************************
RT01                       : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
SW01                       : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

最後の copy タスクについては、ファイルが新規作成された、または既存ファイルの内容が変更された場合、ステータスは changed になります。

実行後以下のようにコンフィグを記録したファイルが保存されます。

(venv) [root@CentOSST9 ansible]# ls -l config
合計 8
-rw-r--r-- 1 root root 2462  9月 23 15:45 Router01_20240923.txt
-rw-r--r-- 1 root root 1557  9月 23 15:45 Switch01_20240923.txt

保存されたファイルの内容は以下のようになっています。

Building configuration...


Current configuration : 2399 bytes
!
! Last configuration change at 12:14:48 JST Mon Sep 23 2024
!
version 15.8
service timestamps debug datetime msec
service timestamps log datetime msec localtime show-timezone year
no service password-encryption
!
hostname Router01

(中略)

!
!
!
end

対話的メッセージが表示される設定変更への対応

IOS 機器で、例えば既存ユーザを削除するコマンドを実行した場合、以下のような確認メッセージが表示されキー押下待ちの状態になります。

This operation will remove all username related configurations with same name.Do you want to continue? [confirm]

この仕様がモジュールの実行結果に不具合を起こす場合があります。

cisco.ios.ios_config モジュールで設定変更を行う場合、設定コマンド1行実行毎にコンフィグモードのプロンプトを待ってから次のコマンドを実行するという流れになるため、上記のような確認メッセージが表示される場合プロンプト待ち状態から処理が進まなくなり以下のようにタイムアウトエラーになってしまいます。

TASK [Configure IOS] *****************************************************************************
fatal: [RT01]: FAILED! => {“changed”: false, “module_stderr”: “command timeout triggered, timeout value is 30 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide.”, “module_stdout”: “”, “msg”: “MODULE FAILURE\nSee stdout/stderr for the exact error”}

cisco.ios.ios_config モジュールではこのような対話的な操作には対応できません。回避策としては以下の方法があります。

  • 対話的な操作が必要な設定のみ特権モードからコマンドを実行する cisco.ios.ios_command モジュールを使用してタスクを分ける
  • 対話的な操作が必要な設定のみ対象項目の設定用モジュールを使用してタスクを分ける

cisco.ios.ios_command モジュールを使用する方法

cisco.ios.ios_command モジュールでは対話的な操作に対応するためのオプションが用意されているため、これを利用します。

以下はユーザ削除を行う場合のタスク例です。

    - name: Delete user
      cisco.ios.ios_command:
        commands:
          - command: "conf t"
          - command: "no username test"
            prompt: "[confirm]"
            answer: "y"
  • commands:
    • リスト形式で実行コマンドリストを定義します
  • - command: "conf t"
    • cisco.ios.ios_command モジュールは特権モードからコマンドを実行するため、まずグローバルコンフィギュレーションモードに移行します
  • - command: "no username test"
    • ユーザ削除用のコマンドです
  • prompt: "[confirm]"
    • 待ち受ける文字列を指定します。メッセージ全体である必要は無く、部分的な文字列でも大丈夫です
    • この文字列を受信した際にanswer:で指定した文字列を送信します
  • answer: "y"
    • prompt:で指定した文字列を受信した際に送信する文字列を指定しています

対象項目の設定用モジュールを使用する方法

cisco.ios コレクションでは、いくつかの設定項目についてはその項目を設定するためのモジュールが用意されています。これらの設定用モジュールを使用して設定変更する場合は対話的な操作を考慮する必要はなく、より安全に設定変更をすることができます。

例えばユーザを設定するためのモジュールとしてcisco.ios.ios_userというモジュールが存在します。

以下はユーザ削除を行う場合のタスク例です。

    - name: Delete user
      cisco.ios.ios_user:
        name: test
        state: absent
  • name: test
    • 対象のユーザ名として「test」を指定しています
  • state: absent
    • 対象ユーザの状態を指定しています。「absent」を指定するとユーザが存在しない状態となり、対象ユーザが存在する場合はそのユーザが削除されます

参考資料


Ansible 関連記事一覧

Amazon アフィリエイトリンク

以下は Amazon アフィリエイトリンクです。インフラエンジニアにそこそこおすすめなアイテムです。

note メンバーシップへの参加もお待ちしています!

note(ノート)
陰の構築者たちのメンバーシップ|シェイド@陰の構築者 ネットワーク設計構築をする人に役立つメンバーシップです。 独自ブログ(https://shadowgarden.org/)にてネットワークエンジニア向け情報を発信しており、その活動を応援...

【アフィリエイト】おすすめ WordPress テーマ【SWELL

当サイトでは WordPress テーマとして SWELL を使用しています。以前は無料・高機能テーマとして知られる Cocoon を使用していて Cocoon も使いやすかったのですが、SWELL を使い始めてからは SWELL のほうが圧倒的に使いやすいなと思いました。そして何より読み込み速度が速い。SWELL を使い始めてから、過去の Cocoon のブログを見直したときに「あれ、こんなに表示遅かったっけ?」という感覚になりました。

また SWELL はデフォルトでもオシャレなデザインですが柔軟にカスタマイズすることもでき個性のあるサイトを作成できます。さらにブログパーツや広告タグといった再利用可能なブログの「部品」も作成することができ、ブログ作成効率も高いです。

技術ブログやアフィリエイト等での収益化を見据えたブログの作成に SWELL は最適です。初見では価格が高いなと思うと思いますが、私としては SWELL を採用して良かったしそれ以上の価値があると感じています。
ブログの新設やテーマ変更を考えている人は一度 SWELL を検討してみてください。
以下の画像リンクから詳細な情報を確認できます。

レンタルサーバーを探している人には安定性に定評のあるエックスサーバーをお勧めします。
当サイトもエックスサーバーを使用しています。WordPress のインストールも簡単にできます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次