てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] グループ変数を活用したネットワーク機器への Syslog サーバー追加



この記事は、Software Design 2018年12月号 の 特集1「[超速]入門 Ansible」内の「第3章:Ansibleでネットワーク作業も自動化」(以下、基本編)の続きです。

ソフトウェアデザイン 2018年12月号

ソフトウェアデザイン 2018年12月号

  • 作者: 中島倫明,横地晃,齊藤秀喜,楠正憲,三廻部大,鷲北賢,くつなりょうすけ,安藤幸央,結城浩,武内覚,宮原徹,平林純,職業「戸倉彩」,速水祐,樽石将人,清水琢也,山田泰宏,田代勝也,eban,中村壮一,上田隆一,谷口岳,mattn,すずきひろのぶ,小飼弾,青田直大,やまねひでき,あわしろいくや,中島雅弘,法林浩之,関治之,後藤大地,杉山貴章,Software Design編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/11/16
  • メディア: 雑誌
  • この商品を含むブログを見る

誌面スペースの関係で掲載できなかった、少し応用的な内容をブログとして投稿します。サンプル Playbook などの一式は、以下のリポジトリの extra ブランチにアップしてあります。

https://github.com/akira6592/sd2018-ansible-nw/tree/extra

また、 エーピーコミュニケーションズ Advent Calendar 2018 の1日目の記事も兼ねています。



応用編: グループと変数の活用

基本編では Playbook の中に直接コマンドを指定し、各 L3 スイッチに対して同じコマンドを実行しました。応用編ではもう少し凝った設定変更の例を見ていきましょう。

基本編の想定環境に、東日本と西日本のそれぞれの機器用に Syslog サーバーが追加設置されたとします。

f:id:akira6592:20181105164151p:plain

そこで、各 L3 スイッチのログ送信先として、自身の所属するエリア用の Syslog サーバーの IP アドレスを設定(logging host コマンド)する例を見ていきましょう。

ファイルの構成は以下の通りです。

  • ファイル構成
.                        # 作業用ディレクトリ
|-- group_vars           # グループ変数ファイル格納ディレクトリ
|  |-- east.yml          # グループ「east」用変数定義ファイル(追加)
|  |-- ios.yml           # グループ「ios」用変数定義ファイル
|  └-- west.yml          # グループ「west」用変数定義ファイル(追加)
|-- 03_set_logging.yml   # ログ送信先Syslogサーバー設定用Playbook(追加)
└-- inventory.ini        # インベントリーファイル(変更)


■ インベントリーファイルの作成

基本編で利用したインベントリーファイルにもうひと工夫加えます。

前述の通り、東日本の機器用と西日本の機器用の Syslog サーバーが1台ずつ追加されたため、2つのサーバーのIPアドレスは異なります。東日本用と、西日本用に1つずつ Playbook を作成してもよいのですが、ここはインベントリーファイルの機能を活用してスマートに設計してみましょう。

具体的にはまず、各 L3 スイッチを拠点グループ「tokyo」と「osaka」にそれぞれ所属させます。さらに「tokyo」「osaka」グループをそれぞれエリアグループ「east」「west」に所属させます。

f:id:akira6592:20181105164432p:plain

後述する各エリアグループ用の変数定義ファイルを組み合わせることで、各 L3 スイッチでエリア用の変数を利用できます。これにより、ひとつの Playbook で各 L3 スイッチに対して異なる値を埋め込んだコマンドを実行できます。

[ios] 
TOKYO-L3SW01 ansible_host=10.10.10.254
OSAKA-L3SW01 ansible_host=10.20.20.254

[tokyo]            # 拠点グループ「tokyo」
TOKYO-L3SW01

[osaka]            # 拠点グループ「osaka」
OSAKA-L3SW01

[east:children]    # エリアグループ「east」の配下に拠点グループ「tokyo」をネスト 
tokyo

[west:children]    # エリアグループ「west」の配下に拠点グループ「osaka」をネスト 
osaka

今回は対象ノードが少ないため、グループにする意味をそれほど感じられないかもしれませんが、グループにしておくことで拠点や対象ノードが増えても効率よく管理できます。

なお、グループの関係については ansible-inventory コマンドで視覚的に確認できます。

$ ansible-inventory -i inventory --graph
@all:
  |--@east:
  |  |--@tokyo:
  |  |  |--TOKYO-L3SW01
  |--@ios:
  |  |--OSAKA-L3SW01
  |  |--TOKYO-L3SW01
  |--@ungrouped:
  |--@west:
  |  |--@osaka:
  |  |  |--OSAKA-L3SW01


■ 変数定義ファイルの作成

基本編で作成した「ios.yml」に加えて、各エリア用の「east.yml」と「west.yml」を新たに作成します。これらのファイルには、各エリア用の Syslog サーバーのIPアドレレスを変数「syslog_server」で定義します。

syslog_server: 10.10.0.1
syslog_server: 10.20.0.1

ここまでの準備により変数「syslog_server」の値は、グループ「east」に所属する対象ノードへのタスク実行時には「10.10.0.1」に、「west」に所属する機器へのタスク実行時には「10.20.0.1」になります。

■ Playbook の作成

最後に、ログ送信先 Syslog サーバーのIPアドレスを設定する Playbook を作成します。

- hosts: ios                      # (a) ヘッダーセクション
  gather_facts: no
  
  tasks:
    - name: set syslog server     # (b) SyslogサーバーIPアドレス設定タスク
      ios_logging:
        dest: host
        name: "{{ syslog_server }}"
      notify:
        - save

  handlers:                       # (c) ハンドラーセクション
    - name: save
      ios_config:
        save_when: always

この Playbook について解説します。

(a) ヘッダーセクション

基本編で作成した2つの Playbook と同様に、グループ「ios」を対象とし、ファクト収集は無効にしていています。

(b) Syslog サーバー IP アドレス設定タスク

ios_logging モジュールを利用しています。ios_logging モジュールは、Cisco IOSのネットワーク機器に対して、ロギング関連の設定をするモジュールです。コマンドとしては logging host などにあたります。

dest オプションにはログの送信先タイプを指定します。 ここでは Syslog サーバーへ送信するため「host」を指定します。この場合、name オプションに Syslog サーバーのホスト名またはIPアドレスを指定します。

notify ディレクティブで、このタスクで設定変更が発生した場合に呼び出すハンドラー「save」を指定しています。

(c) ハンドラーセクション

ios_config モジュールsave_when オプションに「always」を指定しています。これにより、このタスク実行時に常に「runnging-config」を「startup-config」にコピーします。

なお、このタスクは前述の「(b) SyslogサーバーIPアドレス設定タスク」の notify 経由で実行されます。そのため、結果的には「(b) Syslog サーバー IP アドレス設定タスク」で設定変更が発生したら「runnging-config」を「startup-config」にコピーするという動作になります。


■ 実行と確認

それでは Playbook を実行します。利用するコマンドや書式は基本編で作成した Playbook の実行のときと同じです。

$ ansible-playbook -i inventory.ini 03_set_logging.yml

PLAY [ios] *****************************************************************

TASK [set syslog server] ***************************************************
changed: [OSAKA-L3SW01]
changed: [TOKYO-L3SW01]

RUNNING HANDLER [save] *****************************************************
changed: [OSAKA-L3SW01]
changed: [TOKYO-L3SW01]

PLAY RECAP *****************************************************************
OSAKA-L3SW01               : ok=2    changed=2    unreachable=0    failed=0
TOKYO-L3SW01               : ok=2    changed=2    unreachable=0    failed=0

各L3スイッチへのSyslogサーバーIPアドレス設定タスクのステータスが「changed」となり、設定変更されたことが分かります。それに伴い、ハンドラー経由でタスク「save」も呼び出されています。

念の為、ここでは各 L3 スイッチ側で設定が投入、保存されたことを確認します。

  • 東京拠点側
TOKYO-L3SW01# show running-config | inc logging
logging host 10.10.0.1
TOKYO-L3SW01# show startup-config | inc logging
logging host 10.10.0.1
  • 大阪拠点側
OSAKA-L3SW01# show running-config | inc logging
logging host 10.20.0.1
OSAKA-L3SW01# show startup-config | inc logging
logging host 10.20.0.1

これで、正常に2台の L3 スイッチに異なる Syslog サーバーのIPアドレスを指定した logging host コマンドが投入されたことを確認できました。

まとめ

このように、一部のパラメータのみが異なる作業を抽象化し、Playbook と 変数(パラメータ)を分けることでメンテナンス性と Playbook の再利用性が向上します。

Software Design 2018年12月号の Ansible 特集に寄稿しました(ウラ話など)

gihyo.jp

はじめに

Software Design 2018年12月号の Ansible 特集の中の「第3章:Ansibleでネットワーク作業も自動化」という章を寄稿させていただきました。個人的には貴重な経験だったので、経緯や気づきなどを書きたいと思います。

f:id:akira6592:20181116160011j:plain:w300


きっかけは継続したアウトプットから

もともとは、技術評論社さんとレッドハットさんの間で、企画がうまれました。

そこから、Ansible ユーザー会というコミュティで開催しているイベントへの参加や登壇、Ansible 関連のブログ投稿などをしていた私に「ネットワークの章を書いてみないか」とお声がけいただきました。

紙の媒体へのアウトプットは自信が無かったのですが、せっかくありがたく頂いた機会だったので、やってみようと思いました。


過去資料をベースにネタ検討

Ansible とネットワーク組み合わせの資料はいくつか作ってので、それらを参考にして内容を構成しようと考えました。

ベースとなるネタはあったとしても、どのような読者を想定するか、何ページ設けられるかなどの要素を考ええると、アウトラインを決めるまで検討することは少なくなかったです。

結果としては、シンプルな内容するため以下の内容に絞りました。

  • 概要
  • 情報取得サンプル(show コマンドの結果出力)
  • 設定変更サンプル(SNMPコミュニティ名の設定)

Playbook で指定するコマンドは、あえてすべてべた書きにしました。 テンプレートや変数を利用してもよかったのですが、なるべく簡単にしようと思って避けました。

自分の中で、記事の設計のようなものができるのは時間がかかってしまいましたが、そこからは意外と順調でした。(ただし、書きすぎ。後述)


文章の書き方に四苦八苦、ツールの力もお借りして

そもそも、文章を書くのが得意ではなく、このブログも文章を書く練習を兼ねて書いています。 そのため、正しい日本語書くための資料をいくつか読みました。とくに以下の点に気を付けました。

  • 文章は短く
    • 長くしない。適度に区切って、必要に応じて接続詞を挟む。
  • 主語と述語は合わせる
    • 主語と述語がねじれてしまわないようにする。
  • 「~することができる」は「~できる」にする
    • 不思議なクセでよく書いてしまうが、多くの場合は短くできる
  • 印刷してチェックする
    • ディスプレイでいくらチェックしても気づけないミスに気付ける

初期段階の原稿は、Visual Studio Codeテキスト校正くん という拡張を利用してチェックしながら書きました。自分の悪いクセを指摘してくれる先生のような存在で、非常に助かりました。

また、スライド資料であれば箇条書きと口頭で説明できる内容でも、いざ文章にしようとすると、文章の組み立て方に迷って苦戦しました。


後輩にレビューを依頼

原稿がある程度できたところで、後輩のネットワークエンジニアにレビューをお願いしました。分かりにくかった箇所などを指摘してもらい、修正しました。迷いながら書いた箇所が思いっきりバレました。


ブログとも専門書籍とも違う

やはり、ブログを書くのと違って、気軽に修正できないという点で、気を使う場面が多くありました。 原稿のボリュームのコントロールも難しかったです。当初、張り切って書いたら長すぎてしまいました。。どこをどう削るかは悩みました。紙媒体固有の難しさを感じました。

また、雑誌の中のひとつの特集ですから Ansible 専門書と違って、読者は Ansible 目的で読んでいるとは限りません。その中でちょっとでも興味を持ってもらうためには、淡々と紹介するのではなく、見出し、とくに導入部分に気を遣いました。


おわりに

中島さん(@irix_jp)、齊藤さん(@saito_hideki)というスーパーなエンジニアのみなさんと一緒に特集を作り上げることができて、とてもうれしかったです。

また、技術評論社Software Designご担当のみなさんにもお世話になりました。 gihyo.jp

編集さんもデザイナーさんもみなさんプロフェッショナルですね!

特集全体としては、入門、ネットワーク、GUIツールのAWX、CIの組み立て方などをカバーしてます。Ansible を始めたり、もっと知るきっかけになったら、とてもうれしいです。

今回は機会をいただきありがとうございました!




おまけ:リンク集

記事中に登場するリンクを以下に掲載します。

[Batfish] 重複したインターフェースのIPアドレスを検出する(Cisco IOS編)

ネットワーク機器のコンフィグ解析ツール Batfish には、重複したインターフェースのIPアドレスを検出する機能があります。 Batfish の Python ライブラリpybatfish でいう ipOwners() に、パラメータ duplicatesOnly=True を与えたときの動作です。

以下に、試した Junipter Notebook を貼り付けます。

Check_Duplicate_IP_Addresses

なお、あくまでもインターフェースのIPアドレスをチェックしますので、 それ以外、例えば ntp server 10.0.0.123 のような設定が複数のコンフィグにあっても重複にはなりません。

関連エントリ

tekunabe.hatenablog.jp

[Batfish] SRX(Junos)上の評価されないポリシーを検出する

はじめに

ネットワーク機器のコンフィグ解析ツール Batfish には、読み込んだコンフィグのルーターACLや、ファイアウォールのポリシーの中から、評価されないポリシーを検出する機能があります。 Batfish の Python ライブラリpybatfish でいう filterLineReachabilityです。

評価されないポリシーとは

ポリシーは、通常上から順番に評価され、条件にマッチした時点でそれ以降のポリシーは評価しません。そのため、例えば(極端な例ですが)1行目に IP を利用したすべての通信を許可するポリシーがある場合、2行目に HTTP を許可するポリシーが定義してあっても評価されません。

ポリシーの追加、変更が繰り返されるとポリシーが複雑化し、意図せずこのような評価されないポリシーができてしまうこともあるかもしれません。 ポリシーの数が多い場合、人間の判断による検出が難しいので、機械的に実現したいところです。

SRX (Junos)で試しました

試した Jupyter Notebook の .ipynb ファイルを以下の Gist にアップしましたので貼り付けます。

gist3bf4a03265db735977dbec7625169d96

なお、上記の例には含まれていませんが、ICMP の type や code までは判断していないようです。 具体的に試したのは、junos-icmp-all 許可と junos-icmp-ping 許可 の組み合わせです。

junos-icmp-ping 許可 → junos-icmp-all 許可というポリシーの順番であれば、後者の junos-icmp-all も評価されるはずです。ですが、batfish 上では、評価されないポリシーとして検出されました。

そのため、batfish 上では2つのポリシーとも type や code までは判断せず、単にICMP 許可という定義として扱われ、重複、後ろにあるポリシーは評価されないと判断された、と考えました。

Cisco IOSACL での例は公式 Notebook に

Cisco IOSACL での利用されないエントリを検出する例は、公式 Jupyter Notebook の Analyzing ACLs and firewall rules with Batfish 内の filterLineReachability: Analyzing reachability of filter lines にあります。

参考

tekunabe.hatenablog.jp

[Batfish] 単体の Docker イメージと pybatfish の環境構築方法

■ Batfish 公式の 2つの Docker イメージ

Batfish には公式 Docker イメージが2つあります。

  • イメージ1: batfish/batfish
    • batfish 本体の イメージ
  • イメージ2: batfish/allinone
    • batfish 本体と かんたんにお試しできる Jupyter Notebook とサンプルコンフィグ入りイメージ

以前の Batfish 概要をお伝えした記事では、簡単に試すの目的だったため、batfish/allinone を利用しましたが、イメージサイズが少々大きめです。 Batfish 本体だけで良ければ、イメージサイズが小さめの batfish/batfish のほうが適しています。

この記事では、以下の点についてまとめます。

  • Docker イメージ batfish/batfish を利用したコンテナの起動
  • ホスト側に pybatfish をインストールして、コンテナ内の batfish にアクセスする

概要図

f:id:akira6592:20181026185106p:plain


■ コンテナの起動

手順は docker/batfish.md at master · batfish/docker Batfish service docker container に記載されています。

mkdir -p data
docker run -v $(pwd)/data:/data -p 9997:9997 -p 9996:9996 batfish/batfish

コンテナから見た /data には、機器構成情報をまとめたスナップショットなどのデータが保存されます。 これらのデータを、ホスト側のデータとして永続的に保持するために、-v オプションでマウントを指定しています。 権限の都合上 --privileged が必要な場合もあります。


■ ホストへの pybatfish のインストール

主な手順は batfish/pybatfish: Python client for Batfish に記載されています。

# pybatfish リポジトリの clone
git clone https://github.com/batfish/pybatfish.git
cd pybatfish

# pybatfish のインストール
pip install .

現状は直接 pip install pybatfish でインストールできませんが、いずれできるようになるかもしれません。


■ 動作確認

手順は pybatfish のドキュメントの Getting started に記載されているコードを参考にします。

あらかじめ python インタープリタを起動しておきます。

各種 import

from pybatfish.client.commands import *
from pybatfish.question.question import load_questions, list_questions
from pybatfish.question import bfq

エスチョンのロード

load_questions()

スナップショットの初期化

bf_init_snapshot('jupyter_notebooks/networks/example') 

jupyter_notebooks/networks/example は、pybatfish リポジトリを clone した中に含まれる、サンプルのネットワーク機器のコンフィグなどが含まれています。 単なる動作確認目的のため、こちらを利用しています。

ログ

status: TRYINGTOASSIGN
.... no task information
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Parse configurations 0 / 13
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Parse configurations 0 / 13
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Parse configurations 0 / 13
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Parse configurations 0 / 13
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Parse configurations 2 / 13
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Parse configurations 8 / 13 Elapsed 00:00:05
status: ASSIGNED
.... Fri Oct 26 08:51:18 2018 UTC Reading, unpacking, and deserializing files containing 'org.batfish.datamodel.GenericConfigObject' instances 10 / 15
status: TERMINATEDNORMALLY
.... Fri Oct 26 08:51:18 2018 UTC Deserializing objects of type 'org.batfish.datamodel.Configuration' from files 15 / 15
Default snapshot is now set to ss_b10132b4-75db-4544-a2ba-8dc82f1706d2
'ss_b10132b4-75db-4544-a2ba-8dc82f1706d2'

IPアドレスの取得

ip_owners_ans = bfq.ipOwners().answer()

取得したIPアドレスの表示

ip_owners_ans.frame().head()

ログ

         Node      VRF           Interface          IP  Mask  Active
0    as2dist2  default           Loopback0     2.1.3.2    32    True
1    as2dist1  default           Loopback0     2.1.3.1    32    True
2    as2dept1  default  GigabitEthernet1/0  2.34.201.4    24    True
3    as2dept1  default           Loopback0     2.1.1.2    32    True
4  as3border2  default  GigabitEthernet1/0     3.0.2.1    24    True

as1border1 の GigabitEthernet0/0 の情報を取得、表示

iface_ans = bfq.interfaceProperties(nodes='as1border1', interfaces='GigabitEthernet0/0', properties='all-prefixes').answer()
iface_ans

ログ

                       Interface
0  as1border1:GigabitEthernet0/0


■ まとめ

Batfish 単体のコンテナの起動と pybatfish の環境構築方法をご紹介しました。 このあとは、Python でコードを書いたり、Junypter Notebook を準備するなどして、実現したいことを実装していくことになります。

https://www.batfish.org/

[Batfish] ネットワーク機器のコンフィグを読み込んでルーティングなどの様々な検証ができるツール「Batfish」の紹介

■ Batfish とは: 実機に接続することなくコンフィグを検証

f:id:akira6592:20181025150354p:plain

Batfish は、ネットワーク機器のコンフィグの様々な検証ができるツールです。 実機に接続する必要はありません。 準備したコンフィグファイルを読み込んでパースし、解析して内部でネットワーク機器が動作するようなイメージです。

本体は Java で書かれていて、Python から扱うためのクライアントである pybatfishもあります。 設定変更のコンフィグの妥当性を、あらかじめ Batfish で確認してから実機に投入する、というようなことが実現できるのではないかと、最近興味を持ちました。

この記事では、Batfish でできることなどの概要や、Docker、Jupyter Notebook を利用した試し方をご紹介します。

Cisco、Arista、Juniper、Palo Alto などの機器に対応

Batfish が対応している機器の一覧はこちらです。これらの機器の形式のコンフィグファイルを読み込むことができます。 https://github.com/batfish/batfish#what-configuration-formats-does-batfish-support

Cisco、Arista、Juniper、Palo Alto などの機器に対応しています。

情報ソース(デモ動画・プレゼン資料)

Batfish 公式サイトのトップにもリンク掲載されていますが、デモ動画やプレゼン資料などがあります。

チュートリアル動画

今後も Batfish の YouTube チャンネルで動画が増えるかもしれません。

プレゼン動画・資料

ブログ


■ Allinone の Docker イメージ でかんたんにお試しできる

Batfish には 2 つの公式 Docker イメージがあります。

イメージ1: batfish/batfish

batfish 本体の イメージです。 f:id:akira6592:20181026160249p:plain (数字はTCPポート番号)

イメージ2: batfish/allinone  ←今回はこちらを利用

batfish と かんたんにお試しできる Jupyter Notebook とサンプルコンフィグ入りイメージです f:id:akira6592:20181026230814p:plain

利用方法は、Dockerfile が管理されているリポジトリ batfish/dockerREADME.md に記載されています。 ここでは、batfish/allinone を利用して、簡単に動作を確認する方法をご紹介します。

もし、Docker コンテナを動かす環境が用意できない場合は、batfish/pybatfish リポジトリにある Jupyter Notebook の .ipynb ファイル で雰囲気がつかめます。 Play with Docker のような、ブラウザだけで Docker 環境を一定時間利用できるサービスを利用するという手段もあります。

コンテナの起動と Junipter Notebook へのログイン

docker run -p 8888:8888 batfish/allinone

コンテナ側で Jupyter Notebook が 8888/TCP ポートを空けているので、ホスト側からも 8888/TCP でアクセスできるようにポートマッピングしています。

コンテナが起動すると、以下のようなログが表示されます。

  • ログ
[root@centos7 ~]# docker run -p 8888:8888 batfish/allinone
[I 04:30:16.094 NotebookApp] Writing notebook server cookie secret to /data/.local/share/jupyter/runtime/notebook_cookie_secret
[I 04:30:16.779 NotebookApp] Serving notebooks from local directory: /notebooks
[I 04:30:16.779 NotebookApp] The Jupyter Notebook is running at:
[I 04:30:16.779 NotebookApp] http://(0320725b43c3 or 127.0.0.1):8888/?token=abcdef123456xxxx
[I 04:30:16.779 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 04:30:16.780 NotebookApp] No web browser found: could not locate runnable browser.
[C 04:30:16.780 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://(0320725b43c3 or 127.0.0.1):8888/?token=abcdef123456xxxx

上記のログの例では token=abcdef123456xxxx が Jupyter Notebook へログインするトークン情報です。この場合、以下のような URL で Jupyter Notebook へログインします。

http://localhost:8888/?token=abcdef123456xxxx

Notebook の選択

Jupyter Notebook にログインすると、以下の Notebook の一覧が表示されます。

f:id:akira6592:20181025150132p:plain

ここでは、一番初歩的そうな「Getting started with Batfish.ipynb」を選択して説明します。

なお、同じディレクトリにある networks ディレクトリの配下には、example-filtersexamples ディレクトリがあります。これらの 2つのディレクトリの中には、ネットワーク機器のコンフィグやホストの定義ファイルが含まれています。Batfish でこれらのディレクトリを指定すると、コンフィグなどを読み込んで、解析できる状態になります。

Getting started with Batfish

この Notebook は、大まかには以下の流れです。

  • networks/example ディレクトリに含まれる、ネットワーク機器(Cisco IOS)のコンフィグや、ホストの定義などを読み込み、スナップショットを作成する
  • 設定の抽出や、traceroute、ルーティングテーブルなどを検証する。

見出しだけ翻訳して、一部 "※" で注釈をつけた .ipynb ファイルを作成したので、以下に貼り付けます。

Getting started with Batfish (Japanese)

自身で準備したコンフィグで試すには

上記の例では SNAPSHOT_PATH = "networks/example"という指定で、 networks/example ディレクトリ配下のネットワーク機器のコンフィグやホスト定義ファイルを読み込んでいます。自身で準備したコンフィグなどを読み込ませたい場合は、以下のようなファイル、ディレクトリの配置にした上で、読み込むパスを変更します。

networks/mynet
|-- configs      # ネットワーク機器のコンフィグを格納
|   |-- router1.cfg 
|   `-- router2.cfg
|-- hosts         # ホスト定義ファイルを格納(batfish固有使仕様)(任意)
|   |-- host1.json
|   `-- host2.json
`-- iptables     # ホストに適用する iptables 定義ファイル(任意)
   |-- host1.iptables
   `-- host2.iptables

詳細は Packaging snapshots for analysis を参照してください。

また、コンテナ起動時に、別途用意したディレクトリをマウントするという方法もあります。 詳細は以下の記事を参照ください。

[Batfish] allinone イメージの Jupyter Notebook から自前のコンフィグディレクトリを利用可能にする方法 - てくなべ (tekunabe)


■ まとめ

ネットワーク機器のコンフィグを読み込んでルーティングなどの様々な検証ができるツール「Batfish」で、どんな事ができるかなど、雰囲気が伝わりましたでしょうか。 完全に実機と同じものとみなして検証することは難しいですが、補助的な検証には利用できるのではないでしょうか。 また、実機に接続する必要がなく、コンフィグだけ用意すればよい点も魅力的です。

私自身はまだ調べ始めたばかりです。また何か新しいことが分かったり試したりしたら、このブログに投稿したいしと思います。

参考

Ansible と Batfish を組み合わせた話の Webinar があるようです。

[2018/11/12 追記] 動画と資料がアップされました。

www.ansible.com

https://www.ansible.com/hubfs/2018_Content/Ansible-Intentionet-Webinar-Slides.pdf

【Ansible】ios_config モジュールでべき等性を考慮せずにコンフィグを投入する方法(match: none)

■ match オプション を none にするとべき等性を考慮しない

Ansible には、Cisco IOS 機器にコンフィグ投入などができる ios_config というモジュールがあります。 このモジュールはデフォルトで、べき等性を保とうとする仕様になっています。 大まかな流れとしては以下の通りです。

  1. 事前に現状のコンフィグを取得
  2. オプションで指定されたコンフィグとの差分を確認
  3. 差分コンフィグのみを投入

なんらかの事情で、べき等性を考慮せずに無条件でコンフィグを投入したい場合は match オプションに none を指定します。

  • ios_config モジュールの match オプションの none の説明

    if match is set to none, the module will not attempt to compare the source configuration with the running configuration on the remote device.


■ 検証

簡単な例で検証した結果を記載します。

環境: Ansbile 2.7.0

match: no を指定しない場合(デフォルト)

Playbook
- hosts: iosal
  gather_facts: no

  tasks:
    - name: set ntp
      ios_config:
        lines:
          - ntp server 10.0.0.123
初回実行 (changed=1)
TASK [set ntp] *************************************************************
changed: [iosal1]

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

今までなかっコンフィグを指定したため、実際に投入され、changed になりました。

再実行 (changed=0: べき等性を考慮した結果)

同じ Playbook を使用してもう一度実行します。

TASK [set ntp] *************************************************************
ok: [iosal1]

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

タスクは changed にならず、べき等性を考慮した結果となりました。

match: none を指定する場合

先の検証で投入したコンフィグはいったん削除し、match: none を指定した Playbook で検証します。

Playbook
- hosts: iosal
  gather_facts: no

  tasks:
    - name: set ntp
      ios_config:
        lines:
          - ntp server 10.0.0.123
        match: none          # 追加
初回実行 (changed=1)
TASK [set ntp] *************************************************************
changed: [iosal1]

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

今までなかっコンフィグを指定したため、実際に投入され、changed になりました。

再実行 (changed=1: べき等性を考慮しなかった結果)

同じ Playbook を使用してもう一度実行します。

TASK [set ntp] *************************************************************
changed: [iosal1]

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

また changed になり、べき等性を考慮しなかった結果となりました。