いまどきのネットワークOSのお話

# はじめに
日頃、あまり目立たない割りに重要な役割を果たしているネットワークOSですが、利用環境や要求の変化、ハードウェア/ソフトウェア技術の進化に合わせて常にダイナミックに変化しながら進化を遂げています。

今回はCisco Nexus 9000シリーズで利用されているNX-OS(以下、NX-OSとはNexus9000/3000シリーズ、NX-OS 7.0(3)I2(1)以降のNX-OSを前提とします)を例として、いまどきのネットワークOSの話をしたいと思います。

# いまどきのNX-OSのアーキテクチャ(Nexus9000/3000シリーズ)

Nexus9000/3000シリーズ向けNX-OSの配布イメージは1つの配布イメージに統合されており、scp/sftp等でファイルをコピー後にインストール/アップグレードする事が可能となっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/215426/b69e505d-c066-b5ea-2caa-76f8e96d942e.png)
**Figure. NX-OS Architecture overview (Nexus9000/3000シリーズ(NX-OS 7.0(3)I2(1)以降))**

NX-OSの内部アーキテクチャーは上図の様なモジュラー型のアーキテクチャとなっており、内部データ構造のオブジェクト化とそれらを参照可能なオープンで多様なインターフェースの提供等、自由度が高くセキュアなアプリケーション環境を提供しやすく設計されています。

従来のIOSライクなCLIによる設定や運用は変わらず利用可能である事は当然として、その他に多種多様なAPIやインターフェースによりスイッチ内部や外部からコントロール可能な仕様となっています。

[参考資料]
[Cisco Nexus 9000 Series Switches: Integrate Programmability into Your Data Center](https://www.cisco.com/c/en/us/products/collateral/switches/nexus-9000-series-switches/white-paper-c11-733915.html)

# 多様なAPI/インターフェースの提供
- NX-OS CLI (VSH)

- Shells and Scripting
    - Bash
    - Guest Shell 2.3
    - Broadcom Shell (Broadcom ASIC採用プラットフォームのみ)
    - Python API
    - Scripting with Tcl
    - iPXE
    - Kernel Stack

- Applications
    - Third-Party Applications
    - Ansible
    - Puppet Agent
    - Using Chef Client with Cisco NX-OS 
    - NX-SDK

- NX-API
    - NX-API CLI
    - NX-API REST
    - NX-API Developer Sandbox

- Model-Driven Programmability
    - NETCONF Agent
    - RESTConf Agent
    - gRPC Agent
    - Dynamic Logger
    - Model-Driven Telemetry

[参考資料]
[Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x]
(https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/7-x/programmability/guide/b_Cisco_Nexus_9000_Series_NX-OS_Programmability_Guide_7x.html)


# NX-OS CLI(正式にはVSH、従来からあるIOSライクなCLI)

NX-OS CLIのコンソールに接続する方法としてはTelnet/SSH/Serial Consoleが選択できます。SSH/Serial ConsoleはデフォルトでEnableとなっていますが、telnetはセキュリティの観点で標準ではDisableになっています。

Telnetを利用したい場合は以下のとおり`feature`コマンドでTelnet機能を明示的に設定してEnableにする必要があります。

```
N93180YC-EX-01# conf t
N93180YC-EX-01(config)# feature telnet
N93180YC-EX-01(config)# copy running-config startup-config
```
※NX-OSでは設定を保存する為のコマンドである`write`コマンドは廃止されておりますので、`copy running-config startup-config`を利用する必要があります。

NX-OSではセキュリティや効率的なリソース活用の観点で標準機能以外はデフォルトでメモリー上に展開しない仕組みとなっています。(Linux Kernelで言うところのKLMのような考え方です)

従って、例えばSVIやOSPF/BGP等を利用したい場合、`feature`コマンドでそれらの機能を明示的に有効化しない限りCLIで設定が入らないようになっています。

```
N93180YC-EX-01# conf t
N93180YC-EX-01(config)# router ospf 1
                             ^
% Invalid command at '^' marker.
N93180YC-EX-01(config)# feature ospf
N93180YC-EX-01(config)# router ospf 1
```

NX-OS CLIから標準でPythonを呼び出す事もできます。

```
N93180YC-EX-01# python
Python 2.7.5 (default, Nov  5 2016, 04:39:52)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

つまり、購入した機材の箱を開けて物理設置/電源投入後にManagement用のIP addressをDHCP or Static IPで設定さえしてしまえば、Ansible等で設定をプロビジョニングすることが可能になります。

[参考資料]
[Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x (Chapter: Ansible)]
(https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/7-x/programmability/guide/b_Cisco_Nexus_9000_Series_NX-OS_Programmability_Guide_7x/b_Cisco_Nexus_9000_Series_NX-OS_Programmability_Guide_7x_chapter_011001.html)

[NX-OS developer landing page]
(https://developer.cisco.com/site/nx-os/docs/automation/configuration-management/index.gsp)

[Ansible NX-OS playbook examples on github]
(https://github.com/datacenter/Ansible-NXOS)

# Native shellとGuest shellの関係

Native shellとGuest shellの大きな違いはNX-OSのNative環境(Distribution: Wind River Linux 5)に対してダイレクトにアクセス可能な環境であるか、LXC上に構成されたCentOS7ベースで且つリソースへのアクセス制限がより行き届いた分離された環境であるのかの違いとなっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/215426/fef70a57-bfe2-43f4-1269-17888d01e4f9.png)
**Figure2. NX-OSにおける Native shell と Guest shell の関係**

Native shellとGuest shellに関係なく、Linux Namespaseによるリソース制限や分離が実現されています。ネットワークにつきましてもNetwork NamespaceとSwitch上のVRFがマッピングされた形で実装されている為、各shellからnamespace(==VRF)を指定して各ネットワークにアクセスできるようになっています。

実際の動作や詳細につきましては以後の各項で説明したいと思います。

# Native shell
実際にNX-OSのNative shell(Bash)を呼び出してみます。

```
N93180YC-EX-01# run bash
                    ^
% Invalid command at '^' marker.'
```
デフォルトではBash shellが有効化されていないため、Bash shellを以下のとおり有効化します。

```
N93180YC-EX-01# conf t
N93180YC-EX-01(config)# feature bash-shell
N93180YC-EX-01(config)# exit
```

再びNative shellを呼び出します。

```
N93180YC-EX-01# run bash
bash-4.2$ whoami
admin
```
adminユーザとしてログインしている事が分かります。

```
bash-4.2$ sudo su
bash-4.2# whoami
root
```

rootユーザとしてログインする事も可能です。

```
bash-4.2# ifconfig -a
Eth1-1    Link encap:Ethernet  HWaddr 00:2a:10:xx:xx:xy
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:29 errors:0 dropped:16 overruns:0 frame:0
          TX packets:44958 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:6003 (5.8 KiB)  TX bytes:9783084 (9.3 MiB)
<snip>
Eth1-48   Link encap:Ethernet  HWaddr 00:2a:10:xx:xx:xx
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
<snip>
```

各スイッチのポートの状態をifconfigコマンドで参照する事が可能です。

```
bash-4.2# ls /bootflash
nxos.7.0.3.I7.1.bin
monitor.py
```
Native shellからbootflashの内容を参照する事も可能です。

Native shellからNX-OS CLI(VSH)を呼び出して実行結果を活用する事もできます。

```
bash-4.2# vsh -c "show ver" | tail -20

Hardware
  cisco Nexus9000 93180YC-EX chassis
  Intel(R) Xeon(R) CPU  @ 1.80GHz with 24633508 kB of memory.
  Processor Board ID FDOXXXXXXXX

  Device name: N93180YC-EX-01
  bootflash:   53298520 kB
Kernel uptime is 6 day(s), 6 hour(s), 16 minute(s), 21 second(s)

Last reset
  Reason: Unknown
  System version: 7.0(3)I7(1)
  Service:

plugin
  Core Plugin, Ethernet Plugin

Active Package(s):
```

Native shellから外部のサーバに対してアクセスしたい場合はNetwork Namespace(実際にはVRFにMappingされている)を明示的に指定して行います。

まず、Network Namespaceを確認します。

```
bash-4.2# ls /var/volatile/run/netns
default  V100_VRF  management
```

管理用ポートであるmgmt0にデフォルトでアサインされているmanagement VRFがNetwork Namespaceとして存在している事が確認できます。

実際にPingやSSHの接続を行えるか確認します。

```
bash-4.2# ip netns exec management ping 192.168.1.1 -c1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_req=1 ttl=63 time=0.719 ms

--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.719/0.719/0.719/0.000 ms
```

```
bash-4.2# ip netns exec management ssh user@192.168.1.1
user@192.168.1.1's password:
Last login: Wed Dec  6 15:13:34 2017 from hoge.example.com
[user@spc-sv ~]$
```

上記のとおりShell scriptやPython scriptから自在に参照可能である事が分かります。また、Native Shell環境に対してPuppetやChefなどのAgentや自身でBuildしたrpmでインストールして運用する事も可能になっています。

Native shell環境に任意のアプリケーションをbuildしてインストールする為のbuild環境は以下のURLから入手する事ができます。
※NX-OSが稼動するSwitch上でbuildするのではなくVM等で別の環境を用意して行います。

[参考資料]
[Nexus Application Development - SDK](
https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/7-x/programmability/guide/b_Cisco_Nexus_9000_Series_NX-OS_Programmability_Guide_7x/b_Cisco_Nexus_9000_Series_NX-OS_Programmability_Guide_7x_chapter_011101.html)

# Guest shell

Guest shellはNexus9000シリーズではデフォルトで有効、Nexus3000シリーズでは無効となっています。また、Guest shellで利用するovaはNX-OSの配布イメージ(1つのファイル)に同梱されており、別途、個別にダウンロードしてインストールする必要はありません。

実際にGuest shellの稼働状況を確認してみます。

```
N93180YC-EX-01# show virtual-service list

Virtual Service List:

Name                    Status             Package Name
-----------------------------------------------------------------------
guestshell+             Activated          guestshell.ova

```
仮に、Guest shellが有効になっていなかった場合は以下のコマンドで有効化します。


```
N93180YC-EX-01# guestshell enable
```
※guest shellの新規立ち上げには多少時間がかかりますので、`show virtual-service list`で起動状況を確認します。StatusがActivatedになれば立ち上げ完了です。

逆にGuest shellを無効にしたい場合や環境を作り直したい場合の手順は以下のとおりです。

```
N93180YC-EX-01# guestshell destroy
You are about to destroy the guest shell and all of its contents.  Be sure to save your work. Are you sure you want to continue? (y/n) [n] y
```

Guest shellを呼び出します。

```
N93180YC-EX-01# run guestshell
[admin@guestshell ~]$ whoami
admin
```
adminユーザとしてログインしている事が分かります。

```
[admin@guestshell ~]$ sudo su
[root@guestshell admin]# whoami
root
```

無論、rootユーザとしてログインする事も可能です。

**Native shellとGuest shellの大きな違いはGuest shellはLXC上に構成されたCentOS7(64bit)環境であるという点です。**
※前述のとおりNative shellはWind River Linux 5ベースの環境

```
[root@guestshell admin]# cat /etc/redhat-release
CentOS Linux release 7.1.1503 (Core)
```

また、Native shellと比べてGuest shellはLXC上で稼動している事もありCPU/Memory/bootflash容量の制限をよりきめ細かく実施できる点も大きく異なっています。

**Guest shellを活用することで任意のライブラリーの追加等のアプリケーション動作環境の自由度の提供と任意のリソース制限を適用可能となり、任意のアプリケーションをスイッチ上で稼動させた際の本来のSwitch動作に対する実影響を極小化することが可能となります。**

次に、Native shellと同様にGuest shellから各リソースがどの様に見えるか確認したいと思います。

```
[root@guestshell admin]# ifconfig -a
Eth1-1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 00:2a:10:xx:xx:xy  txqueuelen 100  (Ethernet)
        RX packets 29  bytes 6003 (5.8 KiB)
        RX errors 0  dropped 16  overruns 0  frame 0
        TX packets 45707  bytes 9946160 (9.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
<snip>
Eth1-48: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 00:2a:10:xx:xx:xx  txqueuelen 100  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
<snip>
```

Native shellの時と同様に各スイッチのポートの状態をifconfigコマンドで参照する事が可能です。

```
[root@guestshell admin]# ls /bootflash
nxos.7.0.3.I7.1.bin
monitor.py
```
Guest shellからもbootflashの内容を参照する事も可能です。
また、Guest shellにおいてNX-OS CLI(VSH)を呼び出して実行結果を活用する事もできます。
※呼び出し方がNative shellの場合とは異なります。

```
[root@guestshell admin]# dohost "show ver" | tail -20

Hardware
  cisco Nexus9000 93180YC-EX chassis
  Intel(R) Xeon(R) CPU  @ 1.80GHz with 24633508 kB of memory.
  Processor Board ID FDOXXXXXXXX

  Device name: N93180YC-EX-01
  bootflash:   53298520 kB
Kernel uptime is 6 day(s), 8 hour(s), 23 minute(s), 25 second(s)

Last reset
  Reason: Unknown
  System version: 7.0(3)I7(1)
  Service:

plugin
  Core Plugin, Ethernet Plugin

Active Package(s):
```

Guest shellから外部のサーバにアクセスしたい場合にもNetwork Namespace(実際にはVRFにMappingされている)を明示的に指定して行います。

まず、Network Namespaceを確認します。
※Native shellの時とは参照先が異なります。

```
[root@guestshell admin]# ls /var/run/netns
default  V100_VRF  management
```

管理用ポートであるmgmt0にデフォルトでアサインされているmanagement VRFがNetwork Namespaceとして存在している事が確認できます。

実際にPingやSSHの接続を行えるか確認します。

```
[root@guestshell admin]# ip netns exec management ping 192.168.1.1 -c1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=63 time=0.618 ms

--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.618/0.618/0.618/0.000 ms
```

```
[root@guestshell admin]# ip netns exec management ssh user@192.168.1.1
network@192.168.1.1's password:
Last login: Wed Dec  6 19:05:42 2017 from hoge.example.com
[user@spc-sv ~]$ 
```

上記のとおりGuest shellはNative shellと同様な使い勝手を提供しながらよりセキュアで自由度の高いアプリケーション動作環境を提供しています。

NX-OS上でスクリプトやアプリケーションを稼動させる事を検討する場合は、まずはGuest shellでの動作を検討した上で必要に応じてNative shell環境の活用(設定変更動作をShell上から行いたい場合等)を考えて良いかも知れません。

[参考資料]
[Cisco Nexus 9000 Series NX-OS Programmability Guide, Release 7.x (Chapter: Guest Shell 2.3)](https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/7-x/programmability/guide/b_Cisco_Nexus_9000_Series_NX-OS_Programmability_Guide_7x/Guest_Shell.html)