Nexus 9000v で Docker を動かす

NX-OS 9.2(1) から Nexus 9000、Nexus 3000 スイッチで Docker が公式にサポートされています。簡単な動作確認を行ってみました。

環境

f:id:naoki029:20190825160202p:plain
構成

検証用に仮想 OS の NX-OS 9000v 9.3(1) を使います。

Nexus の設定

Docker は Nexus スイッチの Bash Shell で動作するので、Bash Shell を有効にしておきます。Docker コンテナへのアクセスや、コンテナイメージのダウンロードのためにマネジメントインターフェースに IP を設定し、インターネットへ接続できるようにします。今回は dhcp を使ってマネジメント IP を設定しています。

feature bash-shell
feature dhcp

interface mgmt0
  ip address dhcp
  vrf member management

mgmt0 に IP が設定され、vrf management にデフォルトルートが存在することを確認しておきます。

NX-OS9000v-1(config-if)# show ip int brief vrf management 

IP Interface Status for VRF "management"(2)
Interface            IP Address      Interface Status
mgmt0                192.168.122.188 protocol-up/link-up/admin-up       
NX-OS9000v-1(config-if)# show ip route vrf management 
IP Route Table for VRF "management"
'*' denotes best ucast next-hop
'**' denotes best mcast next-hop
'[x/y]' denotes [preference/metric]
'%<string>' in via output denotes VRF <string>

0.0.0.0/0, ubest/mbest: 1/0
    *via 192.168.122.1, [1/0], 00:00:22, static
192.168.122.0/24, ubest/mbest: 1/0, attached
    *via 192.168.122.188, mgmt0, [0/0], 00:00:23, direct
192.168.122.188/32, ubest/mbest: 1/0, attached
    *via 192.168.122.188, mgmt0, [0/0], 00:00:23, local

Docker の起動

Bash Shell に root ユーザーで入り、Docker サービスを起動します。

NX-OS9000v-1# run bash sudo su -
root@NX-OS9000v-1#
root@NX-OS9000v-1# service docker start
Free bootflash: 1873 MB, total bootflash: 3471 MB
Carving docker bootflash storage: 300 MB
300+0 records in
300+0 records out
300000000 bytes (300 MB) copied, 17.9738 s, 16.7 MB/s
losetup: /bootflash/dockerpart: Warning: file does not fit into a 512-byte sector; the end of the file will be ignored.
mke2fs 1.42.9 (28-Dec-2013)
fs_types for mke2fs.conf resolution: 'ext4', 'small'
Discarding device blocks: done                            
Discard succeeded and will return 0s - skipping inode table wipe
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
73440 inodes, 292968 blocks
2929 blocks (1.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67633152
36 block groups
8192 blocks per group, 8192 fragments per group
2040 inodes per group
Superblock backups stored on blocks: 
        8193, 24577, 40961, 57345, 73729, 204801, 221185

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done 

tune2fs 1.42.9 (28-Dec-2013)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          4b7221c3-1621-4d89-ad29-713326d64e71
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              73440
Block count:              292968
Reserved block count:     2929
Free blocks:              273437
Free inodes:              73429
First block:              1
Block size:               1024
Fragment size:            1024
Reserved GDT blocks:      256
Blocks per group:         8192
Fragments per group:      8192
Inodes per group:         2040
Inode blocks per group:   255
Flex block group size:    16
Filesystem created:       Sun Aug 25 00:29:56 2019
Last mount time:          n/a
Last write time:          Sun Aug 25 00:29:57 2019
Mount count:              0
Maximum mount count:      -1
Last checked:             Sun Aug 25 00:29:56 2019
Check interval:           0 (<none>)
Lifetime writes:          8 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               128
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      f9469a11-571a-4db0-864a-27d802626c88
Journal backup:           inode blocks
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
Starting dockerd with args '--debug=true':      .

root@NX-OS9000v-1#service docker status
dockerd (pid  17962) is running...
root@NX-OS9000v-1#

これで Docker が立ち上がりました。コンテナを起動させる前に、Bash Shell から network namespace (=VRF)を確認してみます。management namespace に Docker 用の docker0 ブリッジが作成されていることがわかります。

root@NX-OS9000v-1#ip netns show
management (id: 1)
default (id: 0)
root@NX-OS9000v-1#
root@NX-OS9000v-1#ip netns exec management ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:cc:96:3f:f9  
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:166 errors:0 dropped:0 overruns:0 frame:0
          TX packets:68 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:13454 (13.1 KiB)  TX bytes:5408 (5.2 KiB)

eth1      Link encap:Ethernet  HWaddr 0c:6a:dd:c4:60:00  
          inet addr:192.168.122.188  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:46517 errors:7389 dropped:25 overruns:0 frame:7389
          TX packets:30299 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:59131374 (56.3 MiB)  TX bytes:2243260 (2.1 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  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:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@NX-OS9000v-1#

bootflash に Docker 用のファイルが作成されています。

root@NX-OSv9000-1#ls -lr /bootflash/dockerpart 
-rw-r--r-- 1 root root 300000000 Aug 25 00:33 /bootflash/dockerpart
root@NX-OSv9000-1#

コンテナの起動と外部接続

nginx を起動させて、ホストの 30080 にコンテナの 80 ポートを割り当てます。わかりやすくするために、nginx の index.html を書き換えておきます。起動時に、docker image をインターネットから取得できていることが確認できます。

root@NX-OSv9000-1#docker run -d -p 30080:80 --rm --name web nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
1ab2bdfe9778: Pull complete 
a17e64cfe253: Pull complete 
e1288088c7a8: Pull complete 
Digest: sha256:53ddb41e46de3d63376579acf46f9a41a8d7de33645db47a486de9769201fec9
Status: Downloaded newer image for nginx:latest
b5569c7b4427b270045b69554a722c0fc30f180ba8f82b05e74452a907e2487c
root@NX-OSv9000-1#
root@NX-OS9000v#echo "NX-OS9000v" > index.html
root@NX-OS9000v#docker cp index.html web:/usr/share/nginx/html/index.html
root@NX-OS9000v#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
b5569c7b4427        nginx               "nginx -g 'daemon ..."   31 minutes ago      Up 31 minutes       0.0.0.0:30080->80/tcp   web
root@NX-OS9000v#

Client 端末から Nexus のマネジメントインターフェースの 30080 ポートにアクセスすると、nginx のコンテナに対してアクセスできることが確認できます。

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
9: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether f6:fd:87:aa:2f:5d brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::f4fd:87ff:feaa:2f5d/64 scope link 
       valid_lft forever preferred_lft forever
/ # curl 192.168.122.188:30080
NX-OS9000v
/ # 

management namespace の nat テーブルに、コンテナへの NAT エントリが追加されていることが確認できます。

root@NX-OS9000v#ip netns  exec management iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:http

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:30080 to:172.17.0.2:80

まとめ

Nexus 9000 上で Docker コンテナを起動できることを確認しました。スイッチ上でユーザーがコンテナを使うメリットはイマイチ思いつきませんが、今後、面白い使い方を発見したら試してみようと思います。