ARISTA vEOS に jq を入れて使う (小ネタ)
小ネタです。twitter で「Arista に jq 欲しい」って話を見かけたので「確かに vEOS デフォルトで入ってなくて、入れりゃー使えるけど(この記事)...最初から入っていて欲しいよなあ」というだけのお話。
環境
いつも通り(3年ぶり)の vEOS ですぞな。
localhost#show version Arista vEOS Hardware version: Serial number: System MAC address: 0021.96aa.9b52 Software image version: 4.20.1F Architecture: i386 Internal build version: 4.20.1F-6820520.4201F Internal build ID: 790a11e8-5aaf-4be7-a11a-e61795d05b91 Uptime: 2 minutes Total memory: 2017260 kB Free memory: 1259404 kB [admin@localhost ~]$ uname -a Linux localhost 3.18.28.Ar-6765725.4201F #1 SMP PREEMPT Wed Nov 15 09:47:13 PST 2017 x86_64 x86_64 x86_64 GNU/Linux
インストール
前述の環境では一応 /etc/yum
配下が揃っていそうなのですが、ササッと binary ファイル取ってきて PATH 通ったところに放り込む感じで。
まず curl でインターネッツからとってこれるように DNS キャッシュサーバと Ma1
の IP アドレスくらいを EOS で設定して。
ip name-server vrf default <DNSキャッシュサーバの IP address> ! interface Management1 ip address <EOS の IPv4 アドレス(DHCPでも)> ! ip route 0.0.0.0/0 <インターネッツに抜ける Gateway IP address>
bash
におりて binary ファイルを取ってくるだけ。
localhost#bash Arista Networks EOS shell [admin@localhost ~]$ [admin@localhost tmp]$ cd /var/tmp [admin@localhost tmp]$ curl -LO https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 [admin@localhost tmp]$ ll total 2964 drwxrwxrwt 4 root root 100 Nov 29 13:30 agents drwxrwxrwx 2 root root 40 Nov 29 13:19 cli -rw-r--r-- 1 admin eosadmin 3027945 Nov 29 13:40 jq-linux64 -rw-rw-rw- 1 root root 2 Nov 29 13:20 startup-config.loaded [admin@localhost tmp]$ sudo cp jq-linux64 /bin/jq [admin@localhost tmp]$ sudo chmod 755 /bin/jq [admin@localhost ~]$ which jq /bin/jq
EOS から使う
後はお好きなように。EOS シェル側に戻れば、ほいこの通り。
localhost#show int | json | jq '.interfaces[] | [.name, .lineProtocolStatus]' [ "Management1", "up" ] [ "Ethernet2", "up" ] [ "Ethernet3", "up" ] [ "Ethernet1", "up" ]
最後に
僕も EOS にデフォルトで入れておいて欲しいです。 (EOS ならばお手軽に eAPI を突いてスクリプト言語の json ライブラリで処理する、のが常道なのかも知れないけど...shell だけでチョチョイとやりたいことも多々あるよね)
Nexus9000v の API を弄る(NX-API REST, NX-API CLI)
最初に
やること
Cisco 公式 / Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x のツリーを眺めると、NX-OS には色々な API が揃っていそうです。なので、様子を見ていきます。
ドキュメントレベルでは、少なくとも以下が揃っていそうで、今回はその一部を取り上げます。
なお、まずは機器側としての様子を見たかったため、ツールに関してはほぼ触れず。(まずは機器側の限界を知っておきたい)
- NX-API
- NETCONF
- ドキュメントを流し読みした感じ、割とちゃんと作られていそう
- OnBox Python
参考資料
試用する
環境情報と準備
NX-OS 側
torsw101a# show version | egrep -i nxos NXOS: version 7.0(3)I6(1) NXOS image file is: bootflash:///nxos.7.0.3.I6.1.bin NXOS compile time: 5/16/2017 22:00:00 [05/17/2017 15:21:28]
以下のように機能を有効化するだけ
torsw101a(config)# feature scp-server torsw101a(config)# feature nxapi torsw101a# show nxapi nxapi enabled HTTP Listen on port 80 HTTPS Listen on port 443
APIクライアント側準備
kotetsu@receiver:~/nxos_rest$ uname -a Linux receiver 4.4.0-97-generic #120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux kotetsu@receiver:~/nxos_rest$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
$ sudo apt install -y python3-pip $ pip3 install requests
...(無言)
NX-API REST 試用
参照
以下のような VLAN 設定の NX-OS に対して
torsw101a# show run vlan !Command: show running-config vlan !Time: Sun Oct 29 11:19:38 2017 version 7.0(3)I6(1) vlan 1,100,300,3901 vlan 100 vn-segment 10100 vlan 300 vn-segment 10300 vlan 3901 vn-segment 50001
こんな感じのサンプルスクリプトを作って実行すれば
(なお前半の認証部分は Cisco APIC REST API User Guide / Testing the API with Python のサンプルコードをマルパク)
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json base_url = 'http://10.0.0.230/api/' # create credentials structure name_pwd = {'aaaUser': {'attributes': {'name': 'admin', 'pwd': 'P@ssw0rd'}}} json_credentials = json.dumps(name_pwd) # log in to API login_url = base_url + 'aaaLogin.json' post_response = requests.post(login_url, data=json_credentials) # get token from login response structure auth = json.loads(post_response.text) login_attributes = auth['imdata'][0]['aaaLogin']['attributes'] auth_token = login_attributes['token'] # create cookie array from token cookies = {} cookies['APIC-Cookie'] = auth_token bd_url = base_url + 'node/mo/sys/bd.json?rsp-subtree=children' get_response = requests.get(bd_url, cookies=cookies, verify=False) print(json.dumps(get_response.json(), indent=2))
以下のような出力を得られる
{ "totalCount": "1", "imdata": [ { "bdEntity": { "attributes": { "childAction": "", "modTs": "2017-08-17T02:27:52.937+00:00", "persistentOnReload": "true", "sysDefaultSVIAutostate": "enable", "descr": "", "dn": "sys/bd", "monPolDn": "uni/fabric/monfab-default", "status": "" }, "children": [ { "l2BD": { "attributes": { "modTs": "2017-09-09T23:58:01.301+00:00", "vlanmgrCfgState": "0", "status": "", "fwdMode": "bridge,route", "uid": "0", "epOperSt": "", "pcTag": "1", "type": "bd-regular", "monPolDn": "", "controllerId": "", "childAction": "", "BdOperName": "VLAN0300", "fwdCtrl": "mdst-flood", "id": "300", "mode": "CE", "rn": "bd-[vlan-300]", "media": "enet", "bdDefDn": "", "adminSt": "active", "vlanmgrCfgFailedBmp": "", "hwId": "0", "bridgeMode": "mac", "accEncap": "vxlan-10300", "createTs": "1970-01-01T09:00:00.000+00:00", "vlanmgrCfgFailedTs": "00:00:00:00.000", "name": "", "unkMacUcastAct": "proxy", "unkMcastAct": "flood", "fabEncap": "vlan-300", "ctrl": "", "persistentOnReload": "true", "BdState": "active", "operSt": "up" } } }, { "l2BD": { "attributes": { "modTs": "2017-09-09T23:57:01.911+00:00", "vlanmgrCfgState": "0", "status": "", "fwdMode": "bridge,route", "uid": "0", "epOperSt": "", "pcTag": "1", "type": "bd-regular", "monPolDn": "", "controllerId": "", "childAction": "", "BdOperName": "VLAN0100", "fwdCtrl": "mdst-flood", "id": "100", "mode": "CE", "rn": "bd-[vlan-100]", "media": "enet", "bdDefDn": "", "adminSt": "active", "vlanmgrCfgFailedBmp": "", "hwId": "0", "bridgeMode": "mac", "accEncap": "vxlan-10100", "createTs": "1970-01-01T09:00:00.000+00:00", "vlanmgrCfgFailedTs": "00:00:00:00.000", "name": "", "unkMacUcastAct": "proxy", "unkMcastAct": "flood", "fabEncap": "vlan-100", "ctrl": "", "persistentOnReload": "true", "BdState": "active", "operSt": "up" } } }, { "l2BD": { "attributes": { "modTs": "2017-09-10T13:32:39.908+00:00", "vlanmgrCfgState": "0", "status": "", "fwdMode": "bridge,route", "uid": "0", "epOperSt": "", "pcTag": "1", "type": "bd-regular", "monPolDn": "", "controllerId": "", "childAction": "", "BdOperName": "VLAN3901", "fwdCtrl": "mdst-flood", "id": "3901", "mode": "CE", "rn": "bd-[vlan-3901]", "media": "enet", "bdDefDn": "", "adminSt": "active", "vlanmgrCfgFailedBmp": "", "hwId": "0", "bridgeMode": "mac", "accEncap": "vxlan-50001", "createTs": "1970-01-01T09:00:00.000+00:00", "vlanmgrCfgFailedTs": "00:00:00:00.000", "name": "", "unkMacUcastAct": "proxy", "unkMcastAct": "flood", "fabEncap": "vlan-3901", "ctrl": "", "persistentOnReload": "true", "BdState": "active", "operSt": "0" } } } ] } } ] }
設定
同様にこんな感じのサンプルスクリプトで
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json base_url = 'http://10.0.0.230/api/' # create credentials structure name_pwd = {'aaaUser': {'attributes': {'name': 'admin', 'pwd': 'P@ssw0rd'}}} json_credentials = json.dumps(name_pwd) # log in to API login_url = base_url + 'aaaLogin.json' post_response = requests.post(login_url, data=json_credentials) # get token from login response structure auth = json.loads(post_response.text) login_attributes = auth['imdata'][0]['aaaLogin']['attributes'] auth_token = login_attributes['token'] # create cookie array from token cookies = {} cookies['APIC-Cookie'] = auth_token bd_url = base_url + 'node/mo/sys/bd.json' post_payload = { "bdEntity": { "children": [ { "l2BD": { "attributes": { "accEncap": "vxlan-10190", "fabEncap": "vlan-190", "pcTag": "1" }}}]}} post_response = requests.post(bd_url, data=json.dumps(post_payload), cookies=cookies, verify=False) print(json.dumps(post_response.json(), indent=2))
{ "imdata": [] }
設定が追加されている。しかし startup-config
に反映されているわけではないので、要注意。
torsw101a# show run vlan !Command: show running-config vlan !Time: Sun Oct 29 11:27:28 2017 version 7.0(3)I6(1) vlan 1,100,190,300,3901 vlan 100 vn-segment 10100 vlan 190 vn-segment 10190 vlan 300 vn-segment 10300 vlan 3901 vn-segment 50001
さっきの情報取得をもう一回やると、設定したものが増えているのが分かります。
また URL 末尾に options として query-target-filter
で条件指定も出来ます。この辺はまあ netconf で xml 扱うのと同じようなノリで。
>>> bd_url = base_url + 'node/mo/sys/bd.json?query-target==children&query-target-filter=eq(l2BD.id,"190")' >>> >>> get_response = requests.get(bd_url, cookies=cookies, verify=False) >>> print(json.dumps(get_response.json(), indent=2))
{ "imdata": [ { "l2BD": { "attributes": { "BdOperName": "VLAN0190", "monPolDn": "", "hwId": "0", "status": "", "createTs": "1970-01-01T09:00:00.000+00:00", "unkMacUcastAct": "proxy", "accEncap": "vxlan-10190", "adminSt": "active", "pcTag": "1", "uid": "62982", "epOperSt": "", "controllerId": "", "vlanmgrCfgState": "0", "fwdMode": "bridge,route", "vlanmgrCfgFailedBmp": "", "fwdCtrl": "mdst-flood", "type": "bd-regular", "dn": "sys/bd/bd-[vlan-190]", "BdState": "active", "bridgeMode": "mac", "bdDefDn": "", "name": "", "id": "190", "persistentOnReload": "true", "childAction": "", "mode": "CE", "modTs": "2017-10-29T11:27:05.932+00:00", "ctrl": "", "operSt": "down", "fabEncap": "vlan-190", "unkMcastAct": "flood", "media": "enet", "vlanmgrCfgFailedTs": "00:00:00:00.000" } } } ], "totalCount": "1" }
NX-API CLI
参照
JSON-RPC message format
JSON RPC
には cli
と cli_ascii
というコマンドタイプがあります。
レスポンスを JSON フォーマットで得られないような (bash コマンドとか)やつは、cli_ascii
の方を使わないとエラーになります。
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json payload = [ { "jsonrpc": "2.0", "method": "cli", "params": { "cmd": "show nve vni 50001 detail", "version": 1 }, "id": 1 } ] response = requests.post('http://10.0.0.230/ins', data=json.dumps(payload), headers={'content-type': 'application/json-rpc'}, auth=('admin', 'P@ssw0rd'), verify=False) print(json.dumps(response.json(), indent=2))
{ "id": 1, "jsonrpc": "2.0", "result": { "body": { "TABLE_nve_vni": { "ROW_nve_vni": { "svi-state": "UP [vrf-id: 3]", "vlan-bd": "3901", "if-name": "nve1", "prvsn-state": "add-complete", "mcast": "n/a", "vni-state": "Up", "cp-submode": "bgp", "flags": "", "type": "L3 [VRF001]", "mode": "control-plane", "vni": "50001" } } } } }
こんな感じで bash コマンドも打てます。
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json payload = [ { "jsonrpc": "2.0", "method": "cli_ascii", "params": { "cmd": "run bash df -h", "version": 1 }, "id": 1 } ] response = requests.post('http://10.0.0.230/ins', data=json.dumps(payload), headers={'content-type': 'application/json-rpc'}, auth=('admin', 'P@ssw0rd'), verify=False) print(json.dumps(response.json(), indent=2))
{ "result": { "msg": "Filesystem Size Used Avail Use% Mounted on\n/dev/root 8.9G 761M 8.1G 9% /\nnone 10M 1.4M 8.7M 14% /nxos/tmp\nnone 10M 2.9M 7.2M 29% /nxos/xlog\nnone 80M 9.9M 71M 13% /nxos/dme_logs\nnone 50M 3.0M 48M 6% /var/volatile/log\nnone 2.0M 12K 2.0M 1% /var/home\nnone 120M 364K 120M 1% /var/volatile/tmp\nnone 900M 256K 900M 1% /var/sysmgr\nnone 500M 60K 500M 1% /var/sysmgr/ftp\nnone 20M 0 20M 0% /var/sysmgr/srv_logs\nnone 2.0M 0 2.0M 0% /var/sysmgr/ftp/debug_logs\nnone 1.0G 349M 676M 35% /dev/shm\nnone 600M 61M 540M 11% /volatile\nnone 2.0M 16K 2.0M 1% /debug\nnone 1.0G 736K 1.0G 1% /mnt/ifc/cfg/db\n/dev/loop1 57M 57M 0 100% /isan_lib_ro\n/dev/loop2 65M 65M 0 100% /isan_bin_ro\n/dev/loop3 28M 28M 0 100% /isan_bin_eth_ro\n/dev/loop4 14M 14M 0 100% /isan_lib_eth_ro\n/dev/loop5 768K 768K 0 100% /isan_lib_n9k_ro\n/dev/loop6 128K 128K 0 100% /isan_bin_n9k_ro\nunionfs 8.9G 761M 8.1G 9% /isan/bin\nunionfs 8.9G 761M 8.1G 9% /isan/lib\n/dev/sda4 3.3G 1.1G 2.3G 33% /bootflash\n/dev/sda5 643M 18M 592M 3% /mnt/cfg/0\n/dev/sda6 643M 18M 592M 3% /mnt/cfg/1\n/dev/sda2 317M 12M 289M 4% /mnt/plog\nnone 400M 6.1M 394M 2% /var/sysmgr/startup-cfg\n/dev/loop7 49M 49M 0 100% /lc_ro\n/dev/loop8 41M 41M 0 100% /lc_n9k_ro\nunionfs 8.9G 761M 8.1G 9% /lc\n/dev/sda3 643M 19M 592M 4% /mnt/pss\n/dev/sda7 2.4G 80M 2.2G 4% /logflash\n/dev/loop9 57M 1.2M 53M 3% /bootflash/.rpmstore/patching\n" }, "id": 1, "jsonrpc": "2.0" }
bash ではデフォルト VRF での動作になるが Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x / Guest Shell 2.3 にあるように chvrf management
とかをいれて別 VRF から IP 通信系のコマンドも実行できます。
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json payload = [ { "jsonrpc": "2.0", "method": "cli_ascii", "params": { "cmd": "run guestshell chvrf management ping 10.0.0.231 -c 3", "version": 1 }, "id": 1 } ] response = requests.post('http://10.0.0.230/ins', data=json.dumps(payload), headers={'content-type': 'application/json-rpc'}, auth=('admin', 'P@ssw0rd'), verify=False) print(json.dumps(response.json(), indent=2))
{ "result": { "msg": "PING 10.0.0.231 (10.0.0.231) 56(84) bytes of data.\n64 bytes from 10.0.0.231: icmp_seq=1 ttl=255 time=0.663 ms\n64 bytes from 10.0.0.231: icmp_seq=2 ttl=255 time=0.733 ms\n64 bytes from 10.0.0.231: icmp_seq=3 ttl=255 time=0.568 ms\n\n--- 10.0.0.231 ping statistics ---\n3 packets transmitted, 3 received, 0% packet loss, time 2001ms\nrtt min/avg/max/mdev = 0.568/0.654/0.733/0.073 ms\n" }, "jsonrpc": "2.0", "id": 1 }
JSON message format
JSON
には以下のような type
があります(名前で察せられる通り)
cli_show
cli_show_ascii
cli_conf
bash
JSON
の場合は payload の JSON key 順序によっては Wrong request message version, expecting 1.0 Request.is.rejected
と Status Code 400 を返してくる...。
仕方がないので Python の dict 型は避けて、単純に文字列で渡す。
(正直、この辺で「JSON-XML に出来なくて JSON で出来ること、がなければ...もうこいつとは付き合わなくていいかなー」と思い始めた)
こんな感じで、JSON-XML
の時と同じ出力を得られます。
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json payload = """{ "ins_api": { "version": "1.0", "type": "cli_show", "chunk": "0", "sid": "1", "input": "show version", "output_format": "json" } }""" response = requests.post('http://10.0.0.230/ins', data=payload, headers={'content-type':'application/json'}, auth=('admin', 'P@ssw0rd')) print(json.dumps(response.json(), indent=2))
#! /usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json payload = """{ "ins_api": { "version": "1.0", "type": "bash", "chunk": "0", "sid": "1", "input": "df -h", "output_format": "json" } }""" response = requests.post('http://10.0.0.230/ins', data=payload, headers={'content-type':'application/json'}, auth=('admin', 'P@ssw0rd')) print(json.dumps(response.json(), indent=2))
binding library を探せ
NX-API REST
見つかりませんでした(完)。
NX-API CLI
以下 2017/10/30
現在の様子ですが。
- github / datacenter/nexus9000
- github / jedelman8/pycsco
- 以前は
napalm
でも下回りで使われていたっぽい (napalm
側のドキュメントを見た感じ) 2017/10/30
現在、最後の commit は2016/09/20
とか...数件溜まっている Issue や PR も進捗ない
- 以前は
- github / networktocode/pynxos
naparm
の下回りとして使われている- これ単体ではドキュメントなどもなさげ
- Ansible 公式 / Network Modules / Nxos
- 今のところこれが一番機能は揃っていそう
ちなみに napalm
で NX-OS を数分弄った感触は以下の通りです。
2年半ぶりにNAPALMを数分弄って(対象は Nexus9000v)、なんか標準 getter 少ないし下回りのライブラリを自分で呼ぶか、RestClient 使って機器の REST API 直接叩いた方が何ぼかマシでは...という感触を得た
— こてつ (@kakkotetsu) 2017年10月25日
単体の Network OS を相手にしたら、そりゃそういう感触になるのは当然か
— こてつ (@kakkotetsu) 2017年10月25日
getter が足りていないなら...って、こーゆーのはもうえーっちゅーねん pic.twitter.com/TdOBJAfxXt
— こてつ (@kakkotetsu) 2017年10月25日
おしまい
感想を好きに述べます。
- NX-API REST
- DN が最新バージョンで変わっていたりして、まだまだ開発中ではありそう
- それゆえにかライブラリはまだ無さげ (欲しい)
- データモデル的は Telemetry と共通の DME で、そのドキュメントは「よー分からんところもあるから試行錯誤」が必要なところもあった
- 参照・設定に関しては良くて、その他のオペレーション(ファイル操作・再起動 etc)に関しては不足している感
-
- とりあえずこれを使えば何でも出来そう
- 「この処理は API で出来ないから expect で...」というケースは避けられる
- CLI で NW 装置を扱っているネットワーク屋にも扱いやすい気がする
- ARISTA eAPI と使用感がほぼ同じなので...感想も一緒
NX-OS の NX-API CLI と EOS の eAPI を見ていると、君たち仲良くして一緒に標準化すれば?と言いたくなる
— こてつ (@kakkotetsu) 2017年9月13日
- とりあえずこれを使えば何でも出来そう
ライブラリ
- Junos でいうところの
PyEZ
みたいに特定 NOS に特化した良い感じに機能が揃ったやつはなさげ - 例えば ARISTA EOS の
pyeapi
なんかは、(インストール手順を見ると)リモート制御用サーバと EOS 側とどちらで動かせるようになっているので- 現状 On-box library として NX-OS 側に入っているライブラリを、リモート制御用サーバに入れて使うような展開もありうるかも??
- パブリックな情報を眺めていると、公式的には ACI 方面の開発優先に見える
- でもまあ HTTP Client としての最低限処理だけなら、ライブラリがなくとも...
- Junos でいうところの
まあ色々と言いましたが、選択肢が多くて驚きですね。
最後に、もう ncclient
とかでシコシコと NETCONF を弄る気にはならなかったんで、そこもライブラリ欲しいな...。
Nexus9000v で VxLAN+EVPN (MAC Mobility Extended Community 簡易動作確認編)
最初に
やること
先日の記事(Nexus9000v で VxLAN+EVPN (anycast gateway 編)) で、EVPN で学習した MAC アドレステーブルを見た僕が「Seq No があるってことは MAC Mobility Extended Community が使えるんじゃないのか!?」と口走っていたので、その簡易動作確認をします。
EVPN MAC Mobility ?
RFC 7432 (BGP MPLS-Based Ethernet VPN) / 15. MAC Mobility に書かれています。
EVPN PE を跨ぐような LiveMigration や Flapping が発生した際に、網内の PE 達が当該 MAC アドレスの最新の居場所(どの PE 配下にあるか)を正しく把握するために Sequence No を埋め込んで使う Extended Community ... それが MAC Mobility Extended Community です。 今回は確認できませんでしたが、RFCによれば同じ Sequence No が複数 PE から来た場合には PE の IP アドレスが小さい方を選択...てなルールもあるようです。
なーんて、僕の拙い日本語よりも、"EVPN MAC Mobility" で Google 画像検索でもすれば、Juniper さんあたりの分かりやすい図面が出てきますよ(雑)。
環境情報 / 事前準備
先日の記事(Nexus9000v で VxLAN+EVPN (anycast gateway 編)) のまま、完全シングルホーム環境。
なお、後述のシナリオのために torsw101a
と torsw201a
の Et 1/3
に以下設定をした上で、
torsw101a# show run int et 1/3 !Command: show running-config interface Ethernet1/3 !Time: Sun Oct 22 17:31:42 2017 version 7.0(3)I6(1) interface Ethernet1/3 description DEV=ostinato IF=Port0 switchport access vlan 100
torsw201a# show run int et 1/3 !Command: show running-config interface Ethernet1/3 !Time: Sun Oct 22 17:31:49 2017 version 7.0(3)I6(1) interface Ethernet1/3 description DEV=ostinato IF=Port1 switchport access vlan 100
トラフィックジェネレータとして Ostinato を接続してあります。
一応軽く GNS3 で手っ取り早く準備できるトラフィックジェネレータである Ostinato の参考資料も以下に載せておきます。
- OSTINATO
- OSTINATO 公式 / HOME
- OSTINATO 公式 / Download / vDrone Appliance
- GNS3 用のアプライアンス
Community member Bernhard has created a custom vDrone appliance for use with GNS3 based on TinyCore Linux - see Ostinato for GNS3 for download and detailed usage instructions.
- GNS3 用のアプライアンス
- Bernhard's Homepage / Ostinato for GNS3
- 前述の通りなので、ありがたく使わせて頂こう
- OSTINATO 公式 / Python API Guide
- GNS3
簡易動作確認
シナリオ
こんな風に様子を見ます。
- EVPN PE である
torsw101a
とtorsw201a
それぞれのEt 1/3
(VNI 10100 にマッピングされる VLAN を割当済)に、同一 Src MAC address(11:11:11:11:11:11
) の ARP トラフィックを流し続ける - 以下を見る
torsw101a
とtorsw201a
間に流れるパケット(主にEVPN 周りの UPDATE)torsw101a
とtorsw201a
での EVPN MAC アドレス学習情報 遷移
結果
MAC Mobility Extended Community シーケンス
拾ったパケットを追っていくと、以下の感じ (thanks WebSequenceDiagrams)
今回 PE x2 のみで Ostinato でチンタラトラフィックを流している環境では、Sequence No 2 以上が使われることはなかったです。
各 loop の最後に MAC Mobility Extended Community なしの(= Sequence No 0 扱い) UPDATE が出るのは RFC で以下の記載があるからかも知れません。
In order to process mobility events correctly, an implementation MUST handle scenarios in which sequence number wraparound occurs.
上記の loop を 4 回繰り返した後、30s 程度の間は一切の UPDATE を双方が出さなくなりました。
これはどうやら「180s の間に 5 回 move が発生したら 30s の hold timer を発動する(カスタマイズ可能)」というデフォルト値動作によるものみたいです。(以下の本いわく)
Building Data Centers with VXLAN BGP EVPN: A Cisco NX-OS Perspective (Networking Technology)
- 作者: David Jansen,Lukas Krattiger,Shyam Kapadia
- 出版社/メーカー: Cisco Press
- 発売日: 2017/04/04
- メディア: Kindle版
- この商品を含むブログを見る
こんな syslog も出ていた
2017 Oct 22 11:40:17 torsw101a %USER-2-SYSTEM_MSG: Detected duplicate host 1111.1111.1111, topology 100, during Local update, with host located at remote VTEP 198.18.1.21, VNI 10100 - l2rib
次に MAC Mobility Extended Community で Sequence No = 1 で UPDATE 吐いているパケットをピックアップすると以下の感じ
RFC 7432 (BGP MPLS-Based Ethernet VPN) / 7.7. MAC Mobility Extended Community にある format を見ると、Sticky/static
を示す Flags
が 0 になっています。この Flags
の用途は RFC 7432 (BGP MPLS-Based Ethernet VPN) / 15.2. Sticky MAC Addresses の通り、MAC address の移動が起こりえない環境で 1 をたててアラートをあげるような使い方を想定している模様。
NX-OS の設定で変更できるのかは調査した限りでは分からずです。余談ですが、例えば Juniper の実装だと Juniper 公式 / EVPN MAC Pinning Overview のように、この Flags を有効化する設定で MAC アドレス遷移事故を防ぐようなことも出来る(当然、ライブマイグレーションを使わないなどの制約と引き換えに)ようです。
MAC アドレス学習状況
先のシーケンス図と比較しながら見ていきましょう。(余談ですがこれ、拾うタイミングが結構シビアでした。)
torsw101a (VTEP 用の lo IP アドレス = 198.18.1.11)
配下に当該 MAC address があると思っている torsw201a
だったが
torsw201a# show l2route evpn mac all Flags -(Rmac):Router MAC (Stt):Static (L):Local (R):Remote (V):vPC link (Dup):Duplicate (Spl):Split (Rcv):Recv (AD):Auto-Delete(D):Del Pending (S):Stale (C):Clear (Ps):Peer Sync (O):Re-Originated Topology Mac Address Prod Flags Seq No Next-Hops ----------- -------------- ------ ------------- ---------- ---------------- 100 1111.1111.1111 BGP Rcv 0 198.18.1.11
自分配下から同 MAC address を学習し、それを Sequence No = 1
として扱い
torsw201a# show l2route evpn mac all Flags -(Rmac):Router MAC (Stt):Static (L):Local (R):Remote (V):vPC link (Dup):Duplicate (Spl):Split (Rcv):Recv (AD):Auto-Delete(D):Del Pending (S):Stale (C):Clear (Ps):Peer Sync (O):Re-Originated Topology Mac Address Prod Flags Seq No Next-Hops ----------- -------------- ------ ------------- ---------- ---------------- 100 1111.1111.1111 Local L, 1 Eth1/3 100 1111.1111.1111 BGP D 0 198.18.1.11
多分 torsw101a
が WithDrawn を送ってくれたタイミングで、Next-Hops 198.18.1.11
の経路を削除しつつ、自分が持っている経路の Sequence No
を 0 にリセットして再度 UPDATE を送っている。
torsw201a# show l2route evpn mac all Flags -(Rmac):Router MAC (Stt):Static (L):Local (R):Remote (V):vPC link (Dup):Duplicate (Spl):Split (Rcv):Recv (AD):Auto-Delete(D):Del Pending (S):Stale (C):Clear (Ps):Peer Sync (O):Re-Originated Topology Mac Address Prod Flags Seq No Next-Hops ----------- -------------- ------ ------------- ---------- ---------------- 100 1111.1111.1111 Local L, 0 Eth1/3 torsw201a#
なお、タイミング次第では Dup
フラグを観測できたこともありました。
torsw101a# show l2route evpn mac all Flags -(Rmac):Router MAC (Stt):Static (L):Local (R):Remote (V):vPC link (Dup):Duplicate (Spl):Split (Rcv):Recv (AD):Auto-Delete(D):Del Pending (S):Stale (C):Clear (Ps):Peer Sync (O):Re-Originated Topology Mac Address Prod Flags Seq No Next-Hops ----------- -------------- ------ ------------- ---------- ---------------- 100 1111.1111.1111 Local L,Dup, 1 Eth1/3 100 1111.1111.1111 BGP Dup,Rcv 0 198.18.1.21
完
「Seq No があるってことは MAC Mobility Extended Community が使えるんじゃないのか!?」という自分自身の問いに対して「何となく動いていそうな雰囲気はあるぞ」と答えておきます。
それはそれとして、この Sequence No がリセットする間もなくブリバリカウントアップしていくような環境を今回は作れずでしたが、まぁそんな恐ろしい環境には関わりたくないお気持ちでございます。
Nexus9000v で Telemetry
最初に
やること/サマリ
- NX-OS の Telemetry 機能を軽く様子見
- 細かいカスタマイズをシコシコやっていると、まるで盆栽のように終わりがなかったので、ほんの触り
- 送信側は以下のように動かす
- 受信側は以下のように動かす
今回の完成図はこんなところまで
構成
前回の構成 と一緒
BGP + VxLAN + EVPN
あたりが動いている torSW101a
を送信側として使います。
なお、receiver 側は各スイッチの management ポートと通信可能なところに、適当なサーバを置いておきます。
参考資料
機器側からの送信に関してはマニュアルとデータ構造(詳細仕様までは分からないが...)が揃っています。
受信に関しては、インストールしてノンカスタマイズで綺麗に見えるようなメーカ謹製系のやつは見当たらなかったので、メーカが提供している Docker Hub 上のそれっぽいのを。
- 送信側 Cisco 公式マニュアル
- Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x / Chapter: Model-Driven Telemetry
- NX-OS 7 系の Telemetry マニュアル
- NX-OS 側で送信に関する記述がほとんど
- Cisco Nexus 3000 and 9000 Series Telemetry Sources
- Telemetry の
data management engine (DME) Native Model
Source として NX-OS で指定可能な path とか - とりあえず一覧がザーッと並んでいるだけで、詳細な仕様とかは分からない
- Telemetry の
- Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x / Chapter: Model-Driven Telemetry
- 受信側 Cisco が提供している Docker Hub のリポジトリ
- Docker Hub / dockercisco/telemetryreceiver
- gRPC receiver
- GPB データのデコードをして Elasticsearch に叩き込むところまでやってくれる
- NX-OS 側はこいつに GPB エンコード形式データを gRPC で送り付けるようにする
- Docker Hub / dockercisco/elklat
- Elasticsearch + Kibana
- Kibana には諸々の query 設定例などが入っていて、利用者はそれを参考・流用可能
- Docker Hub / dockercisco/telemetryreceiver
- その他
環境情報
受信側サーバ (前述の Cisco Docker image を動かす)
Docker インストールは Get Docker CE for Ubuntu あたりを参考に済ませているものとして。
$ uname -a Linux receiver 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS" $ docker --version Docker version 17.09.0-ce, build afdb6d4 $ docker-compose --version docker-compose version 1.16.1, build 6d1ac21
NX-OS
例によって 4GB
メモリで限界を狙う。
torsw101a# show version ... NX-OSv9K is a demo version of the Nexus Operating System Software BIOS: version NXOS: version 7.0(3)I6(1) BIOS compile time: NXOS image file is: bootflash:///nxos.7.0.3.I6.1.bin NXOS compile time: 5/16/2017 22:00:00 [05/17/2017 15:21:28] Hardware cisco NX-OSv Chassis with 4037916 kB of memory. Processor Board ID 90SNLUQJ25I Device name: torsw101a bootflash: 3509454 kB Kernel uptime is 28 day(s), 7 hour(s), 12 minute(s), 9 second(s)
構築~動作確認
Telemetry Receiver 初期設定
以下、どちらも同じサーバ上で動かします。
何度も立ち上げなおしたり恒久的に動かすものでもないので docker-compose は使ってないです。
dockercisco/elklat インストール~サービス起動
まずは Docker Hub の公式手順 ままで pull ~ run ~ 初期設定
$ docker pull dockercisco/elklat $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE dockercisco/elklat latest 826e2f062fc4 10 months ago 6.54GB $ docker run -d -p 5601:5601 -p 9200:9200 -p 5044:5044 -it 826e2f062fc bash $ docker exec -it cranky_sinoussi service elasticsearch start $ docker exec -it cranky_sinoussi service elasticsearch status * elasticsearch is running $ docker exec -it cranky_sinoussi service kibana start $ docker exec -it cranky_sinoussi service kibana status * kibana is running
これで http://<Docker母艦IPアドレス>:5601/
で Kibana の画面を見られる筈です。
Elasticsearch の mapping 設定(最低限)
Kibana で各 _source
の @timestamp
を拾うにあたって、Elasticsearch に格納されているどのフィールドを使うか...という設定をするのですが。
この後入れる telemetryreceiver
が送り付けてくるデータ構造は、postDate
というフィールドが何故か Unix Time 形式になってしまっています。
このまま Elasticsearch で自動的に mapping が生成されると postDate
が Kibana 上で String やら Integer やらとして解釈されてしまいます。
仕方ないので、ここだけは手動で mapping を作ってやります。
まず、既に過去のデータが telemetry
という index に格納されているので、これを掃除して
$ curl -XDELETE <Docker母艦IPアドレス>:9200/telemetry
そのうえで以下のように mapping を定義
$ curl -X PUT -H "Content-Type: application/json" -d @- <<EOT http://<Docker母艦IPアドレス>:9200/_template/tmpl_telemetry { "template": "telemetry*", "mappings": { "modify": { "properties": { "postDate": { "type": "date", "format": "strict_date_optional_time||epoch_millis" } } } } } EOT
dockercisco/telemetryreceiver インストール
2017/10/08
時点で見たところ latest
の更新日時が 2017/10/06
になっていて、絶賛開発中の模様です。
で、なんとなく嫌な予感がして一世代前の v4
を入れました。(深い理由はないです)
$ docker pull dockercisco/telemetryreceiver:v4 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE dockercisco/telemetryreceiver latest fbbc29139f5b 2 days ago 1.1GB dockercisco/telemetryreceiver v4 454c1e98fcbb 7 weeks ago 1.1GB dockercisco/elklat latest 826e2f062fc4 10 months ago 6.54GB $ docker run -d -p 50001:50001 -it fbbc29139f5b bash $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a70cce08a261 fbbc29139f5b "bash" 46 seconds ago Up 45 seconds 0.0.0.0:50001->50001/tcp dreamy_lamarr 68a5f661093b 826e2f062fc "bash" 6 minutes ago Up 6 minutes 0.0.0.0:5044->5044/tcp, 0.0.0.0:5601->5601/tcp, 0.0.0.0:9200->9200/tcp cranky_sinoussi $ docker exec -it vigilant_benz /grpc/telemetry/src/telemetry_receiver 50001 <Docker母艦IPアドレス> 9200 1 Server listening on 0.0.0.0:50001
最後の receiver プログラムを動かすやつは、公式手順では 末尾 "&" でバックグラウンド動作させています。
フォアグラウンドで動かしておくと、標準出力で以下のように NX-OS からの受信状況をリアルタイムで見るのに便利なので、そうしただけ。
Received GPB RPC with Data size is: 237550 Total RPC count:4926 Received GPB RPC with Data size is: 9043 Total RPC count:4927 Received GPB RPC with Data size is: 4627 Total RPC count:4928 Received GPB RPC with Data size is: 237550 Total RPC count:4929 Received GPB RPC with Data size is: 9043 Total RPC count:4930 Received GPB RPC with Data size is: 4627 Total RPC count:4931 Received GPB RPC with Data size is: 237550 Total RPC count:4932
Telemetry Sender 設定
NX-OS 側の設定を。
7.0(3)I6(1)
では、エージェントインストールなど特にする必要なく、単純に CLI で feature 有効化~送信設定をするだけです。
torsw101a# show run section telemetry show running-config | section telemetry feature telemetry telemetry destination-group 100 ip address <Docker母艦IPアドレス> port 50001 protocol gRPC encoding GPB sensor-group 100 path sys/bgp depth unbounded path sys/bd depth unbounded path sys/epId-1/nws depth unbounded subscription 600 dst-grp 100 snsr-grp 100 sample-interval 10000
sensor-group
にて Cisco 公式 / Cisco Nexus 3000 and 9000 Series Telemetry Sources や実際に送信されるデータ内容を見比べながら、シコシコシコシコとカスタマイズをしていくことになります。
Kibana 初期設定(index)
ここまでで「NX-OS がデータを送信して、telemetry_receiverがデコード~Elasticsearchに格納」ってところまではできている筈です。
まあ必要に応じて、Elasticsearch に $ curl -XGET <Docker母艦IPアドレス>:9200/telemetry/_search -d '{"query" : { "match_all" : {} }}' | python3 -m json.tool
とかすれば、格納されている情報がザッと(デフォルトは10件まで)見える。
なので、今度は Kibana の設定をば。
telemetry_receiver はデフォルトで telemetry
という名前で index
作っているので、それを拾う設定をします。
以下のように、既に届いているデータ構造の中から Time-field name
として postDate
が選択肢に現れるので、それを選択します。(先の mapping 設定 at Elasticsearch がちゃんとしていれば)
これで画面上側の Discover
タブを選んで、左上の index 選択で telemetry
を選んでやれば、ザーッと右側にデータが並びます。
Kibana / NX-OS でカスタマイズ
ここからは、以下のようなカスタマイズをひたすらに繰り返していくことになります。
- どんな情報を NX-OS から送信して
- どんな情報をどんな条件で Kibana で Visualize して
- どんな風に Kibana で Dashboard を見るか
既に Kibana の画面上で Settings > Objects
を見ると各種 Visualization
や Dashboard
が並んでいます。
が、これは別にそのまま使えるわけではなく(何かのデモで使ったものをベースにしているのか、開発中のものなのか)、少なくとも以下のようなカスタマイズが必要です。
Kibana
のVisualizations
index
にtelemetry
以外が指定されていたりするので、適宜変更- なお
telemetry_receiver
のlatest
ではindex
も自分で指定できるようになっていたので、もう少しカスタマイズがきく筈
- なお
node_id_str
という Field (要はNX-OS側のホスト名)がハードコードされていたりするので、適宜変更- 送信側である程度条件を絞っている、という前提がある(ものもある)ようで、送信側を雑に設定した時には期待通りの値を得られないので適宜変更
- 仮想版では正常に得られないような情報もありそうなので適宜修正
- etc etc
NX-OS
のsensor-group path
- 送信したい情報を選択
- どの階層にどの情報があるのか、マニュアルだけだとちゃんと分からないので試行錯誤
- 送信したい情報を選択
それでも、受信側をゼロから全てやっていくよりは大分マシだと思いますが。
例えば、以下のように事前定義されている Visualizations
Object が並んでいますが
その一つを編集画面はこんな感じで、「あー、この情報を NX-OS 側から送信するのね」とかやっていきます。
んで、自分向けのカスタマイズをして Visualizations
の一つが最低限の正しい情報が見られるようになって...
それを繰り返していけば、デフォルトの Dashboard
も少しずつ情報が埋まっていくし、自分好みのものも作れるでしょう。(折角なので時系列なやつも見られるようにしたいですよね)
おしまい ~ここからが本当の地獄だ...!!~
最後に述べたような盆栽カスタマイズをしていて、メーカ謹製の受信側アプリケーションがあると楽が出来るのかなーと。(SNMPの時代から変わらないですが)
Kibana も Elasticsearch も大規模環境でお守りをしていく...ことを考えると、なかなかしんどい。この辺はまあ、自分で頑張るか金で何とかするかの話ですね...。
あと、特に受信側はコンピュータリソースをかなり食うので、得たい・得るべき情報とそのコストを天秤にかけて運用に乗せるには結構手をかけねばな、という感触です。
はい、グダグダ言ってないで盆栽弄りに戻ります...。
Nexus9000v で VxLAN+EVPN (anycast gateway 編) Appendix. IPv6エンドノード通信確認
最初に
やること/サマリ
タイトルの通り、前回記事のオマケ
- 前回の記事 Nexus9000v で VxLAN+EVPN (anycast gateway 編) で除外していた「エンドノードおよび anycast gateway が IPv6」の設定と動作確認
- 結果から言うと IPv4 の場合と何ら変わらず
構成
前回の構成 と一緒で、以下のように IPv6 セグメントを足します。
参考資料
- 前回の参考資料全般
- Cisco 公式 / Cisco Programmable Fabric with VXLAN BGP EVPN Configuration Guide / Chapter: Unicast Forwarding
IPv6 address handling in the VXLAN BGP EVPN fabric
の項目
前回までの Nexus9000v 設定
スタート時点の設定として、関係個所のみ show run
結果をペタリ
- torsw101a
version 7.0(3)I6(1) hostname torsw101a nv overlay evpn feature ospf feature bgp feature interface-vlan feature vn-segment-vlan-based feature lldp clock timezone JST 9 0 feature nv overlay vlan 1,100,300,3901 fabric forwarding anycast-gateway-mac 2020.0000.00aa vlan 100 vn-segment 10100 vlan 300 vn-segment 10300 vlan 3901 vn-segment 50001 vrf context VRF001 vni 50001 rd auto address-family ipv4 unicast route-target both auto route-target both auto evpn vrf context management interface Vlan1 interface Vlan100 no shutdown vrf member VRF001 no ip redirects ip address 192.168.1.254/24 fabric forwarding mode anycast-gateway interface Vlan300 no shutdown vrf member VRF001 no ip redirects ip address 192.168.3.254/24 fabric forwarding mode anycast-gateway interface Vlan3901 no shutdown vrf member VRF001 ip forward interface nve1 no shutdown source-interface loopback1 host-reachability protocol bgp member vni 10001-10300 ingress-replication protocol bgp member vni 50001 associate-vrf interface Ethernet1/1 description DEV=node11 IF=ens4 switchport access vlan 100 interface Ethernet1/2 description DEV=node13 IF=ens4 switchport access vlan 300 interface Ethernet1/8 description DEV=spine001 IF=Eth1/1 no switchport mtu 9216 ip address 192.0.2.1/31 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0.0.0.0 no shutdown interface loopback0 ip address 172.16.1.1/32 ip router ospf OSPF_UNDERLAY area 0.0.0.0 interface loopback1 ip address 198.18.1.11/32 ip router ospf OSPF_UNDERLAY area 0.0.0.0 router ospf OSPF_UNDERLAY router-id 172.16.1.1 router bgp 64512 neighbor 172.31.0.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended vrf VRF001 address-family ipv4 unicast advertise l2vpn evpn evpn vni 10100 l2 rd auto route-target import auto route-target export auto vni 10300 l2 rd auto route-target import auto route-target export auto
- torsw201a
version 7.0(3)I6(1) hostname torsw201a nv overlay evpn feature ospf feature bgp feature interface-vlan feature vn-segment-vlan-based feature lldp clock timezone JST 9 0 feature nv overlay vlan 1,100,200,3901 fabric forwarding anycast-gateway-mac 2020.0000.00aa vlan 100 vn-segment 10100 vlan 200 vn-segment 10200 vlan 3901 vn-segment 50001 vrf context VRF001 vni 50001 rd auto address-family ipv4 unicast route-target both auto route-target both auto evpn vrf context management interface Vlan1 interface Vlan100 no shutdown vrf member VRF001 no ip redirects ip address 192.168.1.254/24 fabric forwarding mode anycast-gateway interface Vlan200 no shutdown vrf member VRF001 no ip redirects ip address 192.168.2.254/24 fabric forwarding mode anycast-gateway interface Vlan3901 no shutdown vrf member VRF001 ip forward interface nve1 no shutdown source-interface loopback1 host-reachability protocol bgp member vni 10001-10300 ingress-replication protocol bgp member vni 50001 associate-vrf interface Ethernet1/1 description DEV=node21 IF=ens4 switchport access vlan 100 interface Ethernet1/2 description DEV=node22 IF=ens4 switchport access vlan 200 interface Ethernet1/8 description DEV=spine001 IF=Eth1/2 no switchport mtu 9216 ip address 192.0.2.3/31 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0.0.0.0 no shutdown interface loopback0 ip address 172.16.2.1/32 ip router ospf OSPF_UNDERLAY area 0.0.0.0 interface loopback1 ip address 198.18.1.21/32 ip router ospf OSPF_UNDERLAY area 0.0.0.0 router ospf OSPF_UNDERLAY router-id 172.16.2.1 router bgp 64512 neighbor 172.31.0.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended vrf VRF001 address-family ipv4 unicast advertise l2vpn evpn evpn vni 10100 l2 rd auto route-target import auto route-target export auto vni 10200 l2 rd auto route-target import auto route-target export auto
- swpine001
version 7.0(3)I6(1) hostname spine001 nv overlay evpn feature ospf feature bgp feature lldp clock timezone JST 9 0 interface Ethernet1/1 description DEV=torsw101a IF=Eth1/8 no switchport mtu 9216 ip address 192.0.2.0/31 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0.0.0.0 no shutdown interface Ethernet1/2 description DEV=torsw201a IF=Eth1/8 no switchport mtu 9216 ip address 192.0.2.2/31 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0.0.0.0 no shutdown interface loopback0 ip address 172.31.0.1/32 ip router ospf OSPF_UNDERLAY area 0.0.0. router ospf OSPF_UNDERLAY router-id 172.31.0.1 router bgp 64512 neighbor 172.16.1.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended route-reflector-client neighbor 172.16.2.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended route-reflector-client
構築
node 群の設定
通信確認用ノード群の関連設定を貼っておきます。
- node11
kotetsu@node11:~$ ip a show dev ens4 3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:21:96:9a:03:01 brd ff:ff:ff:ff:ff:ff inet 192.168.1.1/24 brd 192.168.1.255 scope global ens4 valid_lft forever preferred_lft forever inet6 fd00:0:0:1::1/64 scope global valid_lft forever preferred_lft forever inet6 fe80::221:96ff:fe9a:301/64 scope link valid_lft forever preferred_lft forever kotetsu@node11:~$ ip -6 r show dev ens4 fd00:0:0:1::/64 proto kernel metric 256 pref medium fe80::/64 proto kernel metric 256 pref medium default via fd00:0:0:1::fe metric 1024 pref medium
- node13
kotetsu@node13:~$ ip a show dev ens4 3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:21:96:3d:6e:01 brd ff:ff:ff:ff:ff:ff inet 192.168.3.1/24 brd 192.168.3.255 scope global ens4 valid_lft forever preferred_lft forever inet6 fd00:0:0:3::1/64 scope global valid_lft forever preferred_lft forever inet6 fe80::221:96ff:fe3d:6e01/64 scope link valid_lft forever preferred_lft forever kotetsu@node13:~$ ip -6 r show dev ens4 fd00:0:0:3::/64 proto kernel metric 256 pref medium fe80::/64 proto kernel metric 256 pref medium default via fd00:0:0:3::fe metric 1024 pref medium
- node21
kotetsu@node21:~$ ip a show dev ens4 3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:21:96:9f:c7:01 brd ff:ff:ff:ff:ff:ff inet 192.168.1.2/24 brd 192.168.1.255 scope global ens4 valid_lft forever preferred_lft forever inet6 fd00:0:0:1::2/64 scope global valid_lft forever preferred_lft forever inet6 fe80::221:96ff:fe9f:c701/64 scope link valid_lft forever preferred_lft forever kotetsu@node21:~$ ip -6 r show dev ens4 fd00:0:0:1::/64 proto kernel metric 256 pref medium fe80::/64 proto kernel metric 256 pref medium default via fd00:0:0:1::fe metric 1024 pref medium
- node22
kotetsu@node22:~$ ip a show dev ens4 3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:21:96:42:5f:01 brd ff:ff:ff:ff:ff:ff inet 192.168.2.1/24 brd 192.168.2.255 scope global ens4 valid_lft forever preferred_lft forever inet6 fd00:0:0:2::1/64 scope global valid_lft forever preferred_lft forever inet6 fe80::221:96ff:fe42:5f01/64 scope link valid_lft forever preferred_lft forever kotetsu@node22:~$ ip -6 r show dev ens4 fd00:0:0:2::/64 proto kernel metric 256 pref medium fe80::/64 proto kernel metric 256 pref medium default via fd00:0:0:2::fe metric 1024 pref medium
Nexus9000v 追加設定
IPv6 関係の設定追加内容は以下の通り
interface vlan 3901
という L3VNI 用の SVI でも ipv6 forward
設定をしておかないと、受信した VxLAN パケットをノード側に転送してくれないです。
- torsw101a
interface vlan 100 ipv6 address fd00:0:0:1::fe/64 interface vlan 300 ipv6 address fd00:0:0:3::fe/64 interface vlan 3901 ipv6 forward vrf context VRF001 address-family ipv6 unicast route-target both auto route-target both auto evpn
- torsw201a
interface vlan 100 ipv6 address fd00:0:0:1::fe/64 interface vlan 200 ipv6 address fd00:0:0:2::fe/64 interface vlan 3901 ipv6 forward vrf context VRF001 address-family ipv6 unicast route-target both auto route-target both auto evpn
Nexus9000v 各種テーブル確認
ノード間がフルメッシュで IPv6 での通信が可能になったので、通信確認後の Nexus9000v テーブル情報を。
EVPN 学習経路情報
torsw101a# show bgp l2vpn evpn BGP routing table information for VRF default, address family L2VPN EVPN BGP table version is 15946, local router ID is 172.16.1.1 Status: s-suppressed, x-deleted, S-stale, d-dampened, h-history, *-valid, >-best Path type: i-internal, e-external, c-confed, l-local, a-aggregate, r-redist, I-injected Origin codes: i - IGP, e - EGP, ? - incomplete, | - multipath, & - backup Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 172.16.1.1:32867 (L2VNI 10100) *>l[2]:[0]:[0]:[48]:[0021.969a.0301]:[0]:[0.0.0.0]/216 198.18.1.11 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[0]:[0.0.0.0]/216 198.18.1.21 100 0 i *>l[2]:[0]:[0]:[48]:[0021.969a.0301]:[32]:[192.168.1.1]/272 198.18.1.11 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 0 i *>l[2]:[0]:[0]:[48]:[0021.969a.0301]:[128]:[fd00:0:0:1::1]/368 198.18.1.11 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[128]:[fd00:0:0:1::2]/368 198.18.1.21 100 0 i *>l[3]:[0]:[32]:[198.18.1.11]/88 198.18.1.11 100 32768 i *>i[3]:[0]:[32]:[198.18.1.21]/88 198.18.1.21 100 0 i Route Distinguisher: 172.16.1.1:33067 (L2VNI 10300) *>l[2]:[0]:[0]:[48]:[0021.963d.6e01]:[0]:[0.0.0.0]/216 198.18.1.11 100 32768 i *>l[2]:[0]:[0]:[48]:[0021.963d.6e01]:[32]:[192.168.3.1]/272 198.18.1.11 100 32768 i *>l[2]:[0]:[0]:[48]:[0021.963d.6e01]:[128]:[fd00:0:0:3::1]/368 198.18.1.11 100 32768 i *>l[3]:[0]:[32]:[198.18.1.11]/88 198.18.1.11 100 32768 i Route Distinguisher: 172.16.2.1:32867 *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[0]:[0.0.0.0]/216 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[128]:[fd00:0:0:1::2]/368 198.18.1.21 100 0 i *>i[3]:[0]:[32]:[198.18.1.21]/88 198.18.1.21 100 0 i Route Distinguisher: 172.16.2.1:32967 *>i[2]:[0]:[0]:[48]:[0021.9642.5f01]:[32]:[192.168.2.1]/272 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.9642.5f01]:[128]:[fd00:0:0:2::1]/368 198.18.1.21 100 0 i Route Distinguisher: 172.16.1.1:3 (L3VNI 50001) *>i[2]:[0]:[0]:[48]:[0021.9642.5f01]:[32]:[192.168.2.1]/272 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.9642.5f01]:[128]:[fd00:0:0:2::1]/368 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[128]:[fd00:0:0:1::2]/368 198.18.1.21 100 0 i
torsw201a# show bgp l2vpn evpn BGP routing table information for VRF default, address family L2VPN EVPN BGP table version is 16191, local router ID is 172.16.2.1 Status: s-suppressed, x-deleted, S-stale, d-dampened, h-history, *-valid, >-best Path type: i-internal, e-external, c-confed, l-local, a-aggregate, r-redist, I-injected Origin codes: i - IGP, e - EGP, ? - incomplete, | - multipath, & - backup Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 172.16.1.1:32867 *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[0]:[0.0.0.0]/216 198.18.1.11 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[32]:[192.168.1.1]/272 198.18.1.11 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[128]:[fd00:0:0:1::1]/368 198.18.1.11 100 0 i *>i[3]:[0]:[32]:[198.18.1.11]/88 198.18.1.11 100 0 i Route Distinguisher: 172.16.1.1:33067 *>i[2]:[0]:[0]:[48]:[0021.963d.6e01]:[32]:[192.168.3.1]/272 198.18.1.11 100 0 i *>i[2]:[0]:[0]:[48]:[0021.963d.6e01]:[128]:[fd00:0:0:3::1]/368 198.18.1.11 100 0 i Route Distinguisher: 172.16.2.1:32867 (L2VNI 10100) *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[0]:[0.0.0.0]/216 198.18.1.11 100 0 i *>l[2]:[0]:[0]:[48]:[0021.969f.c701]:[0]:[0.0.0.0]/216 198.18.1.21 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[32]:[192.168.1.1]/272 198.18.1.11 100 0 i *>l[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[128]:[fd00:0:0:1::1]/368 198.18.1.11 100 0 i *>l[2]:[0]:[0]:[48]:[0021.969f.c701]:[128]:[fd00:0:0:1::2]/368 198.18.1.21 100 32768 i *>i[3]:[0]:[32]:[198.18.1.11]/88 198.18.1.11 100 0 i *>l[3]:[0]:[32]:[198.18.1.21]/88 198.18.1.21 100 32768 i Route Distinguisher: 172.16.2.1:32967 (L2VNI 10200) *>l[2]:[0]:[0]:[48]:[0021.9642.5f01]:[0]:[0.0.0.0]/216 198.18.1.21 100 32768 i *>l[2]:[0]:[0]:[48]:[0021.9642.5f01]:[32]:[192.168.2.1]/272 198.18.1.21 100 32768 i *>l[2]:[0]:[0]:[48]:[0021.9642.5f01]:[128]:[fd00:0:0:2::1]/368 198.18.1.21 100 32768 i *>l[3]:[0]:[32]:[198.18.1.21]/88 198.18.1.21 100 32768 i Route Distinguisher: 172.16.2.1:3 (L3VNI 50001) *>i[2]:[0]:[0]:[48]:[0021.963d.6e01]:[32]:[192.168.3.1]/272 198.18.1.11 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[32]:[192.168.1.1]/272 198.18.1.11 100 0 i *>i[2]:[0]:[0]:[48]:[0021.963d.6e01]:[128]:[fd00:0:0:3::1]/368 198.18.1.11 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969a.0301]:[128]:[fd00:0:0:1::1]/368 198.18.1.11 100 0 i
ドリルダウンして、特定経路の詳細を見るとこんな感じ。
出力情報の解説は Cisco 公式 / Cisco Programmable Fabric with VXLAN BGP EVPN Configuration Guide / Chapter: Unicast Forwarding の下の方をご参照くださいませ。
torsw101a
で node22 (torsw201a 配下)
の情報を見たものです。
torsw101a# show bgp l2vpn evpn fd00:0:0:2::1 BGP routing table information for VRF default, address family L2VPN EVPN Route Distinguisher: 172.16.2.1:32967 BGP routing table entry for [2]:[0]:[0]:[48]:[0021.9642.5f01]:[128]:[fd00:0:0:2::1]/368, version 15909 Paths: (1 available, best #1) Flags: (0x000202) on xmit-list, is not in l2rib/evpn, is not in HW, is locked Advertised path-id 1 Path type: internal, path is valid, is best path, no labeled nexthop AS-Path: NONE, path sourced internal to AS 198.18.1.21 (metric 81) from 172.31.0.1 (172.31.0.1) Origin IGP, MED not set, localpref 100, weight 0 Received label 10200 50001 Extcommunity: RT:64512:10200 RT:64512:50001 ENCAP:8 Router MAC:0021.9643.7607 Originator: 172.16.2.1 Cluster list: 172.31.0.1 Path-id 1 not advertised to any peer Route Distinguisher: 172.16.1.1:3 (L3VNI 50001) BGP routing table entry for [2]:[0]:[0]:[48]:[0021.9642.5f01]:[128]:[fd00:0:0:2::1]/368, version 15912 Paths: (1 available, best #1) Flags: (0x000202) on xmit-list, is not in l2rib/evpn, is not in HW Advertised path-id 1 Path type: internal, path is valid, is best path, no labeled nexthop Imported from 172.16.2.1:32967:[2]:[0]:[0]:[48]:[0021.9642.5f01]:[128]:[fd00:0:0:2::1]/240 AS-Path: NONE, path sourced internal to AS 198.18.1.21 (metric 81) from 172.31.0.1 (172.31.0.1) Origin IGP, MED not set, localpref 100, weight 0 Received label 10200 50001 Extcommunity: RT:64512:10200 RT:64512:50001 ENCAP:8 Router MAC:0021.9643.7607 Originator: 172.16.2.1 Cluster list: 172.31.0.1 Path-id 1 not advertised to any peer
VRF のルーティングテーブル(IPv6)
torsw101a# show ipv6 route vrf VRF001 IPv6 Routing Table for VRF "VRF001" '*' denotes best ucast next-hop '**' denotes best mcast next-hop '[x/y]' denotes [preference/metric] fd00:0:0:1::/64, ubest/mbest: 1/0, attached *via fd00:0:0:1::fe, Vlan100, [0/0], 01:27:22, direct, fd00:0:0:1::1/128, ubest/mbest: 1/0, attached *via fd00:0:0:1::1, Vlan100, [190/0], 01:24:44, hmm fd00:0:0:1::2/128, ubest/mbest: 1/0 *via ::ffff:198.18.1.21%default:IPv4, [200/0], 01:14:49, bgp-64512, internal, tag 64512 (evpn) segid 50001 tunnel: 0xc6120115 encap: VXLAN fd00:0:0:1::fe/128, ubest/mbest: 1/0, attached *via fd00:0:0:1::fe, Vlan100, [0/0], 01:27:22, local fd00:0:0:2::1/128, ubest/mbest: 1/0 *via ::ffff:198.18.1.21%default:IPv4, [200/0], 01:14:49, bgp-64512, internal, tag 64512 (evpn) segid 50001 tunnel: 0xc6120115 encap: VXLAN fd00:0:0:3::/64, ubest/mbest: 1/0, attached *via fd00:0:0:3::fe, Vlan300, [0/0], 01:26:13, direct, fd00:0:0:3::1/128, ubest/mbest: 1/0, attached *via fd00:0:0:3::1, Vlan300, [190/0], 01:24:45, hmm fd00:0:0:3::fe/128, ubest/mbest: 1/0, attached *via fd00:0:0:3::fe, Vlan300, [0/0], 01:26:13, local
torsw201a# show ipv6 route vrf VRF001 IPv6 Routing Table for VRF "VRF001" '*' denotes best ucast next-hop '**' denotes best mcast next-hop '[x/y]' denotes [preference/metric] fd00:0:0:1::/64, ubest/mbest: 1/0, attached *via fd00:0:0:1::fe, Vlan100, [0/0], 01:27:51, direct, fd00:0:0:1::1/128, ubest/mbest: 1/0 *via ::ffff:198.18.1.11%default:IPv4, [200/0], 01:15:31, bgp-64512, internal, tag 64512 (evpn) segid 50001 tunnel: 0xc612010b encap: VXLAN fd00:0:0:1::2/128, ubest/mbest: 1/0, attached *via fd00:0:0:1::2, Vlan100, [190/0], 01:17:26, hmm fd00:0:0:1::fe/128, ubest/mbest: 1/0, attached *via fd00:0:0:1::fe, Vlan100, [0/0], 01:27:51, local fd00:0:0:2::/64, ubest/mbest: 1/0, attached *via fd00:0:0:2::fe, Vlan200, [0/0], 01:26:04, direct, fd00:0:0:2::1/128, ubest/mbest: 1/0, attached *via fd00:0:0:2::1, Vlan200, [190/0], 01:17:27, hmm fd00:0:0:2::fe/128, ubest/mbest: 1/0, attached *via fd00:0:0:2::fe, Vlan200, [0/0], 01:26:04, local fd00:0:0:3::1/128, ubest/mbest: 1/0 *via ::ffff:198.18.1.11%default:IPv4, [200/0], 01:15:31, bgp-64512, internal, tag 64512 (evpn) segid 50001 tunnel: 0xc612010b encap: VXLAN
VRF のND テーブル
torsw101a# show ipv6 neighbor vrf VRF001 Flags: # - Adjacencies Throttled for Glean G - Adjacencies of vPC peer with G/W bit R - Adjacencies learnt remotely CP - Added via L2RIB, Control plane Adjacencies PS - Added via L2RIB, Peer Sync RO - Dervied from L2RIB Peer Sync Entry IPv6 Adjacency Table for VRF VRF001 Total number of entries: 4 Address Age MAC Address Pref Source Interface fd00:0:0:3::1 07:50:57 0021.963d.6e01 50 icmpv6 Vlan300 fe80::221:96ff:fe3d:6e01 07:50:52 0021.963d.6e01 50 icmpv6 Vlan300 fd00:0:0:1::1 07:50:56 0021.969a.0301 50 icmpv6 Vlan100 fe80::221:96ff:fe9a:301 07:50:57 0021.969a.0301 50 icmpv6 Vlan100
torsw201a# show ipv6 neighbor vrf VRF001 Flags: # - Adjacencies Throttled for Glean G - Adjacencies of vPC peer with G/W bit R - Adjacencies learnt remotely CP - Added via L2RIB, Control plane Adjacencies PS - Added via L2RIB, Peer Sync RO - Dervied from L2RIB Peer Sync Entry IPv6 Adjacency Table for VRF VRF001 Total number of entries: 4 Address Age MAC Address Pref Source Interface fd00:0:0:1::2 07:43:00 0021.969f.c701 50 icmpv6 Vlan100 fe80::221:96ff:fe9f:c701 07:43:01 0021.969f.c701 50 icmpv6 Vlan100 fd00:0:0:2::1 07:43:01 0021.9642.5f01 50 icmpv6 Vlan200 fe80::221:96ff:fe42:5f01 07:42:56 0021.9642.5f01 50 icmpv6 Vlan200
おしまい
Nexus9000v で VxLAN+EVPN (anycast gateway 編)
最初に
本項でやること / 概要構成図
- Nexus9000v で VxLAN の Control Plane として EVPN を動かす
- EVPN NLRI Type2+3 を使って L2 と L3 統合 (Type5 は登場しない)
- L3 端点では anycast gateway を動かす
- ARP suppression は仮想版Nexus9000vでは現状サポートされないので確認対象外
- L3 で動かすのは IPv4 のみ
- IPv6 は Nexus9000v で VxLAN+EVPN (anycast gateway 編) Appendix. IPv6エンドノード通信確認 としてオマケ記事にしていますが、別に動作に変わりはないです
- L3 端点では anycast gateway を動かす
以前 Juniper vQFX で似たようなことを試した のですが、その Nexus9000v 版です。
実装の違いにより、完全に同じではないですが。
構成としてはこんな感じで
肝になる EVPN 周りの動作はこんな感じで
テナントから見るとこんな風かな、という絵
参考資料
- EVPN 標準 関連
- RFC7432 (BGP MPLS-Based Ethernet VPN)
- draft-ietf-bess-evpn-inter-subnet-forwarding-03
- L3回り、Symmetric と Asymmetric の詳細
- draft-snr-bess-evpn-proxy-arp-nd-02
- ARP suppression回り
- 今回は仮想版の機能制約により確認対象外
- Cisco Nexus 9000v 関連
- Cisco 公式 / Cisco Nexus 9000v Switch / Document
- Nexus9000全般のドキュメント
- Cisco 公式 / A Modern, Open, and Scalable Fabric: VXLAN EVPN(pdf)
- 一般的な VxLAN + EVPN の話が書いてあるのと共に、Nexus9000 実装に関しても書かれている(全170P)
- P35-36 に
Asymmetric vs Symmetric Forwarding
の話- Nexus は sysmmetric のみサポートと書いてある
- P62-65 に
anycast gateway
実装の話
- Cisco 公式 / Cisco Programmable Fabric with VXLAN BGP EVPN Configuration Guide
- 設定ガイド、これをメインの手引書として使う
- Cisco 公式 / Cisco Nexus 9000 Series NX-OS VXLAN Configuration Guide, Release 7.x
- Cisco 公式 / NX-OSv 9000 Guide / NX-OSv 9000 Software Functionality
- VxLAN + EVPN の技術全般を割と詳細に解説しており(メーカに依存しない話)、Cisco Nexus の実装話も盛り込まれている良書 (先の PDF とかのより詳説版的なイメージ)
- Cisco 公式 / Cisco Nexus 9000v Switch / Document
Building Data Centers with VXLAN BGP EVPN: A Cisco NX-OS Perspective (Networking Technology)
- 作者: Lukas Krattiger,Shyam Kapadia,David Jansen
- 出版社/メーカー: Cisco Press
- 発売日: 2017/04/10
- メディア: ペーパーバック
- この商品を含むブログを見る
環境情報
KVM 母艦と GNS3 は以下の感じで(前回 から Ubuntu と GNS3 のバージョンアップしているので一応)
$ uname -a Linux kvm01 4.4.0-93-generic #116-Ubuntu SMP Fri Aug 11 21:17:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS" $ virsh -v 1.3.1 $ qemu-system-x86_64 --version QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.14), Copyright (c) 2003-2008 Fabrice Bellard $ gns3 --version 2.0.3
Nexus9000v
は 2017/08/16
現在ダウンロード可能な最新の nxosv-final.7.0.3.I6.1.qcow2
で OVMF
は 2016/08/13
時点のビルド版ぽい(MARKETPLACE
で降ってきたのを使っただけ)
構築
Nexus9000v デプロイ
前回の記事 の感じで、ポチポチとデプロイしていきます。
今回、メモリは全て最低要件を狙って 4096MB
としてあります。(Memory Usage Warning みたいなのは Syslog に出ていたけれど…)
同様に、疎通確認用のノードもいくらか用意しておきます。
Nexus9000v 物理IF 設定
Nexus 同士の部分をば。VxLAN 渡すので MTU は大きめに。
あと、NXOS の特徴的なところで feature なにがし
で有効化しないと設定コマンドの候補も出てこないので、使う機能は feature
コマンドでまず有効化する必要ありです。
- spine001
feature lldp interface Ethernet1/1 description DEV=torsw101a IF=Eth1/8 no switchport mtu 9216 ip address 192.0.2.0/31 no shutdown interface Ethernet1/2 description DEV=torsw201a IF=Eth1/8 no switchport mtu 9216 ip address 192.0.2.2/31 no shutdown
- torsw101a
feature lldp interface Ethernet1/8 description DEV=spine001 IF=Eth1/1 no switchport mtu 9216 ip address 192.0.2.1/31 no shutdown
- torsw201a
feature lldp interface Ethernet1/8 description DEV=spine001 IF=Eth1/2 no switchport mtu 9216 ip address 192.0.2.3/31 no shutdown
Nexus9000v Underlay 設定
IP Unnumbered も動くみたいですが ip unnumbered loopback0
は コマンドが通らなかったので、前章の通り普通に IP アドレス降ってます。(何かの feature を有効化する必要あるのか、仮想版の機能制約かは未調査)
プロトコル選択肢としては IS-IS
や eBGP
なども使えるようですが、「ちゃんとテストしているのは OSPF と IS-IS だ」って書いてあったので、あまり考えずに OSPF 使ってます。
これまでの記事(vQFX や Cumulus Linux)では大体 eBGP 使っていましたが、NXOS の設定体系で BGP に Underlay と Overlay を混ぜ込むと(自分的に)分かりが良くなかったというのもありますが。
設定
- spine01
feature ospf interface loopback0 ip address 172.31.0.1/32 router ospf OSPF_UNDERLAY router-id 172.31.0.1 interface Ethernet1/1 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0 interface Ethernet1/2 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0 interface loopback0 ip router ospf OSPF_UNDERLAY area 0.0.0.0
- torsw101a
feature ospf interface loopback0 ip address 172.16.1.1/32 router ospf OSPF_UNDERLAY router-id 172.16.1.1 interface Ethernet1/8 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0 interface loopback0 ip router ospf OSPF_UNDERLAY area 0
- torsw201a
feature ospf interface loopback0 ip address 172.16.2.1/32 router ospf OSPF_UNDERLAY router-id 172.16.2.1 interface Ethernet1/8 ip ospf network point-to-point ip router ospf OSPF_UNDERLAY area 0 interface loopback0 ip router ospf OSPF_UNDERLAY area 0
エリア0オンリーでやってますが、大規模環境ではエリア分けも検討するのが良いでしょうかね。
簡易動作確認
1台分をチラ見。
spine001# show ip route IP Route Table for VRF "default" '*' denotes best ucast next-hop '**' denotes best mcast next-hop '[x/y]' denotes [preference/metric] '%<string>' in via output denotes VRF <string> 172.16.1.1/32, ubest/mbest: 1/0 *via 192.0.2.1, Eth1/1, [110/41], 00:12:23, ospf-OSPF_UNDERLAY, intra 172.16.2.1/32, ubest/mbest: 1/0 *via 192.0.2.3, Eth1/2, [110/41], 00:03:39, ospf-OSPF_UNDERLAY, intra 172.31.0.1/32, ubest/mbest: 2/0, attached *via 172.31.0.1, Lo0, [0/0], 00:35:13, local *via 172.31.0.1, Lo0, [0/0], 00:35:13, direct 192.0.2.0/31, ubest/mbest: 1/0, attached *via 192.0.2.0, Eth1/1, [0/0], 00:22:47, direct 192.0.2.0/32, ubest/mbest: 1/0, attached *via 192.0.2.0, Eth1/1, [0/0], 00:22:47, local 192.0.2.2/31, ubest/mbest: 1/0, attached *via 192.0.2.2, Eth1/2, [0/0], 00:22:37, direct 192.0.2.2/32, ubest/mbest: 1/0, attached *via 192.0.2.2, Eth1/2, [0/0], 00:22:37, local spine001# show ip ospf neighbors OSPF Process ID OSPF_UNDERLAY VRF default Total number of neighbors: 2 Neighbor ID Pri State Up Time Address Interface 172.16.1.1 1 FULL/ - 00:21:16 192.0.2.1 Eth1/1 172.16.2.1 1 FULL/ - 00:12:01 192.0.2.3 Eth1/2
Nexus9000v Overlay 設定
- spine001
feature bgp nv overlay evpn router bgp 64512 neighbor 172.16.1.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended route-reflector-client neighbor 172.16.2.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended route-reflector-client
- torsw101a
feature bgp nv overlay evpn router bgp 64512 neighbor 172.31.0.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended
- torsw201a
feature bgp nv overlay evpn router bgp 64512 neighbor 172.31.0.1 remote-as 64512 update-source loopback0 address-family l2vpn evpn send-community send-community extended
Nexus9000v VxLAN + EVPN 設定
設定の羅列を。
!
で軽くポイントをコメント入れておきます…(torsw101a
と torsw201a
はほぼ一緒の設定なので、torsw101a
側のみに)。
なお、spine001
は Control Plane としては MP-BGP の RR 動作しますがその設定は済んでおり、Data Plane としては VxLAN 通信 の土管にしかならないので、本項では何も追加設定なしです。
- torsw101a
! anycast gateway の仮想 MAC アドレス ! fabric forwarding mode anycast-gateway 設定した SVI 全てで使われる Global 設定 fabric forwarding anycast-gateway-mac 20:20:00:00:00:AA feature vn-segment-vlan-based ! L2 VNI と VLAN ID の mapping vlan 100 vn-segment 10100 vlan 300 vn-segment 10300 ! VTEP 間 VxLAN 通信の Src/Dst IP アドレスとなる loopback (先に設定した loopback0 は EVPN Signaling 用 iBGP 用) interface loopback1 ip address 198.18.1.11/32 ip router ospf OSPF_UNDERLAY area 0.0.0.0 feature nv overlay ! Network Virtualization Endpoint (VTEP 用デバイス?インターフェース? 適切な言葉が...) interface nve1 source-interface loopback1 host-reachability protocol bgp ! テナント向け VRF ! ちなみにデフォルトで mgmt は management VRF に所属している vrf context VRF001 ! 本 VRF 専用の L3VNI vni 50001 rd auto address-family ipv4 unicast route-target both auto route-target both auto evpn interface nve1 ! - や , で指定可能 ! ただし上限数があって 10001-14094 とVLAN 4094 分やろうとしたらエラーになった member vni 10001-10300 ! BUM トラフィック処理方法(VTEP 間) は Ingress Replication でユニキャスト通信させる ! マルチキャストも選択可能だが、そもそもこんな調査・検証している理由のひとつに「マルチキャストルーティング使いたくない」もあるので ingress-replication protocol bgp member vni 50001 associate-vrf no shutdown router bgp 64512 vrf VRF001 address-family ipv4 unicast advertise l2vpn evpn ! テナント用 SVI 群 ! SVI 200 は torsw201a 側のみ、SVI 300 は torsw101a 側のみで OK feature interface-vlan interface Vlan100 no shutdown vrf member VRF001 no ip redirects ip address 192.168.1.254/24 ! 本セグメントで anycast gateway を使う fabric forwarding mode anycast-gateway interface Vlan300 no shutdown vrf member VRF001 no ip redirects ip address 192.168.3.254/24 fabric forwarding mode anycast-gateway ! テナント エンドノード収容物理 IF 設定 ! trunk VLAN でも OK interface Ethernet1/1 switchport access vlan 100 description DEV=node11 IF=ens4 interface Ethernet1/2 switchport access vlan 300 description DEV=node13 IF=ens4 evpn vni 10100 l2 rd auto route-target import auto route-target export auto vni 10300 l2 rd auto route-target import auto route-target export auto ! テナント VRF の L3 VNI につきひとつ、VLAN と SVI が必要... ! なお、VLAN は 4094 全て使えるわけでなく 39XX までしかいけない vlan 3901 vn-segment 50001 interface Vlan3901 no shutdown vrf member VRF001 ip forward
- torsw201a
fabric forwarding anycast-gateway-mac 20:20:00:00:00:AA feature vn-segment-vlan-based vlan 100 vn-segment 10100 vlan 200 vn-segment 10200 interface loopback1 ip address 198.18.1.21/32 ip router ospf OSPF_UNDERLAY area 0.0.0.0 feature nv overlay interface nve1 source-interface loopback1 host-reachability protocol bgp vrf context VRF001 vni 50001 rd auto address-family ipv4 unicast route-target both auto route-target both auto evpn interface nve1 member vni 10001-10300 ingress-replication protocol bgp member vni 50001 associate-vrf no shutdown router bgp 64512 vrf VRF001 address-family ipv4 unicast advertise l2vpn evpn feature interface-vlan interface Vlan100 no shutdown vrf member VRF001 no ip redirects ip address 192.168.1.254/24 fabric forwarding mode anycast-gateway interface Vlan200 no shutdown vrf member VRF001 no ip redirects ip address 192.168.2.254/24 fabric forwarding mode anycast-gateway interface Ethernet1/1 switchport access vlan 100 description DEV=node21 IF=ens4 interface Ethernet1/2 switchport access vlan 200 description DEV=node22 IF=ens4 evpn vni 10100 l2 rd auto route-target import auto route-target export auto vni 10200 l2 rd auto route-target import auto route-target export auto vlan 3901 vn-segment 50001 interface Vlan3901 no shutdown vrf member VRF001 ip forward
動作確認
Nexus9000v 各種テーブル確認
これで 4 つの node が相互通信可能になったわけですが、その通信確認後の Nexus9000v のテーブルを見ていきます。
VTEP 同士の peer 状態 / 自身の NVE 状態
torsw101a# show nve peers detail Details of nve Peers: ---------------------------------------- Peer-Ip: 198.18.1.21 NVE Interface : nve1 Peer State : Up Peer Uptime : 05:40:49 Router-Mac : 0021.9643.7607 Peer First VNI : 50001 Time since Create : 05:40:50 Configured VNIs : 10001-10300,50001 Provision State : add-complete Route-Update : Yes Peer Flags : RmacL2Rib, TunnelPD, DisableLearn Learnt CP VNIs : 10100,50001 Peer-ifindex-resp : Yes ---------------------------------------- torsw101a# show nve internal platform interface nve 1 detail Printing Interface ifindex 0x49000001 detail |======|=========================|===============|===============|=====|=====| |Intf |State |PriIP |SecIP |Vnis |Peers| |======|=========================|===============|===============|=====|=====| |nve1 |UP |198.18.1.11 |0.0.0.0 |3 |1 | |======|=========================|===============|===============|=====|=====| SW_BD/VNIs of interface nve1: ================================================ |======|======|=========================|======|====|======|======== |Sw BD |Vni |State |Intf |Type|Vrf-ID|Notified |======|======|=========================|======|====|======|======== |100 |10100 |UP |nve1 |CP |0 |Yes |300 |10300 |UP |nve1 |CP |0 |Yes |3901 |50001 |UP |nve1 |CP |3 |Yes |======|======|=========================|======|====|======|======== Peers of interface nve1: ============================================ Peer_ip: 198.18.1.21 Peer-ID : 1 State : UP Learning : Disabled TunnelID : 0xc6120115 MAC : 0021.9643.7607 Table-ID : 0x1 Encap : 0x1
torsw201a# show nve peers detail Details of nve Peers: ---------------------------------------- Peer-Ip: 198.18.1.11 NVE Interface : nve1 Peer State : Up Peer Uptime : 05:40:33 Router-Mac : 0021.960f.f307 Peer First VNI : 10100 Time since Create : 05:40:33 Configured VNIs : 10001-10300,50001 Provision State : add-complete Route-Update : Yes Peer Flags : RmacL2Rib, TunnelPD, DisableLearn Learnt CP VNIs : 10100,50001 Peer-ifindex-resp : Yes ---------------------------------------- torsw201a# show nve internal platform interface nve 1 detail Printing Interface ifindex 0x49000001 detail |======|=========================|===============|===============|=====|=====| |Intf |State |PriIP |SecIP |Vnis |Peers| |======|=========================|===============|===============|=====|=====| |nve1 |UP |198.18.1.21 |0.0.0.0 |3 |1 | |======|=========================|===============|===============|=====|=====| SW_BD/VNIs of interface nve1: ================================================ |======|======|=========================|======|====|======|======== |Sw BD |Vni |State |Intf |Type|Vrf-ID|Notified |======|======|=========================|======|====|======|======== |100 |10100 |UP |nve1 |CP |0 |Yes |200 |10200 |UP |nve1 |CP |0 |Yes |3901 |50001 |UP |nve1 |CP |3 |Yes |======|======|=========================|======|====|======|======== Peers of interface nve1: ============================================ Peer_ip: 198.18.1.11 Peer-ID : 1 State : UP Learning : Disabled TunnelID : 0xc612010b MAC : 0021.960f.f307 Table-ID : 0x1 Encap : 0x1
あと、設定終わったと思いきや何か想定通り動かない…って時に、以下のコマンドを使いました。
以下出力例は「L3 VNI 用の SVI と VLAN が不正(前記設定の 3901 を設定していなかった)」ものですが、他にも mcast-group-or-ingress-rep-not-cfg
みたいな割と分かりやすい出力もあります。
torsw101a# show nve internal vni 50001 VNI 50001 Ready-State : Not Ready [invalid sw-bd]
MP-BGP for EVPN Signaling Neighbor 情報
torsw101a# show bgp l2vpn evpn neighbors BGP neighbor is 172.31.0.1, remote AS 64512, ibgp link, Peer index 3 BGP version 4, remote router ID 172.31.0.1 BGP state = Established, up for 1d06h Using loopback0 as update source for this peer Last read 00:00:14, hold time = 180, keepalive interval is 60 seconds Last written 00:00:48, keepalive timer expiry due 00:00:11 Received 2911 messages, 0 notifications, 0 bytes in queue Sent 3216 messages, 0 notifications, 0 bytes in queue Connections established 1, dropped 0 Last reset by us never, due to No error Last reset by peer never, due to No error Neighbor capabilities: Dynamic capability: advertised (mp, refresh, gr) received (mp, refresh, gr) Dynamic capability (old): advertised received Route refresh capability (new): advertised received Route refresh capability (old): advertised received 4-Byte AS capability: advertised received Address family L2VPN EVPN: advertised received Graceful Restart capability: advertised received Graceful Restart Parameters: Address families advertised to peer: L2VPN EVPN Address families received from peer: L2VPN EVPN Forwarding state preserved by peer for: Restart time advertised to peer: 120 seconds Stale time for routes advertised by peer: 300 seconds Restart time advertised by peer: 120 seconds Extended Next Hop Encoding Capability: advertised received Receive IPv6 next hop encoding Capability for AF: IPv4 Unicast Message statistics: Sent Rcvd Opens: 1 1 Notifications: 0 0 Updates: 1443 1449 Keepalives: 1771 1460 Route Refresh: 0 0 Capability: 1 1 Total: 3216 2911 Total bytes: 155694 160466 Bytes in queue: 0 0 For address family: L2VPN EVPN BGP table version 2897, neighbor version 2897 4 accepted paths consume 512 bytes of memory 6 sent paths Community attribute sent to this neighbor Extended community attribute sent to this neighbor Third-party Nexthop will not be computed. Last End-of-RIB received 00:00:01 after session start Local host: 172.16.1.1, Local port: 19618 Foreign host: 172.31.0.1, Foreign port: 179 fd = 76
EVPN 学習経路情報
Cumulus Linux と似た出力フォーマットですね。
torsw101a# show bgp l2vpn evpn BGP routing table information for VRF default, address family L2VPN EVPN BGP table version is 2893, local router ID is 172.16.1.1 Status: s-suppressed, x-deleted, S-stale, d-dampened, h-history, *-valid, >-best Path type: i-internal, e-external, c-confed, l-local, a-aggregate, r-redist, I-injected Origin codes: i - IGP, e - EGP, ? - incomplete, | - multipath, & - backup Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 172.16.1.1:32867 (L2VNI 10100) *>l[2]:[0]:[0]:[48]:[0021.969a.0301]:[0]:[0.0.0.0]/216 198.18.1.11 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[0]:[0.0.0.0]/216 198.18.1.21 100 0 i *>l[2]:[0]:[0]:[48]:[0021.969a.0301]:[32]:[192.168.1.1]/272 198.18.1.11 100 32768 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 0 i *>l[3]:[0]:[32]:[198.18.1.11]/88 198.18.1.11 100 32768 i *>i[3]:[0]:[32]:[198.18.1.21]/88 198.18.1.21 100 0 i Route Distinguisher: 172.16.1.1:33067 (L2VNI 10300) *>l[2]:[0]:[0]:[48]:[0021.963d.6e01]:[0]:[0.0.0.0]/216 198.18.1.11 100 32768 i *>l[2]:[0]:[0]:[48]:[0021.963d.6e01]:[32]:[192.168.3.1]/272 198.18.1.11 100 32768 i *>l[3]:[0]:[32]:[198.18.1.11]/88 198.18.1.11 100 32768 i Route Distinguisher: 172.16.2.1:32867 *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[0]:[0.0.0.0]/216 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 0 i *>i[3]:[0]:[32]:[198.18.1.21]/88 198.18.1.21 100 0 i Route Distinguisher: 172.16.2.1:32967 *>i[2]:[0]:[0]:[48]:[0021.9642.5f01]:[32]:[192.168.2.1]/272 198.18.1.21 100 0 i Route Distinguisher: 172.16.1.1:3 (L3VNI 50001) *>i[2]:[0]:[0]:[48]:[0021.9642.5f01]:[32]:[192.168.2.1]/272 198.18.1.21 100 0 i *>i[2]:[0]:[0]:[48]:[0021.969f.c701]:[32]:[192.168.1.2]/272 198.18.1.21 100 0 i
MAC アドレステーブル
Cisco 公式 / NX-OSv 9000 Guide / NX-OSv 9000 Software Functionality の下の方に NX-OSv 9000 Feature UI/CLI Difference From Hardware Platform
ってのがあって、show mac addr
とかその辺は代わりにこのコマンドを使え、とあったので仮想版ではこれで。
anycast gateway(20:20:00:00:00:aa
) のエントリ表示がおかしいのはご愛敬ということで。
torsw101a# show system internal l2fwder mac Legend: * - primary entry, G - Gateway MAC, (R) - Routed MAC, O - Overlay MAC age - seconds since last seen,+ - primary entry using vPC Peer-Link, (T) - True, (F) - False, C - ControlPlane MAC VLAN MAC Address Type age Secure NTFY Ports ---------+-----------------+--------+---------+------+----+------------------ G 3901 0021.960f.f307 static - F F sup-eth1(R) G 100 0021.960f.f307 static - F F sup-eth1(R) * 100 0021.969f.c701 static - F F (0x47000001) nve-peer1 198.18. G 300 0021.960f.f307 static - F F sup-eth1(R) * 100 0021.969a.0301 dynamic 00:02:55 F F Eth1/1 * 300 0021.963d.6e01 dynamic 00:03:06 F F Eth1/2 1 1 -20:20:00:00:00:aa - 1
torsw201a# show system internal l2fwder mac Legend: * - primary entry, G - Gateway MAC, (R) - Routed MAC, O - Overlay MAC age - seconds since last seen,+ - primary entry using vPC Peer-Link, (T) - True, (F) - False, C - ControlPlane MAC VLAN MAC Address Type age Secure NTFY Ports ---------+-----------------+--------+---------+------+----+------------------ G 100 0021.9643.7607 static - F F sup-eth1(R) * 200 0021.9642.5f01 dynamic 00:01:03 F F Eth1/2 * 100 0021.969f.c701 dynamic 00:03:40 F F Eth1/1 G 200 0021.9643.7607 static - F F sup-eth1(R) * 100 0021.969a.0301 static - F F (0x47000001) nve-peer1 198.18. 1 1 -20:20:00:00:00:aa - 1
MAC アドレステーブル(EVPN 学習観点)
Seq No
があるってことは MAC Mobility Extended Community
が使えるんじゃないのか!?(説明放棄)
torsw101a# show l2route evpn mac all Flags -(Rmac):Router MAC (Stt):Static (L):Local (R):Remote (V):vPC link (Dup):Duplicate (Spl):Split (Rcv):Recv (AD):Auto-Delete(D):Del Pending (S):Stale (C):Clear (Ps):Peer Sync (O):Re-Originated Topology Mac Address Prod Flags Seq No Next-Hops ----------- -------------- ------ ------------- ---------- ---------------- 100 0021.969a.0301 Local L, 0 Eth1/1 100 0021.969f.c701 BGP SplRcv 0 198.18.1.21 300 0021.963d.6e01 Local L, 0 Eth1/2 3901 0021.9643.7607 VXLAN Rmac 0 198.18.1.21
torsw201a# show l2route evpn mac all Flags -(Rmac):Router MAC (Stt):Static (L):Local (R):Remote (V):vPC link (Dup):Duplicate (Spl):Split (Rcv):Recv (AD):Auto-Delete(D):Del Pending (S):Stale (C):Clear (Ps):Peer Sync (O):Re-Originated Topology Mac Address Prod Flags Seq No Next-Hops ----------- -------------- ------ ------------- ---------- ---------------- 100 0021.969a.0301 BGP SplRcv 0 198.18.1.11 100 0021.969f.c701 Local L, 0 Eth1/1 200 0021.9642.5f01 Local L, 0 Eth1/2 3901 0021.960f.f307 VXLAN Rmac 0 198.18.1.11
VRF の ARP テーブル
VxLAN や EVPN は関係ないですが。
なお AgeOut しそうになると、自発的に Nexus9000v が ARP request をノードに投げて、reply があったら AgeOut させないという(割とよくある)動きをしていました。
また、自身の配下にあるノードの分しか見えません。
torsw101a# show ip arp vrf VRF001 Flags: * - Adjacencies learnt on non-active FHRP router + - Adjacencies synced via CFSoE # - Adjacencies Throttled for Glean CP - Added via L2RIB, Control plane Adjacencies PS - Added via L2RIB, Peer Sync RO - Dervied from L2RIB Peer Sync Entry D - Static Adjacencies attached to down interface IP ARP Table for context VRF001 Total number of entries: 2 Address Age MAC Address Interface Flags 192.168.3.1 00:02:36 0021.963d.6e01 Vlan300 192.168.1.1 00:02:24 0021.969a.0301 Vlan100
torsw201a# show ip arp vrf VRF001 Flags: * - Adjacencies learnt on non-active FHRP router + - Adjacencies synced via CFSoE # - Adjacencies Throttled for Glean CP - Added via L2RIB, Control plane Adjacencies PS - Added via L2RIB, Peer Sync RO - Dervied from L2RIB Peer Sync Entry D - Static Adjacencies attached to down interface IP ARP Table for context VRF001 Total number of entries: 2 Address Age MAC Address Interface Flags 192.168.1.2 00:00:07 0021.969f.c701 Vlan100 192.168.2.1 00:02:31 0021.9642.5f01 Vlan200
VRF のルーティングテーブル(IPv4)
EVPN の MAC-IP を NLRI Type 2 でやりとりしているので、ホスト単位の経路情報になってます。
torsw101a# show ip route vrf VRF001 IP Route Table for VRF "VRF001" '*' denotes best ucast next-hop '**' denotes best mcast next-hop '[x/y]' denotes [preference/metric] '%<string>' in via output denotes VRF <string> 192.168.1.0/24, ubest/mbest: 1/0, attached *via 192.168.1.254, Vlan100, [0/0], 1d06h, direct 192.168.1.1/32, ubest/mbest: 1/0, attached *via 192.168.1.1, Vlan100, [190/0], 1d06h, hmm 192.168.1.2/32, ubest/mbest: 1/0 *via 198.18.1.21%default, [200/0], 1d06h, bgp-64512, internal, tag 64512 (evpn) segid: 50001 tunnelid: 0xc6 120115 encap: VXLAN 192.168.1.254/32, ubest/mbest: 1/0, attached *via 192.168.1.254, Vlan100, [0/0], 1d06h, local 192.168.2.1/32, ubest/mbest: 1/0 *via 198.18.1.21%default, [200/0], 1d06h, bgp-64512, internal, tag 64512 (evpn) segid: 50001 tunnelid: 0xc6 120115 encap: VXLAN 192.168.3.0/24, ubest/mbest: 1/0, attached *via 192.168.3.254, Vlan300, [0/0], 1d06h, direct 192.168.3.1/32, ubest/mbest: 1/0, attached *via 192.168.3.1, Vlan300, [190/0], 1d06h, hmm 192.168.3.254/32, ubest/mbest: 1/0, attached *via 192.168.3.254, Vlan300, [0/0], 1d06h, local
torsw201a# show ip route vrf VRF001 IP Route Table for VRF "VRF001" '*' denotes best ucast next-hop '**' denotes best mcast next-hop '[x/y]' denotes [preference/metric] '%<string>' in via output denotes VRF <string> 192.168.1.0/24, ubest/mbest: 1/0, attached *via 192.168.1.254, Vlan100, [0/0], 1d21h, direct 192.168.1.1/32, ubest/mbest: 1/0 *via 198.18.1.11%default, [200/0], 1d06h, bgp-64512, internal, tag 64512 (evpn) segid: 50001 tunnelid : 0xc612010b encap: VXLAN 192.168.1.2/32, ubest/mbest: 1/0, attached *via 192.168.1.2, Vlan100, [190/0], 1d11h, hmm 192.168.1.254/32, ubest/mbest: 1/0, attached *via 192.168.1.254, Vlan100, [0/0], 1d21h, local 192.168.2.0/24, ubest/mbest: 1/0, attached *via 192.168.2.254, Vlan200, [0/0], 1d09h, direct 192.168.2.1/32, ubest/mbest: 1/0, attached *via 192.168.2.1, Vlan200, [190/0], 1d06h, hmm 192.168.2.254/32, ubest/mbest: 1/0, attached *via 192.168.2.254, Vlan200, [0/0], 1d09h, local 192.168.3.1/32, ubest/mbest: 1/0 *via 198.18.1.11%default, [200/0], 1d06h, bgp-64512, internal, tag 64512 (evpn) segid: 50001 tunnelid : 0xc612010b encap: VXLAN
通信・パケット確認
Cisco 公式 / Cisco Programmable Fabric with VXLAN BGP EVPN Configuration Guide / Chapter: Unicast Forwarding に色々なパターンのフォワーディング動作が書いてあるので、それと見比べながら。
node11(VLAN 100) node21(VLAN 100) 通信 (via L2VNI)
各ノードで $ sudo ip n flush dev ens4
で ARP テーブル flush した上で
kotetsu@node11:~$ ping 192.168.1.2 PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data. 64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=24.5 ms 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=7.11 ms 64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=7.05 ms
kotetsu@node11:~$ ip n show dev ens4 192.168.1.2 lladdr 00:21:96:9f:c7:01 STALE 192.168.1.254 lladdr 20:20:00:00:00:aa STALE
kotetsu@node21:~$ ip n show dev ens4 192.168.1.1 lladdr 00:21:96:9a:03:01 STALE 192.168.1.254 lladdr 20:20:00:00:00:aa STALE
node11 からの ARP request は torsw101a が L2 VNI 10100 で VxLAN カプセル化して Ingress Replication (外側の IP src/dst は torsw[12]01a の loopback1)
node11 からの ICMP Echo Request は単に L2 VNI 10100 で VxLAN カプセル化されたやつ
node11(VLAN 100) node22(VLAN 200) 通信 (via L3VNI)
各ノードで $ sudo ip n flush dev ens4
で ARP テーブル flush した上で
kotetsu@node11:~$ ping 192.168.2.1 PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data. 64 bytes from 192.168.2.1: icmp_seq=1 ttl=62 time=22.1 ms 64 bytes from 192.168.2.1: icmp_seq=2 ttl=62 time=9.69 ms 64 bytes from 192.168.2.1: icmp_seq=3 ttl=62 time=12.3 ms 64 bytes from 192.168.2.1: icmp_seq=4 ttl=62 time=8.81 ms
kotetsu@node11:~$ ip n show dev ens4 192.168.1.2 FAILED 192.168.1.254 lladdr 20:20:00:00:00:aa STALE
kotetsu@node22:~$ ip n show dev ens4 192.168.2.254 lladdr 20:20:00:00:00:aa STALE
ARP Req は torsw101a
から torsw201a
に VNI 10100 で転送されるが、torsw201a
側が ARP Reply はしないでくれるので Dup った ARP Reply が node11
に戻ることはないです。(結果的には良いのですが、torsw201a
はどうやって巧く判断しているんだろう…)
node11 からの ICMP Echo Request は torsw101a が VRF 間の L3 VNI 50001 でカプセル化して転送
Control Plane パケット
かなり見飽きてきた感はありますが EVPN NLRI Type2 MAC/IP Advertisement route) Update を一つ見てみます。
今回、inter subnet 通信のために SVI を作っていますので、MAC アドレスだけでなくだけでなく IP アドレスもアドバタイズされています。
おしまい
Cisco Nexus9000v を KVM+GNS3 で動かす
最初に
やること/サマリ
本項では以下の話をします。
KVM+GNS3
環境でNexus9000v
を動かすところまで
話のポイントはこんなところ
GNS3
のMARKETPLACE
を使ったアプライアンスデプロイが楽Cisco Nexus 9000
シリーズの仮想版であるところのNexus9000v
は2017/08/16
現在、誰でもダウンロード可能なのでNX-OS
素振りが出来る- SW 版固有の機能制約はもちろんあり
- メモリ要件は Minimum 4GB, Recommended 8GB といういつも通りなやつ
まー Nexus9000v
のデプロイで UEFI
必須でタルかったので MARKETPLACE
に逃げた、というのが正直なところですが。
参考資料
思うに、こんなページをわざわざ見に来る人は、このリンクを見れば自分で問題なく出来そうだよね。
- Cisco Nexus 9000v 関連
- Cisco 公式 / Cisco Nexus 9000v Switch / Document
- Nexus9000全般のドキュメント
- Cisco だけあって、かなり豊富でしっかりしている
- Cisco 公式 / Cisco Nexus 9000v Switch / Download
- image ファイルダウンロードページ
- qcow2 など各種形式
2017/08/16
現在は個人アカウントでもダウンロード可能Download Options
をポチッて後は流れで
- Cisco 公式 / NX-OSv 9000 Guide
- Nexus9000v にフォーカスしたドキュメント
- HW版と比較した機能制限やリソース要件や各種Hypervisor向けのデプロイパラメータも書いてある
- Cisco 公式 / Cisco Nexus 9000v Switch / Document
- GNS3 関連
- GNS3 公式 / Cisco NX-OSv 9000 appliance
- GNS3 公式 / MARKETPLACE
- GNS3 公式 / Import GNS3 appliance
gns3a
形式のやつをインポートする、ESXi でいうところの ovf import 的な詳細手順- 画面キャプチャ満載で分かりやすい
環境情報
KVM 母艦と GNS3 は以下の感じで
$ uname -a Linux kvm01 4.4.0-79-generic #100-Ubuntu SMP Wed May 17 19:58:14 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS" $ virsh -v 1.3.1 $ qemu-system-x86_64 --version QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.14), Copyright (c) 2003-2008 Fabrice Bellard $ gns3 --version 2.0.2
Nexus9000v
は 2017/08/16
現在ダウンロード可能な最新の nxosv-final.7.0.3.I6.1.qcow2
で OVMF
は 2016/08/13
時点のビルド版ぽい(MARKETPLACE
で降ってきたのを使っただけ)
Nexus9000v デプロイ
Cisco サイトで OS ファイル取得
まあこの後のデプロイ手順は、ここで取得したファイルは使わないのですが…「俺は正当にこのファイルをダウンロードして使える権限を持っているんだな」って確認はしておきたいじゃないですか。
上記から qcow2 ファイルを取得(紐付いているのはハンペンAP1台だけの個人アカウントでも問題なく)して、チェックサムを確認
$ ll nxosv-final.7.0.3.I6.1.qcow2 -rw-r--r-- 1 kotetsu kotetsu 780402688 Aug 16 23:07 nxosv-final.7.0.3.I6.1.qcow2 $ sha512sum nxosv-final.7.0.3.I6.1.qcow2 93f2ffdcb230b3a0bcba4a120db4fcc752a1f91adfd911c9d11d3a725f0bbba7df40509ce896dcea45d33cbeacfa9fad9054678f91169ea1d684db8aadaa04cb nxosv-final.7.0.3.I6.1.qcow2
以下は 2017/08/16
時点でのダウンロード時画面キャプチャ
GNS3 の MARKETPLACE から Nexus9000v 用の テンプレートファイル取得
以下のリンクから DOWNLOAD TEMPLATE
をポチッて cisco-nxosv9k.gns3a
を取得します(完)
テンプレートファイルをインポート
いつも通り GNS3
の適当なプロジェクトを開いたら、先ほど取得した cisco-nxosv9k.gns3a
をインポートします。
GNS3
の File
-> Import appliance
を押して後は流れで…って感じですが、必要に応じて GNS3 公式 / Import GNS3 appliance に画面キャプチャ付の公式手順もございますので、そちらも合わせてご参照くださいませ。
これで GNS3
のテンプレートとして All devices
に Cisco NX-OSv 9000 7.0.3.I6.1
ができあがります。
手動でやる時には、以下あたりと睨めっこしながら試行錯誤して…というのがお決まりの流れだと思うんですが、そこをサボッたのがこの手順です。
- Cisco 公式 / NX-OSv 9000 Resource Requirements
- requirement 的なやつ
- Cisco 公式 / NX-OSv 9000 KVM-QEMU Support Information
- Cisco 公式 / NX-OSv 9000 NX-OSv 9000 Installation/Deployment
- 各種Hypervisor向けインストール時パラメータ詳説
KVM
版だとqemu-system-x86_64
に必要なパラメータが懇切丁寧に記載されている
ちゃんと動くお手本パラメータとして使う、ってのもありかもですね。
テンプレートからデプロイ~起動
いつも通りにテンプレート(all devices
)からD&Dでデプロイします。
なお、GNS3 MARKETPLACE
から取得したテンプレートは前述の公式パラメータに完全に沿ったものになっていますので、メモリを 4GB に減らすなり用途に応じたチューニングはお好きなように。
$ ps aux | grep [N]X-OS root 17924 12.7 1.1 9240844 367620 pts/12 Sl+ 02:26 0:05 /usr/bin/qemu-system-x86_64 -name CiscoNX-OSv90007.0.3.I6.1-1 -m 8096M -smp cpus=2 -enable-kvm -machine smm=off -boot order=c -bios /home/kotetsu/GNS3/images/QEMU/OVMF-20160813.fd -device ahci,id=ahci0,bus=pci.0 -drive file=/home/kotetsu/GNS3/projects/700/project-files/qemu/f8111e6a-9fd1-4f1b-9fd6-a3c9a42b0ff3/hda_disk.qcow2,if=none,id=drive-sata-disk0,index=0,media=disk -device ide-drive,drive=drive-sata-disk0,bus=ahci0.0,id=drive-sata-disk0 -uuid f8111e6a-9fd1-4f1b-9fd6-a3c9a42b0ff3 -serial telnet:127.0.0.1:5004,server,nowait -monitor tcp:127.0.0.1:54313,server,nowait -net none -device e1000,mac=00:21:96:0f:f3:00,netdev=gns3-0 -netdev socket,id=gns3-0,udp=127.0.0.1:10019,localaddr=0.0.0.0:10018 -device e1000,mac=00:21:96:0f:f3:01,netdev=gns3-1 -netdev socket,id=gns3-1,udp=127.0.0.1:10021,localaddr=0.0.0.0:10020 -device e1000,mac=00:21:96:0f:f3:02,netdev=gns3-2 -netdev socket,id=gns3-2,udp=127.0.0.1:10023,localaddr=0.0.0.0:10022 -device e1000,mac=00:21:96:0f:f3:03,netdev=gns3-3 -netdev socket,id=gns3-3,udp=127.0.0.1:10025,localaddr=0.0.0.0:10024 -device e1000,mac=00:21:96:0f:f3:04,netdev=gns3-4 -netdev socket,id=gns3-4,udp=127.0.0.1:10027,localaddr=0.0.0.0:10026 -device e1000,mac=00:21:96:0f:f3:05,netdev=gns3-5 -netdev socket,id=gns3-5,udp=127.0.0.1:10029,localaddr=0.0.0.0:10028 -device e1000,mac=00:21:96:0f:f3:06,netdev=gns3-6 -netdev socket,id=gns3-6,udp=127.0.0.1:10031,localaddr=0.0.0.0:10030 -device e1000,mac=00:21:96:0f:f3:07,netdev=gns3-7 -netdev socket,id=gns3-7,udp=127.0.0.1:10033,localaddr=0.0.0.0:10032 -device e1000,mac=00:21:96:0f:f3:08,netdev=gns3-8 -netdev socket,id=gns3-8,udp=127.0.0.1:10035,localaddr=0.0.0.0:10034 -device e1000,mac=00:21:96:0f:f3:09,netdev=gns3-9 -netdev socket,id=gns3-9,udp=127.0.0.1:10037,localaddr=0.0.0.0:10036 -nographic
んで、起動してコンソールを見守ると、以下のように ZTP ライクなものが走りだします
2017 Aug 16 17:29:15 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - USB Initializing Success 2017 Aug 16 17:29:15 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - USB disk not detected 2017 Aug 16 17:29:15 switch %$ VDC-1 %$ last message repeated 1 time 2017 Aug 16 17:29:15 switch %$ VDC-1 %$ %POAP-2-POAP_DHCP_DISCOVER_START: [90SNLUQJ25I-00:21:96:0F:F3:07] - POAP DHCP Discover phase started 2017 Aug 16 17:29:16 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - Invalid DHCP OFFER from 0.0.0.0: Missing Script Server information 2017 Aug 16 17:29:16 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - Invalid DHCP OFFER from 0.0.0.0: Missing Script Name 2017 Aug 16 17:29:20 switch %$ VDC-1 %$ %ASCII-CFG-2-CONF_CONTROL: System ready 2017 Aug 16 17:29:20 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - Invalid DHCP OFFER from 0.0.0.0: Missing Script Server information 2017 Aug 16 17:29:20 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - Invalid DHCP OFFER from 0.0.0.0: Missing Script Name 2017 Aug 16 17:29:26 switch %$ VDC-1 %$ %POAP-2-POAP_FAILURE: [90SNLUQJ25I-00:21:96:0F:F3:07] - POAP DHCP discover phase failed 2017 Aug 16 17:29:38 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - USB Initializing Success 2017 Aug 16 17:29:38 switch %$ VDC-1 %$ %POAP-2-POAP_INFO: [90SNLUQJ25I-00:21:96:0F:F3:07] - USB disk not detected
ひたすらループするので、以下の出力で y
して止めて
Abort Auto Provisioning and continue with normal setup ?(yes/no)[n]: y Disabling POAP
admin
ユーザ用のパスワード設定とかを対話でやると、初期ログイン可能になります。
Abort Auto Provisioning and continue with normal setup ?(yes/no)[n]: y Disabling POAP ---- System Admin Account Setup ---- Do you want to enforce secure password standard (yes/no) [y]: Enter the password for "admin": Wrong Password, Reason: [Length should be at least 8 characters] Invalid admin password. Enter the password for "admin": Confirm the password for "admin": ---- Basic System Configuration Dialog VDC: 1 ---- This setup utility will guide you through the basic configuration of the system. Setup configures only enough connectivity for management of the system. Please register Cisco Nexus9000 Family devices promptly with your supplier. Failure to register may affect response times for initial service calls. Nexus9000 devices must be registered to receive entitled support services. Press Enter at anytime to skip a dialog. Use ctrl-c at anytime to skip the remaining dialogs. Would you like to enter the basic configuration dialog (yes/no): 2017 Aug 16 17:33:45 switch %$ VDC-1 %$ %ACLQOS-SLOT1-2-ACLQOS_FAILED: ACLQOS failure: TCAM region is not configured for feature QoS class IPv4 direction ingress. Please configure TCAM region Ingress COPP [copp] and retry the command. Error: There was an error executing atleast one of the command Please verify the following log for the command execution errors. TCAM region is not configured. Please configure TCAM region and retry the command User Access Verification User Access Verification login: admin Password: Cisco NX-OS Software Copyright (c) 2002-2017, Cisco Systems, Inc. All rights reserved. NX-OSv9K software ("NX-OSv9K Software") and related documentation, files or other reference materials ("Documentation") are the proprietary property and confidential information of Cisco Systems, Inc. ("Cisco") and are protected, without limitation, pursuant to United States and International copyright and trademark laws in the applicable jurisdiction which provide civil and criminal penalties for copying or distribution without Cisco's authorization. Any use or disclosure, in whole or in part, of the NX-OSv9K Software or Documentation to any third party for any purposes is expressly prohibited except as otherwise authorized by Cisco in writing. The copyrights to certain works contained herein are owned by other third parties and are used and distributed under license. Some parts of this software may be covered under the GNU Public License or the GNU Lesser General Public License. A copy of each such license is available at http://www.gnu.org/licenses/gpl.html and http://www.gnu.org/licenses/lgpl.html *************************************************************************** * NX-OSv9K is strictly limited to use for evaluation, demonstration * * and NX-OS education. Any use or disclosure, in whole or in part of * * the NX-OSv9K Software or Documentation to any third party for any * * purposes is expressly prohibited except as otherwise authorized by * * Cisco in writing. * *************************************************************************** switch# switch# show ver Cisco Nexus Operating System (NX-OS) Software TAC support: http://www.cisco.com/tac Documents: http://www.cisco.com/en/US/products/ps9372/tsd_products_support_serie s_home.html Copyright (c) 2002-2017, Cisco Systems, Inc. All rights reserved. The copyrights to certain works contained herein are owned by other third parties and are used and distributed under license. Some parts of this software are covered under the GNU Public License. A copy of the license is available at http://www.gnu.org/licenses/gpl.html. NX-OSv9K is a demo version of the Nexus Operating System Software BIOS: version NXOS: version 7.0(3)I6(1) BIOS compile time: NXOS image file is: bootflash:///nxos.7.0.3.I6.1.bin NXOS compile time: 5/16/2017 22:00:00 [05/17/2017 06:21:28] Hardware cisco NX-OSv Chassis with 8062148 kB of memory. Processor Board ID 90SNLUQJ25I Device name: switch bootflash: 3509454 kB Kernel uptime is 0 day(s), 19 hour(s), 48 minute(s), 5 second(s) Last reset Reason: Unknown System version: Service: plugin Core Plugin, Ethernet Plugin Active Package(s):
ほい、お疲れ様でしたー。
bootイメージ設定
Cisco 公式 / Troubleshooting the NX-OSv 9000 / How to prevent VM from dropping into “loader >” prompt にあるように、起動イメージを忘れずに設定しないと次回起動時に loader
で止まってしまいますよ、って話
初期状態は以下なので
switch# show boot Current Boot Variables: sup-1 NXOS variable not set No module boot variable set Boot Variables on next reload: sup-1 NXOS variable not set No module boot variable set switch# dir bootflash: 4096 Aug 16 17:27:42 2017 .rpmstore/ 4096 Aug 16 17:27:53 2017 .swtam/ 38575 Aug 16 17:32:16 2017 20170816_172847_poap_26000_init.log 759941120 May 17 06:46:25 2017 nxos.7.0.3.I6.1.bin 0 Aug 16 17:35:04 2017 platform-sdk.cmd 4096 Aug 16 17:28:44 2017 scripts/ 4096 Aug 16 17:28:45 2017 virt_strg_pool_bf_vdc_1/ 4096 Aug 16 17:28:06 2017 virtual-instance/ 59 Aug 16 17:27:57 2017 virtual-instance.conf Usage for bootflash://sup-local 1158098944 bytes used 2379120640 bytes free 3537219584 bytes total
以下のように boot イメージを指定しておきましょう。
switch# configure terminal Enter configuration commands, one per line. End with CNTL/Z. switch(config)# switch(config)# boot nxos nxos.7.0.3.I6.1.bin Performing image verification and compatibility check, please wait.... switch(config)# switch(config)# end switch# switch# copy running-config startup-config [########################################] 100% Copy complete.
そーいや copy run start
はその内なくなる、みたいな話を IOS
時代に見たような気もするんですが、どうなんでしたっけ…。
ともかく、これで再起動してもちゃんと OS が読み込まれます。reload
でも実行して、動作確認しておきましょう。
switch# show boot Current Boot Variables: sup-1 NXOS variable = bootflash:/nxos.7.0.3.I6.1.bin No module boot variable set Boot Variables on next reload: sup-1 NXOS variable = bootflash:/nxos.7.0.3.I6.1.bin No module boot variable set
完
お手軽手順に逃げてインストールしただけなので、別に…
仮想版をユーザ制限なくダウンロードさせてもらったから言うわけじゃないですが、Nexus9000 はデータセンタスイッチとしてはなかなか良さげですよ!!