Open vSwitchのTrunkポートをDockerに割り当てる


# はじめに
Open vSwitchを触ってみたついでに、Dockerと組み合わせるとどういう動きになるのかやってみました。

## 前提条件
- Cent OS 8 Stream

# Dockerのインストール
```shell-session

# sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
# yum install -y yum-utils
# yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
# yum install docker-ce docker-ce-cli containerd.io
```

# Open vSwitchのネットワーク作成
##作るもの
以下のネットワークを作成します。

```
# ovs-vsctl show
a0cac575-f8ff-4019-976e-ca7929fe8217
    Bridge "bridge0"
        # 物理インタフェースをvSwitchに接続
        # switchport mode trunk
        # switchport trunk allowed vlan 11,100
        Port "port1"
            Interface "enp9s0"
                type: system

        # ホストのMGMT (VLAN100)
        # 192.168.100.200/24
        Port "port2"
            tag: 100
            Interface "vlan100"
                type: internal

        $ Docker接続用のポート(Trunk)
        Port "port3"
            Interface "brdocker0"
                type: internal
    ovs_version: "2.12.0"
```

# NetworkManagerの設定

## ブリッジの作成
```
# nmcli conn add type ovs-bridge conn.interface bridge0
```

## 物理インタフェイスの接続(port1)

```
# nmcli conn del enp9s0
# nmcli conn add type ovs-port conn.interface port1 master bridge0
# nmcli conn add type ethernet conn.interface enp9s0 master port1
```

## 管理用インタフェイスの作成(VLAN100)
管理用のインタフェイスを作成します。これで外部からSSHがつながるようになるはず。

```
# nmcli conn add type ovs-port conn.interface port2 master bridge0 ovs-port.tag 100
# nmcli conn add type ovs-interface slave-type ovs-port conn.interface vlan100 master port2
# nmcli conn modify ovs-slave-vlan100 ipv4.method manual
# nmcli conn modify ovs-slave-vlan100 ipv4.address 192.168.100.200/24
# nmcli conn modify ovs-slave-vlan100 ipv4.dns 192.168.100.1
# nmcli conn modify ovs-slave-vlan100 ipv4.gateway 192.168.100.1
# nmcli conn modify ovs-slave-vlan100 ipv6.method disabled
```

## Docker接続用ポートの作成(brdocker0)
ovs-port.tagを指定しなければtrunkポートになるハズ。

```
# nmcli conn add type ovs-port conn.interface port3 master bridge0
# nmcli conn add type ovs-interface slave-type ovs-port conn.interface brdocker0 master port3
# nmcli conn modify ovs-slave-brdocker0 ipv4.method disabled
# nmcli conn modify ovs-slave-brdocker0 ipv6.method disabled
```

# Dockerコンテナの立ち上げ

## ネットワークの作成
-dオプションでmacvlanドライバを指定、parentオプションで接続するインターフェイスをVLAN ID付きで指定します。
名前はVLAN100としていますが何でも良いです。
—-ip-rangeで既存ネットワーク内で重複しないアドレスwl指定する必要があります。

```
# docker network create -d macvlan --subnet=192.168.11.0/24 --gateway=192.168.11.1 --ip-range=192.168.11.128/25 -o parent=brdocker0.11 vlan11
```


## コンテナの起動テスト
CentOSのイメージで起動します。

```
# docker run -itd --network vlan11 --dns 192.168.11.1 --name foo centos /bin/bash

# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
192a6531239f   centos    "/bin/bash"   12 minutes ago   Up 12 minutes             foo

# docker exec -it foo ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
779: eth0@if773: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.11.128/24 brd 192.168.11.255 scope global eth0
       valid_lft forever preferred_lft forever
```


## docker-composeにしてみる。
```docker-compose.yml
version: '3'
services:
  foo:
    image: centos
    command: ip a
    networks:
      vlan11:
        ipv4_address: 192.168.11.199
    dns:
      - 192.168.11.1

networks:
  vlan11:
    name: vlan11
    driver: macvlan
    driver_opts:
      parent: brdocker0.11
    ipam:
      config:
      - subnet: 192.168.11.0/24
        gateway: 192.168.11.1
```

# 参考
1. https://docs.docker.com/engine/install/centos/
2. https://docs.docker.com/network/macvlan/
3. https://docs.docker.com/engine/reference/commandline/network_create/