EC SONiC VS で EVPN BGP L2VNI -- ZTP 自動化編

## はじめに
### SONiC と ZTP
SONiCとZTPの関係をイメージとして以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/617745e8-d237-712d-f1a9-3041efeb3444.png)

ONIE (Open Network Install Environment) 搭載のスイッチの管理ポートなら、デフォルト上で DHCP Client 機能は有効となっています。もし DHCP サーバは事前に用意できた場合、スイッチ起動する際に ONIE と SONiC は DCHPから IP をゲットします。
ONIE と SONiC は、ハードウェア上の同じ物理的な管理ポートを使用しますが、ソフトウェア上では異なる役割を持ち、別々のもので考えればよいです。

本記事は、ONIE の方のイマージインストールを考えず、SONiC 上のコンフィグのみで検証します。

## 目標
以下のように初期状態の Spine-Leaf 構造を EVPN L2VNI に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/494ff0e2-812f-f118-2ec5-c831d07f3c78.png)


## 環境
- OS version: EC SONiC VS 202111版、VS の導入について、前回の記事で[SONiC VS 仮想スイッチを使ってみよう [Community/Edgecore]](https://qiita.com/cyo-chang/items/3f987d1b3e8303e40988) ご参考ください
- ESXi VMware
    - ゲスト OS：Ubuntu Linux (64 ビット)
## Topology
Clos 構造は、[EC SONiC VS で EVPN BGP L2VNI -- 設定編](https://qiita.com/cyo-chang/items/280df667a2ff63569de9) と同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/c7d7dcd1-ad50-6a30-0d0f-10aad96a36b0.png)

## 事前準備
- サーバ * 1
    - DHCP service
    - TFTP service
- mgmt switch * 1
- Spine * 2 & Leaf * 4
    以下の設定完了のコンフィグファイルを事前にデバイスから取得
    - `/etc/sonic/config_db.json`
    - `/etc/sonic/frr/frr.conf`

### DHCP / TFTP サーバ
DHCP / TFTP サーバを作って GNS3 にインポートするため、Ubuntu docker container から作成するのは一番早いかもしれません。手順は以下に参考
1. ESXi 上の Ubuntu Linux のターミナルを開く
1. DCHP/TFTP 用の ubuntu イメージを作成
    - `docker images`で既存のイメージを確認
    - `docker run -id <image id>` でコンテナを実行
    - `docker ps` で実行中のコンテナを確認する
    ![qiita_3_dhcp_server_docker.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/7cce0cff-8396-7dbe-8457-3ba85496b75d.png)
    - `docker exec -it <container id> bash `でコンテナに入る
    - 必要なパッケージをインストールする。DHCP/TFTP に必要なパッケージは以下となる。
    `apt update && apt install vim ssh openssh-client isc-dhcp-server tftpd-hpa tftp-hpa iproute2 iputils-ping tcpdump`
    - インストール完了後、`exit`でコンテナから離れる
    - 新しいコンテナのイメージをコミットする
    `docker stop <container id> `でイメージを停止させる
    `docker commit` で叩いたら、DCHP/TFTP用の ubuntu イメージを作成完了
    ![qiita_3_dhcp_server_docker1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/405f2314-83f4-629a-e6fb-b9783308df96.png)

1. GNS 上に、作った DCHP/TFTP 用の docker container を入れる
    - 手順：GNS3 → Edit → Preference → Dokcer → Docker containers → new
    `image list` 欄には、先程作った dhcp_tftp_server は出てくるはず
    ![qiita_3_dhcp_server_docker10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/71a8d17e-9cd0-954a-970f-42d83646dc9f.png)
    - 名前付けし、Adpterの数を 3 つにして、数個の「次へ」ボタンでって完了
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/d9b2351c-1d29-038c-e17f-a32a432b6bb6.png)
1. コンテナのネットワークインターフェースを設定
    - Topology に合わせて設定
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/694871ee-13f5-e26b-3c69-8dcea02ba663.png)
1. DHCP/TFTP サーバを起動する前の準備は完了

### mgmt switch
Spine *2 / Leaf *4 の管理ポートに接続する mgmt switch について、もう一個の EC SONiC VS を使用して設定します。
#### Config
```
sudo config vlan add 100
sudo config interface ip add Vlan100 10.10.0.1/24
sudo config vlan member add 100 Ethernet0 -u
sudo config vlan member add 100 Ethernet4 -u
sudo config vlan member add 100 Ethernet8 -u
sudo config vlan member add 100 Ethernet12 -u
sudo config vlan member add 100 Ethernet16 -u
sudo config vlan member add 100 Ethernet20 –u
sudo config vlan member add 100 Ethernet24 -u
```

### GNS3 で link up
Topology に合わせて以下のように作図します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/b4684c23-f7b9-bfff-6d15-69661d440154.png)

## ZTP JSON
ztp.json の書き方について、[SONiC 公式サイト](https://github.com/sonic-net/SONiC/blob/master/doc/ztp/ztp.md#31-ztp-json)にも参考できます。
本記事は以下のように記述します。
```
{
"ztp": {
  "01-download": {
    "files": [
      {
        "url": {
          "source": "tftp://10.10.0.5/frr/{$hostname}_frr.conf",
	        "destination": "/etc/sonic/frr/frr.conf"
        }
      }
    ]
  },
  "02-configdb-json": {
    "url": {
      "source": "tftp://10.10.0.5/configs/{$hostname}_config_db.json",
      "destination": "/etc/sonic/config_db.json"
    },
    "reboot-on-success": true
  }
}
}
```
## DHCP Server config
1. `vim /etc/default/isc-dhcp-server` で修正
DHCP サーバーがどのインターフェイスで DHCP リクエストを処理するかを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/df280a31-fc82-4e9d-d464-44fdd9db87da.png)
1. `vim /etc/dhcp/dhcpd.conf` で修正
```
default-lease-time 86400;
max-lease-time 86400;

shared-network ecsonic_gns3{
  allow client-updates;
  allow unknown-clients;

  subnet 10.10.0.0 netmask 255.255.255.0{
    option routers 10.10.0.1;
    option tftp-server-name "10.10.0.5";
    option subnet-mask 255.255.255.0;
    range 10.10.0.100 10.10.0.200;
    option broadcast-address 10.10.0.255;
    option domain-name-servers 8.8.8.8, 8.8.4.4;

    host spine-1{
      hardware ethernet 0c:86:bd:06:00:00;
      fixed-address 10.10.0.101;
      option bootfile-name "ztp/spine-1_ztp.json";
    }
    host spine-2{
      hardware ethernet 0c:86:3d:4f:00:00;
      fixed-address 10.10.0.102;
      option bootfile-name "ztp/spine-2_ztp.json";
    }
    host leaf-1{
      hardware ethernet 0c:78:59:ee:00:00;
      fixed-address 10.10.0.111;
      option bootfile-name "ztp/leaf-1_ztp.json";
    }
    host leaf-2{
      hardware ethernet 0c:02:b1:58:00:00;
      fixed-address 10.10.0.112;
      option bootfile-name "ztp/leaf-2_ztp.json";
    }
    host leaf-3{
      hardware ethernet 0c:90:a5:e8:00:00;
      fixed-address 10.10.0.113;
      option bootfile-name "ztp/leaf-3_ztp.json";
    }
    host leaf-4{
      hardware ethernet 0c:c5:da:7f:00:00;
      fixed-address 10.10.0.114;
      option bootfile-name "ztp/leaf-4_ztp.json";
    }
  }
}
```


`service isc-dhcp-server` でサービスを起動します。
![qiita_3_dhcp_server_docker-5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/2b3c41ca-bafa-0788-7072-dbf0a255a7cf.png)

## TFTP server 
Spine と Leafそれぞれの ztp.json、config_db.json、および frr.conf の設定ファイルは、`/tftp` ディレクトリにコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/8f359c79-3ad2-9397-6381-9e544627e63a.png)

`/etc/default/tftpd-hpa` で、コンフィグファイルの保存先を指定します。
![qiita_3_dhcp_server_docker-6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/ecf823e9-2ecb-c7c4-66d2-7182ad19069c.png)
`service tftpd-hpa`でサービスを起動します。
![qiita_3_dhcp_server_docker-8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/71c6e642-79e1-e3f7-2dde-a74b1f00d44a.png)

## ZTP を実行
`sudo config ztp run` で、ZTP プロセスできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/86dfe992-ca72-807c-92bd-8155b5cb870f.png)

`sudo config ztp run`を実行した後、ztp json と config ファイルをダウンロードするログです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/677ee860-a62c-f67b-0217-ad3f27917adc.png)

完了後、`show ztp --verbose` で ZTP プロセスの状態を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/2522eabc-cd9e-2f19-6b69-9d044789b34b.png)


実は、今年の福岡 JANOG53 でも、本記事の内容を Edgecore のブースで展示しました。DEMO 動画は以下でご参考いただければ幸いです。当時は、本記事と違って、純粋な BGP 環境でデモしました

<iframe width="560" height="315" src="https://www.youtube.com/embed/XVj1HErL_0I?si=840OzSM8FHE4xLLK" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

ちなみに、VS 上の ZTP 実行する時間は、おおよそ 6 分半ぐらいです。


# 最後に
ZTP を使用することで、GNS3 上の設定や展開を自動化することができました！今後 EVPN L2VNI だけではなく、L3VNI、MLAG、Multihoming などの環境も GNS3 で試したく、ZTP はそれぞれの運用開始の手間を軽減します。手元にはHWがない私にとって、とても重要な第一歩ですね。

# 参考
[Apresia 技術ブログ -- SONiC ZTPを仮想マシン環境で試してみた](https://www.apresiatac.jp/blog/202006042276/)
[[Enterprise SONiC] ZTP (Zero Touch Provisioning)](https://support.edge-core.com/hc/en-us/articles/9391323739417--Enterprise-SONiC-ZTP-Zero-Touch-Provisioning)
[Community SONiC -- Zero Touch Provisioning (ZTP)](https://github.com/sonic-net/SONiC/blob/master/doc/ztp/ztp.md#31-ztp-json)