20
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cisco Systems JapanAdvent Calendar 2024

Day 25

CML2.8 Free Tierを使いこなす: IOLを用いてEVPN-VXLANを検証してみた

Posted at

はじめに

本記事は、シスコの有志による Cisco Systems Japan Advent Calendar 2024 シリーズ 2 の25日目として投稿しています。

2017年版: https://qiita.com/advent-calendar/2017/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2019年版: https://qiita.com/advent-calendar/2019/cisco
2020年版: https://qiita.com/advent-calendar/2020/cisco
2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2
2021年版: https://qiita.com/advent-calendar/2021/cisco
2021年版(2枚目): https://qiita.com/advent-calendar/2021/cisco2
2022年版(1,2): https://qiita.com/advent-calendar/2022/cisco
2023年版: https://qiita.com/advent-calendar/2023/cisco
2024年版: https://qiita.com/advent-calendar/2024/cisco

先日、Cisco Modeling Labs(CML)の最新バージョンCML 2.8がリリースされました。今回のリリースでは無償版(Free Tier)が公開され、より多くの方々がCMLの魅力を体験できるようになりました。

昨年、@kykanno さんの記事では、CML 2を用いてベータ版 Catalyst 9000vでEVPN VXLANの設定と検証を行う方法が紹介されました。本記事ではその内容の続編として、CML2でIOL-L2を使用してEVPN VXLANの設定と検証を行い、さらにAnsibleを用いてEVPN VXLANラボ展開の自動化を実現します。これにより、CML 2.8 Free Tierの可能性を最大限に引き出したいと思います。

事前準備

CML2.8 Free Tierのインストール

@ecodrive さんの記事ではCML2.8 Free Tierのインストール手順について詳しく説明されていますので、ぜひご参照ください

CML2.8 Free Tierサービスの起動

以下のサービスを起動します。

sudo systemctl enable --now ssh.service
sudo systemctl enable --now virl2-patty.service

Ansible実行環境の準備

今回、EVPN VXLAN Farbic構築の自動化を実現するため、Ansibleを使用します。

下記に、自動化シナリオで使用されるトポロジーを示します。

ansible_lab_topology

今回使用するAnsible playbookなどについては trustywolf/cml-free-evpn-vxlan をご参照ください。

実際のCML2のトポロジー図はこちらです:

image.png

AnsibleでCML2ラボを自動展開するため、手動での操作は不要です。

Ansible実行用のPCでは、以下の操作を実行し、実行環境の初期化を行います。

git clone https://github.com/trustywolf/cml-free-evpn-vxlan.git

cd cml-free-evpn-vxlan/dag

python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txt

ansible-galaxy collection install cisco.cml

CML2ラボの自動展開

ラボを自動展開するため、以下のPlaybookを実行します。

ansible-playbook cisco.cml.build -e wait='yes' \
-e cml_host=<cml_host> \
-e cml_username=<cml_username> \
-e cml_password=<cml_password> \
-e cml_lab="cml-iol-evpn-vxlan" \
-e cml_lab_file="{{ lookup('env', 'PWD') }}/../cml-iol-evpn-vxlan.yaml"

下図に示すように、ラボが展開され、Power onになりました。

image.png

同様に、ラボを削除する際に、以下のPlaybookを実行します:

ansible-playbook cisco.cml.clean -t erase \
-e cml_host=<cml_host> \
-e cml_username=<cml_username> \
-e cml_password=<cml_password> \
-e cml_lab="cml-iol-evpn-vxlan" \
-e cml_lab_file="{{ lookup('env', 'PWD') }}/../cml-iol-evpn-vxlan.yaml"

下図に示すように、ラボが削除されました。

image.png

次に、Ansible CML Collectionのdynamic inventory pluginの使用し、ラボのinventory情報を取得します:

touch cml.yml
plugin: cisco.cml.cml_inventory
host: <cml_host>
username: <cml_username>
password: <cml_password>
validate_certs: "no"
lab: cml-iol-evpn-vxlan
group_tags: spine, leaf, host
% ansible-playbook cisco.cml.inventory -i cml.yml --limit=spine,leaf,host
SSL Verification disabled
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details

PLAY [cml_hosts] *********************************************************************************************************************************************************************

TASK [debug] *************************************************************************************************************************************************************************
ok: [S1] => {
    "msg": "Node: S1(ioll2-xe), State: BOOTED, Address: cml-free.example.com:2201"
}
ok: [S2] => {
    "msg": "Node: S2(ioll2-xe), State: BOOTED, Address: cml-free.example.com:2202"
}
ok: [L1] => {
    "msg": "Node: L1(ioll2-xe), State: BOOTED, Address: cml-free.example.com:2203"
}
ok: [L2] => {
    "msg": "Node: L2(ioll2-xe), State: BOOTED, Address: cml-free.example.com:2204"
}
ok: [H] => {
    "msg": "Node: H(ioll2-xe), State: BOOTED, Address: cml-free.example.com:2205"
}

PLAY RECAP ***************************************************************************************************************************************************************************
H                          : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
L1                         : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
L2                         : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
S1                         : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
S2                         : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

最後に、疎通確認を行います:

% ansible -i cml.yml cml_hosts -m ping --limit=spine,leaf,host
SSL Verification disabled
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
S2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
L2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
H | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
S1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
L1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

ラボの各ノードがAnsibleのインベントリに追加され、疎通できるようになりました。
しかし、以下のコマンドを実行すると、

% ansible -i cml.yml cml_hosts --limit=spine,leaf -m cisco.ios.ios_command -a "commands='show ip int b'"
SSL Verification disabled
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
S2 | FAILED! => {
    "changed": false,
    "msg": "ssh connection failed: ssh connect failed: Permission denied"
}
S1 | FAILED! => {
    "changed": false,
    "msg": "ssh connection failed: ssh connect failed: Permission denied"
}
L1 | FAILED! => {
    "changed": false,
    "msg": "ssh connection failed: ssh connect failed: Permission denied"
}
L2 | FAILED! => {
    "changed": false,
    "msg": "ssh connection failed: ssh connect failed: Permission denied"
}

SSH接続不可のエラーが出てしまいました。今回のラボ構成では、外部からラボのノードへSSH接続するため、PATty Toolを使用しPATの変換を行っていましたが、これが原因と考えられます。そこで、PAT変換の設定を削除し、CMLサーバをJump Hostとして利用することで、Ansibleからラボのノードへ接続を実現します。

group_vars/all.ymlに以下の内容を追加します:

ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q <cml_username>@<cml_host> -p 1122"'

疎通確認およびAnsibleの実行確認を行います:

% ansible -i inventory.yml all -m ping
S1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
L2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
L1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
S2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
% ansible -i inventory.yml all -m cisco.ios.ios_command -a "commands='show cdp nei'" 
L1 | SUCCESS => {
    "changed": false,
    "stdout": [
        "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge\n                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, \n                  D - Remote, C - CVTA, M - Two-port Mac Relay \n\nDevice ID        Local Intrfce     Holdtme    Capability  Platform  Port ID\nH.lab            Eth 0/3           152             R S I  Linux Uni Eth 0/1\nS2.lab           Eth 0/2           178             R S I  Linux Uni Eth 0/1\nS1.lab           Eth 0/1           154             R S I  Linux Uni Eth 0/1\n\nTotal cdp entries displayed : 3"
    ],
    "stdout_lines": [
        [
            "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge",
            "                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, ",
            "                  D - Remote, C - CVTA, M - Two-port Mac Relay ",
            "",
            "Device ID        Local Intrfce     Holdtme    Capability  Platform  Port ID",
            "H.lab            Eth 0/3           152             R S I  Linux Uni Eth 0/1",
            "S2.lab           Eth 0/2           178             R S I  Linux Uni Eth 0/1",
            "S1.lab           Eth 0/1           154             R S I  Linux Uni Eth 0/1",
            "",
            "Total cdp entries displayed : 3"
        ]
    ]
}
L2 | SUCCESS => {
    "changed": false,
    "stdout": [
        "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge\n                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, \n                  D - Remote, C - CVTA, M - Two-port Mac Relay \n\nDevice ID        Local Intrfce     Holdtme    Capability  Platform  Port ID\nH.lab            Eth 0/3           174             R S I  Linux Uni Eth 0/2\nS2.lab           Eth 0/2           153             R S I  Linux Uni Eth 0/2\nS1.lab           Eth 0/1           154             R S I  Linux Uni Eth 0/2\n\nTotal cdp entries displayed : 3"
    ],
    "stdout_lines": [
        [
            "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge",
            "                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, ",
            "                  D - Remote, C - CVTA, M - Two-port Mac Relay ",
            "",
            "Device ID        Local Intrfce     Holdtme    Capability  Platform  Port ID",
            "H.lab            Eth 0/3           174             R S I  Linux Uni Eth 0/2",
            "S2.lab           Eth 0/2           153             R S I  Linux Uni Eth 0/2",
            "S1.lab           Eth 0/1           154             R S I  Linux Uni Eth 0/2",
            "",
            "Total cdp entries displayed : 3"
        ]
    ]
}
S2 | SUCCESS => {
    "changed": false,
    "stdout": [
        "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge\n                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, \n                  D - Remote, C - CVTA, M - Two-port Mac Relay \n\nDevice ID        Local Intrfce     Holdtme    Capability  Platform  Port ID\nL1.lab           Eth 0/1           152             R S I  Linux Uni Eth 0/2\nL2.lab           Eth 0/2           141             R S I  Linux Uni Eth 0/2\n\nTotal cdp entries displayed : 2"
    ],
    "stdout_lines": [
        [
            "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge",
            "                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, ",
            "                  D - Remote, C - CVTA, M - Two-port Mac Relay ",
            "",
            "Device ID        Local Intrfce     Holdtme    Capability  Platform  Port ID",
            "L1.lab           Eth 0/1           152             R S I  Linux Uni Eth 0/2",
            "L2.lab           Eth 0/2           141             R S I  Linux Uni Eth 0/2",
            "",
            "Total cdp entries displayed : 2"
        ]
    ]
}
S1 | SUCCESS => {
    "changed": false,
    "stdout": [
        "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge\n                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, \n                  D - Remote, C - CVTA, M - Two-port Mac Relay \n\nDevice ID        Local Intrfce     Holdtme    Capability  Platform  Port ID\nL1.lab           Eth 0/1           169             R S I  Linux Uni Eth 0/1\nL2.lab           Eth 0/2           164             R S I  Linux Uni Eth 0/1\n\nTotal cdp entries displayed : 2"
    ],
    "stdout_lines": [
        [
            "Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge",
            "                  S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone, ",
            "                  D - Remote, C - CVTA, M - Two-port Mac Relay ",
            "",
            "Device ID        Local Intrfce     Holdtme    Capability  Platform  Port ID",
            "L1.lab           Eth 0/1           169             R S I  Linux Uni Eth 0/1",
            "L2.lab           Eth 0/2           164             R S I  Linux Uni Eth 0/1",
            "",
            "Total cdp entries displayed : 2"
        ]
    ]
}

ご覧の通り、Ansible実行環境の整備が問題なく完了しました。

EVPN-VXLAN Farbicの自動構築

Underlayのプロビジョニング

ループバックインターフェースと物理インターフェースの設定、スパインおよびリーフデバイス間のIS-ISおよびPIMプロトコルの設定を行います。その結果、スパインとリーフスイッチ間で完全なIP到達性が確立され、アンダーレイネットワークがマルチキャストルーティングをサポートするようになります。

ラボの各ノードのUnderlay設定は以下のファイルにより定義されます:

% ls host_vars/node_vars/
L1.yml  L2.yml  S1.yml  S2.yml

以下のPlaybookを実行することで、preview_filesフォルダの下に<hostname>-underlay.txtのファイルが生成され、各ノードに適用するコンフィグを確認することが可能です。

ansible-playbook -i inventory.yml playbook_underlay_preview.yml
% ls preview_files/
L1-underlay.txt  L2-underlay.txt  S1-underlay.txt  S2-underlay.txt

各ファイルの内容を確認し、問題がない場合は、以下のPlaybookを実行することで、各ノードへコンフィグが適用されます。

ansible-playbook -i inventory.yml playbook_underlay_commit.yml

CMLの各ノードでshowコマンドを使用し、状態を確認します。

L1#show isis neighbors 

Tag UNDERLAY:
System Id       Type Interface     IP Address      State Holdtime Circuit Id
S1              L2   Et0/1         172.16.13.1     UP    22       02
S2              L2   Et0/2         172.16.23.2     UP    22       02

L1#show ip pim neighbor 
PIM Neighbor Table
Mode: B - Bidir Capable, DR - Designated Router, N - Default DR Priority,
      P - Proxy Capable, S - State Refresh Capable, G - GenID Capable,
      L - DR Load-balancing Capable
Neighbor          Interface                Uptime/Expires    Ver   DR
Address                                                            Prio/Mode
172.16.13.1       Ethernet0/1              00:00:57/00:01:16 v2    1 / S P G
172.16.23.2       Ethernet0/2              00:00:57/00:01:16 v2    1 / S P G

ご覧の通り、Underlayのプロビジョニングが無事完了しました。

Overlayのプロビジョニング

Overlay設定は以下のファイルにより定義されます:

% cat group_vars/overlay_db.yml

以下のPlaybookを実行することで、Overlay設定のチェックを行います:

% ansible-playbook -i inventory.yml playbook_yml_validation.yml

また、以下のPlaybookを実行することで、Overlay設定を投入する前に、各NodeのUnderlayのチェックを行います:

% ansible-playbook -i inventory.yml playbook_overlay_precheck.yml

ここで、version_license_checkのエラーが出ましたが、今回のラボ環境では特に影響がないため、無視しても問題ありません。

最後に、先ほどと同様に、各ノードへのコンフィグの確認および適用を行います。

% ansible-playbook -i inventory.yml playbook_overlay_preview.yml
% ls preview_files/ | grep overlay
L1-overlay.txt
L2-overlay.txt
S1-overlay.txt
S2-overlay.txt
% ansible-playbook -i inventory.yml playbook_overlay_commit.yml

アクセスポートのプロビジョニング

最後に、Leafスイッチのアクセスポートのプロビジョニングを行います。

アクセスポートの設定は、以下のファイルで定義されています。

% ls host_vars/access_intf/
L1.yml  L2.yml
% ansible-playbook -i inventory.yml playbook_access_add_preview.yml
% ansible-playbook -i inventory.yml playbook_access_add_commit.yml
% ls preview_files/ | grep add
L1-add-intf.txt
L2-add-intf.txt
% ansible-playbook -i inventory.yml playbook_access_add_commit.yml

これにより、2台のLeafスイッチのEthernet0/3ポートを、アクセスポートVLAN102に設定しました。

疎通確認

今回のラボでは、CML2.8 Free Tierの台数制限により、ホストを模擬する機器は1台しか用意できませんでした。そのため、ホスト模擬スイッチでVRFを使用することで、疑似的に2台のホストを作成します。

ホスト模擬スイッチに以下のコンフィグを投入します。

vrf definition H1
 !
 address-family ipv4
 exit-address-family
 !
 address-family ipv6
 exit-address-family
!
vrf definition H2
 !
 address-family ipv4
 exit-address-family
 !
 address-family ipv6
 exit-address-family
!
default interface Ethernet0/1
interface Ethernet0/1
 no switchport
 vrf forwarding H1
 ip address 10.1.102.201 255.255.255.0
 no shutdown
!
default interface Ethernet0/2
interface Ethernet0/2
 no switchport
 vrf forwarding H2
 ip address 10.1.102.202 255.255.255.0
 no shutdown
!
interface Ethernet0/3
shutdown
!
end

初期状態では、VRF H1 のARPテーブルには VRF 'H2'所属のEthernet0/2のアドレスとMACアドレスが存在しません。

H#show arp vrf H1
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  10.1.102.201            -   aabb.cc00.6210  ARPA   Ethernet0/1

pingコマンドで疎通確認を行います:

H#ping vrf H1 10.1.102.202 source Ethernet0/1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.1.102.202, timeout is 2 seconds:
Packet sent with a source address of 10.1.102.201 
.!!!!
Success rate is 80 percent (4/5), round-trip min/avg/max = 2/2/3 ms

pingで疎通確認後、VRF H1 のARPテーブルにはVRF 'H2'所属のEthernet0/2のアドレスとMACアドレスが無事に学習できました。

H#show arp vrf H1
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  10.1.102.201            -   aabb.cc00.6210  ARPA   Ethernet0/1
Internet  10.1.102.202            0   aabb.cc00.6220  ARPA   Ethernet0/1

これにより、EVPN-VXLAN Farbicの正常性確認ができました。

まとめ

本記事では、Cisco Modeling Labs (CML) 2.8 Free Tierを活用し、IOL-L2を用いたEVPN VXLANのラボ環境構築と、Ansibleによる自動化について解説しました。これらの手順を通して、CML 2.8 Free Tierのポテンシャルを最大限に引き出し、EVPN-VXLANラボの構築から自動化までの一連の流れを、実践的に学んでいただけると考えています。CML 2.8 Free Tier、EVPN-VXLAN、Ansibleに関心のある方々にとって、少しでも役立つ情報となれば幸いです。

参考資料

免責事項

本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。

20
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?