Metonymical Deflection

ゆるく日々のコト・たまにITインフラ

CentOS7 ovs(Open vSwitch)+ovnのネットワーク設定方法

ovs+ovnのoverlayネットワークを構築し、KVM仮想マシンとDockerコンテナのトラフィックをBridgeで外部ネットワークに流して使用する場合の設定方法を記載したいと思います。
これにより、仮想マシンとコンテナと外部ネットワーク機器が同一VLANで通信可能になります。
ただ、実用性の観点で冗長化できないため、あまり使えないかもしれませんが、ovnの仕組みを理解する上では活用できるかと思います。

1.環境

1-1.VMWare
筐体                             : 自作PC(Win10pro)
CPU                           : Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
VMWare              : VMware(R) Workstation 15 Pro 15.1.0 build-13591040  
OS                               : CentOS7.6(1810)
Kernel                           : 3.10.0-957.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools 
ovs&ovn                          : 2.11.1

ベアメタル環境でも同様に設定可能です。

1-2.全体構成その1:Underlay

f:id:metonymical:20190721175822p:plain

1-3.全体構成その2:Overlay

f:id:metonymical:20190721175834p:plain
補足
「'」が付いている箇所は、主に「'」が付いていない箇所を設定すると自動設定されます。*1

1-4 .全体の流れ ~概要~
  1. ovs+ovnのビルドとインストール
  2. ovs+ovnの設定
  3. docker+consulのクラスタ設定
  4. (1)~(7)の設定
1-5 .全体の流れ ~コマンドのみ~

以下のコマンドを投入していきます。
やりたいことが既に決まっている方は、構成図とコマンドの内容を見るだけでもよいと思います。
しかし、ovs+ovnやdocker+consulの設定もそこそこボリュームがあるため、(1)~(7)の辿り着くまでが少々しんどいかもしれません。。

(1)
docker network create -d openvswitch --subnet=192.168.31.0/24 ovs

(2)
vi /etc/sysconfig/network-scripts/ifcfg-br-ext

DEVICE=br-ext
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

vi /etc/sysconfig/network-scripts/ifcfg-ens36

DEVICE=ens36
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ext
BOOTPROTO=none
NM_CONTROLLED=no
OVS_OPTIONS="vlan_mode=trunk trunks=300-301"
HOTPLUG=no

(3)
ovn-sbctl --db=tcp:192.168.30.101:6642 show

ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet301:br-ext
export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME l2gwport "" 301
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses l2gwport unknown
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-type l2gwport l2gateway
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-options l2gwport network_name=physnet301 l2gateway-chassis=28928b40-900b-4f48-b4ed-8d9d2f1082fd

(4)
export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
export IFACE_ID=$(ovs-vsctl get interface vnet1 external_ids:iface-id | sed s/\"//g)
export MAC_ADDR=$(ovs-vsctl get interface vnet1 external_ids:attached-mac | sed s/\"//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME $IFACE_ID
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses $IFACE_ID $MAC_ADDR
ovn-nbctl --db=tcp:192.168.30.101:6641 show

(5)
export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
export IFACE_ID=$(ovs-vsctl get interface vnet1 external_ids:iface-id | sed s/\"//g)
export MAC_ADDR=$(ovs-vsctl get interface vnet1 external_ids:attached-mac | sed s/\"//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME $IFACE_ID
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses $IFACE_ID $MAC_ADDR
ovn-nbctl --db=tcp:192.168.30.101:6641 show

(6)
docker run -itd \
--privileged \
--network ovs \
--name c2 \
c76 \
/sbin/init

(7)
docker run -itd \
--privileged \
--network ovs \
--name c3 \
c76 \
/sbin/init

2.ovs+ovnのビルドとインストール

ControllerNode(c76ovn01)にてビルドとインストールを実施します。またDockerもインストールしてしまいます。

2-1.ControllerNode
yum -y install @'Development Tools' rpm-build yum-utils wget libpcap-devel numactl-devel

mkdir -p /root/rpmbuild/SOURCES
cd /root/rpmbuild/SOURCES
wget https://www.openvswitch.org/releases/openvswitch-2.11.1.tar.gz
tar zxvf openvswitch-2.11.1.tar.gz
sed -e 's/@VERSION@/0.0.1/' openvswitch-2.11.1/rhel/openvswitch-fedora.spec.in > ovs.spec

yum-builddep -y ovs.spec && \
cd openvswitch-2.11.1 && \
./boot.sh && \
./configure && \
make rpm-fedora RPMBUILD_OPT="--without check" && \
make rpm-fedora-ovn RPMBUILD_OPT="--without check"

cd /root/rpmbuild/SOURCES/openvswitch-2.11.1/rpm/rpmbuild/RPMS/noarch
yum -y localinstall python-openvswitch-2.11.1-1.el7.noarch.rpm

cd /root/rpmbuild/SOURCES/openvswitch-2.11.1/rpm/rpmbuild/RPMS/x86_64
yum -y localinstall \
openvswitch-2.11.1-1.el7.x86_64.rpm \
ovn-2.11.1-1.el7.x86_64.rpm \
ovn-common-2.11.1-1.el7.x86_64.rpm \
ovn-central-2.11.1-1.el7.x86_64.rpm \
ovn-host-2.11.1-1.el7.x86_64.rpm \
ovn-docker-2.11.1-1.el7.x86_64.rpm

curl -sSL https://get.docker.com/ | sh

systemctl start openvswitch
systemctl enable openvswitch
systemctl start ovn-northd
systemctl enable ovn-northd
systemctl start docker
systemctl enable docker
2-2.ComputeNode

ComputeNode(c76ovn02&c76ovn03)にてビルドとインストールを実施します。違いは、ovn-central-2.11.1-1.el7.x86_64.rpmが無いだけです。

yum -y install @'Development Tools' rpm-build yum-utils wget libpcap-devel numactl-devel

mkdir -p /root/rpmbuild/SOURCES
cd /root/rpmbuild/SOURCES
wget https://www.openvswitch.org/releases/openvswitch-2.11.1.tar.gz
tar zxvf openvswitch-2.11.1.tar.gz
sed -e 's/@VERSION@/0.0.1/' openvswitch-2.11.1/rhel/openvswitch-fedora.spec.in > ovs.spec

yum-builddep -y ovs.spec && \
cd openvswitch-2.11.1 && \
./boot.sh && \
./configure && \
make rpm-fedora RPMBUILD_OPT="--without check" && \
make rpm-fedora-ovn RPMBUILD_OPT="--without check"

cd /root/rpmbuild/SOURCES/openvswitch-2.11.1/rpm/rpmbuild/RPMS/noarch
yum -y localinstall python-openvswitch-2.11.1-1.el7.noarch.rpm

cd /root/rpmbuild/SOURCES/openvswitch-2.11.1/rpm/rpmbuild/RPMS/x86_64
yum -y localinstall \
openvswitch-2.11.1-1.el7.x86_64.rpm \
ovn-2.11.1-1.el7.x86_64.rpm \
ovn-common-2.11.1-1.el7.x86_64.rpm \
ovn-host-2.11.1-1.el7.x86_64.rpm \
ovn-docker-2.11.1-1.el7.x86_64.rpm

curl -sSL https://get.docker.com/ | sh

systemctl start openvswitch
systemctl enable openvswitch
systemctl start ovn-controller
systemctl enable ovn-controller
systemctl start docker
systemctl enable docker

3.ovs+ovnの設定

3-1.Overlay用のInteface設定
c76ovn01
nmcli con add type ethernet autoconnect yes con-name ens37 ifname ens37
nmcli con mod ens37 ipv4.method manual ipv4.addresses 192.168.30.101/24
nmcli con up ens37

c76ovn02
nmcli con add type ethernet autoconnect yes con-name ens37 ifname ens37
nmcli con mod ens37 ipv4.method manual ipv4.addresses 192.168.30.102/24
nmcli con up ens37

c76ovn03
nmcli con add type ethernet autoconnect yes con-name ens37 ifname ens37
nmcli con mod ens37 ipv4.method manual ipv4.addresses 192.168.30.103/24
nmcli con up ens37
3-2.ovnの設定
c76ovn01
ovn-nbctl set-connection ptcp:6641
ovn-sbctl set-connection ptcp:6642
ovs-appctl -t ovsdb-server ovsdb-server/add-remote ptcp:6640
3-3.ovsの設定
c76ovn02
export CENTRAL_IP=192.168.30.101
export ENCAP_TYPE=geneve
export LOCAL_IP=192.168.30.102

ovs-vsctl set Open_vSwitch . external_ids:ovn-remote="tcp:${CENTRAL_IP}:6642"
ovs-vsctl set Open_vSwitch . external_ids:ovn-nb="tcp:${CENTRAL_IP}:6641"
ovs-vsctl set Open_vSwitch . external_ids:ovn-encap-ip=${LOCAL_IP}
ovs-vsctl set Open_vSwitch . external_ids:ovn-encap-type="${ENCAP_TYPE}"

systemctl restart ovn-controller

c76ovn03
export CENTRAL_IP=192.168.30.101
export ENCAP_TYPE=geneve
export LOCAL_IP=192.168.30.103

ovs-vsctl set Open_vSwitch . external_ids:ovn-remote="tcp:${CENTRAL_IP}:6642"
ovs-vsctl set Open_vSwitch . external_ids:ovn-nb="tcp:${CENTRAL_IP}:6641"
ovs-vsctl set Open_vSwitch . external_ids:ovn-encap-ip=${LOCAL_IP}
ovs-vsctl set Open_vSwitch . external_ids:ovn-encap-type="${ENCAP_TYPE}"

systemctl restart ovn-controller
3-4.設定確認

102と103が101とESTABとなっていればOKです。

c76ovn01
ss -ant |grep 6642

出力例
[root@c76ovn01 ~]# ss -ant |grep 6642
LISTEN     0      10           *:6642                     *:*
ESTAB      0      0      192.168.30.101:6642               192.168.30.102:44102
ESTAB      0      0      192.168.30.101:6642               192.168.30.103:34252

上記がOKな場合、br-intが自動生成され、GeneveによるOverlayのトンネル設定も自動で実施されます。また、ovs上では以下のようなステータスとなっていればOKです。

c76ovn02&03
ovs-vsctl show

出力例
[root@c76ovn02 ~]# ovs-vsctl show
e2d97138-977a-4579-bc6a-dfb43d8769cb
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
        Port "ovn-925250-0"
            Interface "ovn-925250-0"
                type: geneve
                options: {csum="true", key=flow, remote_ip="192.168.30.103"}
    ovs_version: "2.11.0"
3-5.virshによるovsの設定

c76ovn02&03にてovsのPortGroup設定を実施しておきます。*2

c76ovn02&03
vi /tmp/ovsnw.xml

<network>
<name>ovsnw</name>
<forward mode='bridge'/>
<bridge name='br-int'/>
<virtualport type='openvswitch'/>
<portgroup name='untag' default='yes'>
</portgroup>
<portgroup name='vlan300'>
  <vlan>
    <tag id='300'/>
  </vlan>
</portgroup>
<portgroup name='vlan301'>
  <vlan>
    <tag id='301'/>
  </vlan>
</portgroup>
</network>

virsh net-list
virsh net-define /tmp/ovsnw.xml
virsh net-start ovsnw
virsh net-autostart ovsnw
virsh net-list

4.docker+consulのクラスタ設定

4-1.Dockerの設定その1

Option設定を読込みできるようにします。

c76ovn01&02&03

vi /usr/lib/systemd/system/docker.service

EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock \
$OPTIONS \
$DOCKER_STORAGE_OPTIONS \
$DOCKER_NETWORK_OPTIONS \
$ADD_REGISTRY \
$BLOCK_REGISTRY \
$INSECURE_REGISTRY

出力例
青文字はコメントアウトしてください。
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock \
$OPTIONS \
$DOCKER_STORAGE_OPTIONS \
$DOCKER_NETWORK_OPTIONS \
$ADD_REGISTRY \
$BLOCK_REGISTRY \
$INSECURE_REGISTRY

ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
4-2.Dockerの設定その2
c76ovn01
vi /etc/sysconfig/docker
OPTIONS="--cluster-store=consul://127.0.0.1:8500 --cluster-advertise=192.168.30.101:0"

systemctl daemon-reload
systemctl restart docker

c76ovn02
vi /etc/sysconfig/docker
OPTIONS="--cluster-store=consul://127.0.0.1:8500 --cluster-advertise=192.168.30.102:0"

systemctl daemon-reload
systemctl restart docker

c76ovn03
vi /etc/sysconfig/docker
OPTIONS="--cluster-store=consul://127.0.0.1:8500 --cluster-advertise=192.168.30.103:0"

systemctl daemon-reload
systemctl restart docker
4-3.consulのインストール

consulでクラスタを構成します。
一度設定をミスると色々やっかいだった*3ので、VMWareなどで各Nodeを動作させている方は、この手順を進める前にスナップショットなりクローンを作成しておいた方が良いと思います。

c76ovn01&ovn02&ovn03
yum -y install epel-release && \
yum -y install python-pip && \
pip install pip --upgrade && \
pip install flask

wget https://releases.hashicorp.com/consul/1.5.2/consul_1.5.2_linux_amd64.zip
unzip consul_1.5.2_linux_amd64.zip
mv consul /usr/local/bin
4-4.consulの設定

最初に暗号キーを生成しておきます。生成した暗号キーは全Nodeで共通にしますので、任意の1台で生成すればOKです。ここでは例としてc76ovn01にて生成します。

c76ovn01
consul keygen

出力例
[root@c76ovn01 ~]# consul keygen
az3EW5ykRod6hBS1FiSFAA==

各Nodeごとに設定ファイルを作成します。赤文字の箇所のみ異なっています。

c76ovn01
sudo mkdir -p /etc/consul.d/scripts
sudo mkdir /var/consul

vi /etc/consul.d/config.json
{
    "bootstrap_expect": 3,
    "client_addr": "0.0.0.0",
    "datacenter": "dc1",
    "data_dir": "/var/consul",
    "domain": "consul",
    "enable_script_checks": true,
    "dns_config": {
        "enable_truncate": true,
        "only_passing": true
    },
    "enable_syslog": true,
    "encrypt": "az3EW5ykRod6hBS1FiSFAA==",
    "leave_on_terminate": true,
    "log_level": "INFO",
    "rejoin_after_leave": true,
    "bind_addr": "192.168.30.101",
    "server": true,
    "start_join": [
        "192.168.30.101",
        "192.168.30.102",
        "192.168.30.103"
    ],
    "ui": false
}

c76ovn02
sudo mkdir -p /etc/consul.d/scripts
sudo mkdir /var/consul

vi /etc/consul.d/config.json
{
    "bootstrap_expect": 3,
    "client_addr": "0.0.0.0",
    "datacenter": "dc1",
    "data_dir": "/var/consul",
    "domain": "consul",
    "enable_script_checks": true,
    "dns_config": {
        "enable_truncate": true,
        "only_passing": true
    },
    "enable_syslog": true,
    "encrypt": "az3EW5ykRod6hBS1FiSFAA==",
    "leave_on_terminate": true,
    "log_level": "INFO",
    "rejoin_after_leave": true,
    "bind_addr": "192.168.30.102",
    "server": true,
    "start_join": [
        "192.168.30.101",
        "192.168.30.102",
        "192.168.30.103"
    ],
    "ui": false
}

c76ovn03
sudo mkdir -p /etc/consul.d/scripts
sudo mkdir /var/consul

vi /etc/consul.d/config.json
{
    "bootstrap_expect": 3,
    "client_addr": "0.0.0.0",
    "datacenter": "dc1",
    "data_dir": "/var/consul",
    "domain": "consul",
    "enable_script_checks": true,
    "dns_config": {
        "enable_truncate": true,
        "only_passing": true
    },
    "enable_syslog": true,
    "encrypt": "az3EW5ykRod6hBS1FiSFAA==",
    "leave_on_terminate": true,
    "log_level": "INFO",
    "rejoin_after_leave": true,
    "bind_addr": "192.168.30.103",
    "server": true,
    "start_join": [
        "192.168.30.101",
        "192.168.30.102",
        "192.168.30.103"
    ],
    "ui": false
}
4-5.consulのサービス化設定

consulをサービス化し、自動起動するように設定します。

c76ovn01&02&03
vi /etc/systemd/system/consul.service

[Unit]
Description=Consul Startup process
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c '/usr/local/bin/consul agent -config-dir /etc/consul.d/'
TimeoutStartSec=0

[Install]
WantedBy=default.target

systemctl daemon-reload
systemctl start consul
systemctl enable consul

consul members

出力例
全Nodeで同様の出力となります。
[root@c76ovn03 ~]# consul members
Node            Address              Status  Type    Build  Protocol  DC   Segment
c76ovn01.md.jp  192.168.30.101:8301  alive   server  1.5.2  2         dc1  
c76ovn02.md.jp  192.168.30.102:8301  alive   server  1.5.2  2         dc1  
c76ovn03.md.jp  192.168.30.103:8301  alive   server  1.5.2  2         dc1  

[root@c76ovn03 ~]# systemctl status consul
● consul.service - Consul Startup process
   Loaded: loaded (/etc/systemd/system/consul.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-07-21 16:27:32 JST; 1s ago
 Main PID: 28182 (consul)
    Tasks: 14
   Memory: 18.2M
   CGroup: /system.slice/consul.service
           mq28182 /usr/local/bin/consul agent -config-dir /etc/consul.d/

Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: consul: Adding LAN server c76ovn01.md.jp (Addr: tcp/192.168.30.101:8300) (DC: dc1)
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: consul: Adding LAN server c76ovn02.md.jp (Addr: tcp/192.168.30.102:8300) (DC: dc1)
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: serf: EventMemberJoin: c76ovn02.md.jp.dc1 192.168.30.102
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: serf: Re-joined to previously known node: c76ovn01.md.jp.dc1: 192.168.30.101:8302
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: agent: Started HTTP server on [::]:8500 (tcp)
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: consul: Handled member-join event for server "c76ovn01.md.jp.dc1" in area "wan"
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: consul: Handled member-join event for server "c76ovn02.md.jp.dc1" in area "wan"
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: agent: (LAN) joining: [192.168.30.101 192.168.30.102 192.168.30.103]
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: agent: (LAN) joined: 3
Jul 21 16:27:32 c76ovn03.md.jp consul[28182]: agent: started state syncer

ここまで完了したら、一度全Nodeを再起動しておいてください。
再起動完了後、以下のコマンドでDockerとconsulが正常に起動していることを確認してください。

systemctl status docker
systemctl status consul

5.(1)~(7)の設定

5-1.事前準備

ovnのdocker-overlayドライバを各ComputeNodeで起動しておきます。

c76ovn02&03
ovn-docker-overlay-driver --detach
5-2.(1)の設定:DockerOverlaySwitchの作成

(1’)は自動生成されていますが、Overlay上では認識されていません。
以下のコマンドにより、ovnのNorthboundDBにDockerOverlaySwitchが生成されます。それと同時にDocker上のNWとしても認識されます。
c76ovn02もしくはc76ovn03のどちらか一方で設定すればOKです。

c76ovn02 or 03
docker network create -d openvswitch --subnet=192.168.31.0/24 ovs

出力例
[root@c76ovn02 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
7a78f73ce06d        bridge              bridge              local
368be43f05a1        host                host                local
efee695f0f0c        none                null                local
b5fb702e9489        ovs                 openvswitch         global

[root@c76ovn02 ~]# ovn-nbctl --db=tcp:192.168.30.101:6641 show
switch b70b9243-80b3-4ad6-8940-55bff06251fc (b5fb702e948902881b1b933191b9ee83f8dad4eb434a9d27d408d7a2d5fe2aa2)
5-3.(2)の設定:br-extの作成

br-intに無理やりインターフェースをアタッチしても外部とのBridge接続による疎通はできません。この辺りはNeutronのアーキテクチャに近い感じです。br-intとbr-extをPatch接続させて、外部ネットワークとブリッジ接続します。

c76ovn02
3-5に合わせて300-301をTrunkしていますが、今回の構成であれば301のみでOKです。

vi /etc/sysconfig/network-scripts/ifcfg-br-ext

DEVICE=br-ext
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

vi /etc/sysconfig/network-scripts/ifcfg-ens36

DEVICE=ens36
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ext
BOOTPROTO=none
NM_CONTROLLED=no
OVS_OPTIONS="vlan_mode=trunk trunks=300-301"
HOTPLUG=no

systemctl restart network
5-4.(3)の設定:br-intとbr-extのPatch接続

先にovn-sbctlコマンドでシャーシIDを取得した後に設定を入れます。

c76ovn02
(3)
ovn-sbctl --db=tcp:192.168.30.101:6642 show

ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet301:br-ext
export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME l2gwport "" 301
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses l2gwport unknown
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-type l2gwport l2gateway
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-options l2gwport network_name=physnet301 l2gateway-chassis=28928b40-900b-4f48-b4ed-8d9d2f1082fd
補足その1
ovn-sbctl --db=tcp:192.168.30.101:6642 showの出力例を以下に記載します。
赤文字の箇所をl2gateway-chassis=の後に加えます。
出力例
[root@c76ovn02 ~]# ovn-sbctl --db=tcp:192.168.30.101:6642 show
Chassis "1fdd4703-9c73-4afd-adf3-e0e90b7afb63"
    hostname: "c76ovn03.md.jp"
    Encap geneve
        ip: "192.168.30.103"
        options: {csum="true"}
    Port_Binding "35d89c2d-0505-41aa-b0c6-6aff6f483899"
    Port_Binding "b7131d7ecd548dcc4b6eb38bef0179b1bc75645e5683b69e6131da69d0aed1be"
Chassis "28928b40-900b-4f48-b4ed-8d9d2f1082fd"
    hostname: "c76ovn02.md.jp"
    Encap geneve
        ip: "192.168.30.102"
        options: {csum="true"}
    Port_Binding "16b258df72cb52ddb2527be69578c1f953c9275e154d4107743b0ee3ac13f095"
    Port_Binding "2c5a0afd-b12a-419e-b6f5-718c5d0e6446"
    Port_Binding "l2gwport"
[root@c76ovn02 ~]#
補足その2
設定後、以下のようになっていればOKです。
出力例
[root@c76ovn02 ~]# ovn-nbctl --db=tcp:192.168.30.101:6641 show
switch b70b9243-80b3-4ad6-8940-55bff06251fc (b5fb702e948902881b1b933191b9ee83f8dad4eb434a9d27d408d7a2d5fe2aa2)
    port l2gwport
        type: l2gateway
        parent:
        tag: 301
        addresses: ["unknown"]
[root@c76ovn02 ~]#

[root@c76ovn02 ~]# ovs-vsctl show
090be24a-f730-4d28-a4a0-dcf6d97fe618
    Bridge br-int
        fail_mode: secure
        Port "patch-br-int-to-l2gwport"
            Interface "patch-br-int-to-l2gwport"
                type: patch
                options: {peer="patch-l2gwport-to-br-int"}
        Port "ovn-1fdd47-0"
            Interface "ovn-1fdd47-0"
                type: geneve
                options: {csum="true", key=flow, remote_ip="192.168.30.103"}
        Port br-int
            Interface br-int
                type: internal
    Bridge br-ext
        Port "patch-l2gwport-to-br-int"
            Interface "patch-l2gwport-to-br-int"
                type: patch
                options: {peer="patch-br-int-to-l2gwport"}
        Port br-ext
            Interface br-ext
                type: internal
        Port "ens36"
            trunks: [300, 301]
            Interface "ens36"
    ovs_version: "2.11.1"
[root@c76ovn02 ~]#

ここまででアップリンクに相当する部分が構築できました。
あとは、仮想マシンやコンテナをアタッチしていきます。

コンテナは以下のコマンドで作成したDockerネットワークのovsにアタッチさせるだけで自動設定してくれます。

docker network create -d openvswitch --subnet=192.168.31.0/24 ovs

一方、KVMの仮想マシンについては、もう一工夫必要になります。

5-5.(4)と(5)の設定:KVM仮想マシンのアタッチ

先にvirt-installコマンドなどで仮想マシンを起動しておいてください。
その際、仮想マシンに使用するインターフェースは3-5で設定したPortGroupのうちvlan301を使用するようにしてください。

virt-installはこんな感じです。ポイントは赤文字の箇所です。

virt-install --connect=qemu:///system \
 --name=c7623 \
 --disk /var/lib/libvirt/images/c7623.qcow2,format=qcow2,bus=virtio \
 --network bridge=virbr0,model=virtio \
 --network network=ovsnw,portgroup=vlan301,model=virtio \
 --initrd-inject=./c76min.ks \
 --extra-args='ks=file:/c76min.ks biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8' \
 --vcpus=1 \
 --ram=1024 \
 --accelerate \
 --hvm \
 --location='/var/lib/libvirt/images/CentOS-7-x86_64-DVD-1810.iso' \
 --nographics \
 --os-type=linux \
 --os-variant=centos7.0 \
 --arch=x86_64

これにより、以下のような設定になります。ポイントはvnet1とovsnw, vlan301がBridgeしている点です。

vnet0 virbr0 eth0 libvirtでDefault定義
vnet1 ovsnw, vlan301 eth1 3-5で定義

仮想マシンが起動したら以下のコマンドにて、ovn上に登録していきます。
SW_NAME、IFACE_ID、MAC_ADDRを取得し、それをNorthboundDBに登録する形となります。(((4)と(5)のコマンドは同じですが、それぞれのComputeNodeにて実行するため取得するIDが異なります))

c76ovn02
(4)
export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
export IFACE_ID=$(ovs-vsctl get interface vnet1 external_ids:iface-id | sed s/\"//g)
export MAC_ADDR=$(ovs-vsctl get interface vnet1 external_ids:attached-mac | sed s/\"//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME $IFACE_ID
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses $IFACE_ID $MAC_ADDR
ovn-nbctl --db=tcp:192.168.30.101:6641 show

c76ovn03
(5)
export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
export IFACE_ID=$(ovs-vsctl get interface vnet1 external_ids:iface-id | sed s/\"//g)
export MAC_ADDR=$(ovs-vsctl get interface vnet1 external_ids:attached-mac | sed s/\"//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME $IFACE_ID
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses $IFACE_ID $MAC_ADDR
ovn-nbctl --db=tcp:192.168.30.101:6641 show

出力例
[root@c76ovn02 ~]# ovn-nbctl --db=tcp:192.168.30.101:6641 show
switch b70b9243-80b3-4ad6-8940-55bff06251fc (b5fb702e948902881b1b933191b9ee83f8dad4eb434a9d27d408d7a2d5fe2aa2)
    port l2gwport
        type: l2gateway
        parent:
        tag: 301
        addresses: ["unknown"]
    port 35d89c2d-0505-41aa-b0c6-6aff6f483899
        addresses: ["52:54:00:f6:45:c2"]
    port 2c5a0afd-b12a-419e-b6f5-718c5d0e6446
        addresses: ["52:54:00:d7:a6:96"]
[root@c76ovn02 ~]#
5-6.(6)と(7)の設定:Dockerコンテナのアタッチ

DockerコンテナのアタッチはPlug-Inで自動的にovs&ovnに登録されるため、「--network ovs」だけ忘れずに設定すれば問題ありません。

c76ovn02
(6)
docker run -itd \
--privileged \
--network ovs \
--name c2 \
centos \
/sbin/init

c76ovn03
(7)
docker run -itd \
--privileged \
--network ovs \
--name c3 \
centos \
/sbin/init

構成を確認してみます。

確認コマンド
docker network ls
ovn-nbctl --db=tcp:192.168.30.101:6641 show
ovn-sbctl --db=tcp:192.168.30.101:6642 show
ovs-vsctl show

出力例
ここでは例としてc76ovn03にて実施します。
ovs-vsctl showだけは02&03の両方で出力させます。
[root@c76ovn03 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
116424d7f10a        bridge              bridge              local
db62b02926e4        docker_gwbridge     bridge              local
dcdbfcc3e390        host                host                local
da1e0883a8ed        none                null                local
b5fb702e9489        ovs                 openvswitch         global

[root@c76ovn03 ~]# ovn-nbctl --db=tcp:192.168.30.101:6641 show
switch b70b9243-80b3-4ad6-8940-55bff06251fc (b5fb702e948902881b1b933191b9ee83f8dad4eb434a9d27d408d7a2d5fe2aa2)
    port b7131d7ecd548dcc4b6eb38bef0179b1bc75645e5683b69e6131da69d0aed1be
        addresses: ["02:dc:06:e4:de:3c 192.168.31.2"]
    port 16b258df72cb52ddb2527be69578c1f953c9275e154d4107743b0ee3ac13f095
        addresses: ["02:26:b3:e1:ab:5c 192.168.31.3"]
    port l2gwport
        type: l2gateway
        parent:
        tag: 301
        addresses: ["unknown"]
    port 35d89c2d-0505-41aa-b0c6-6aff6f483899
        addresses: ["52:54:00:f6:45:c2"]
    port 2c5a0afd-b12a-419e-b6f5-718c5d0e6446
        addresses: ["52:54:00:d7:a6:96"]

[root@c76ovn03 ~]# ovn-sbctl --db=tcp:192.168.30.101:6642 show
Chassis "1fdd4703-9c73-4afd-adf3-e0e90b7afb63"
    hostname: "c76ovn03.md.jp"
    Encap geneve
        ip: "192.168.30.103"
        options: {csum="true"}
    Port_Binding "35d89c2d-0505-41aa-b0c6-6aff6f483899"
    Port_Binding "b7131d7ecd548dcc4b6eb38bef0179b1bc75645e5683b69e6131da69d0aed1be"
Chassis "28928b40-900b-4f48-b4ed-8d9d2f1082fd"
    hostname: "c76ovn02.md.jp"
    Encap geneve
        ip: "192.168.30.102"
        options: {csum="true"}
    Port_Binding "16b258df72cb52ddb2527be69578c1f953c9275e154d4107743b0ee3ac13f095"
    Port_Binding "2c5a0afd-b12a-419e-b6f5-718c5d0e6446"
    Port_Binding "l2gwport"

[root@c76ovn02 ~]# ovs-vsctl show
090be24a-f730-4d28-a4a0-dcf6d97fe618
    Bridge br-int
        fail_mode: secure
        Port "16b258df72cb52d"
            Interface "16b258df72cb52d"
        Port "vnet1"
            tag: 301
            Interface "vnet1"
        Port "patch-br-int-to-l2gwport"
            Interface "patch-br-int-to-l2gwport"
                type: patch
                options: {peer="patch-l2gwport-to-br-int"}
        Port "ovn-1fdd47-0"
            Interface "ovn-1fdd47-0"
                type: geneve
                options: {csum="true", key=flow, remote_ip="192.168.30.103"}
        Port br-int
            Interface br-int
                type: internal
    Bridge br-ext
        Port "patch-l2gwport-to-br-int"
            Interface "patch-l2gwport-to-br-int"
                type: patch
                options: {peer="patch-br-int-to-l2gwport"}
        Port br-ext
            Interface br-ext
                type: internal
        Port "ens36"
            trunks: [30, 300, 301]
            Interface "ens36"
    ovs_version: "2.11.1"

[root@c76ovn03 ~]# ovs-vsctl show
2cbade66-e4e8-48e1-83e7-2ff460c1d665
    Bridge br-ext
        Port "ens36"
            trunks: [300, 301]
            Interface "ens36"
        Port br-ext
            Interface br-ext
                type: internal
    Bridge br-int
        fail_mode: secure
        Port "ovn-28928b-0"
            Interface "ovn-28928b-0"
                type: geneve
                options: {csum="true", key=flow, remote_ip="192.168.30.102"}
        Port br-int
            Interface br-int
                type: internal
        Port "b7131d7ecd548dc"
            Interface "b7131d7ecd548dc"
        Port "vnet1"
            tag: 301
            Interface "vnet1"
    ovs_version: "2.11.1"

[root@c76ovn03 ~]# docker container exec c3 ping 192.168.31.2
PING 192.168.31.2 (192.168.31.2) 56(84) bytes of data.
64 bytes from 192.168.31.2: icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from 192.168.31.2: icmp_seq=2 ttl=64 time=0.070 ms
^C
[root@c76ovn03 ~]# docker container exec c3 ping 192.168.31.203
PING 192.168.31.203 (192.168.31.203) 56(84) bytes of data.
64 bytes from 192.168.31.203: icmp_seq=1 ttl=64 time=0.946 ms
64 bytes from 192.168.31.203: icmp_seq=2 ttl=64 time=0.697 ms
^C
[root@c76ovn03 ~]# docker container exec c3 ping 192.168.31.2
PING 192.168.31.2 (192.168.31.2) 56(84) bytes of data.
64 bytes from 192.168.31.2: icmp_seq=1 ttl=64 time=0.028 ms
64 bytes from 192.168.31.2: icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from 192.168.31.2: icmp_seq=3 ttl=64 time=0.027 ms
^C
[root@c76ovn03 ~]# docker container exec c3 ping 192.168.31.202
PING 192.168.31.202 (192.168.31.202) 56(84) bytes of data.
64 bytes from 192.168.31.202: icmp_seq=1 ttl=64 time=2.34 ms
64 bytes from 192.168.31.202: icmp_seq=2 ttl=64 time=2.28 ms
64 bytes from 192.168.31.202: icmp_seq=3 ttl=64 time=2.98 ms
^C
[root@c76ovn03 ~]# docker container exec c3 ping 192.168.31.203
PING 192.168.31.203 (192.168.31.203) 56(84) bytes of data.
64 bytes from 192.168.31.203: icmp_seq=1 ttl=64 time=0.256 ms
64 bytes from 192.168.31.203: icmp_seq=2 ttl=64 time=0.984 ms
64 bytes from 192.168.31.203: icmp_seq=3 ttl=64 time=0.262 ms
^C
[root@c76ovn03 ~]# docker container exec c3 ping 192.168.31.254
PING 192.168.31.254 (192.168.31.254) 56(84) bytes of data.
64 bytes from 192.168.31.254: icmp_seq=1 ttl=64 time=9.48 ms
64 bytes from 192.168.31.254: icmp_seq=2 ttl=64 time=3.94 ms
64 bytes from 192.168.31.254: icmp_seq=3 ttl=64 time=3.91 ms

NorthboundDBとSouthboundDBの状態を確認する以下のコマンドですが

ovn-nbctl --db=tcp:192.168.30.101:6641 show
ovn-sbctl --db=tcp:192.168.30.101:6642 show

図に起こすとこんな感じになります。
f:id:metonymical:20190721180630p:plain
最初に載せた2つの図と合わせて観ると、より明確になってくるかと思います。

6.補足

ComputeNodeを再起動やShutdownしたいときは、以下のようなコマンドで必ずコンテナを終了させた後に、再起動やShutdownしてください。

docker container stop c2

というのも、Dockerコンテナのアタッチ時はほぼほぼ自動で設定してくれていましたが、デタッチ時は上記コマンドのように正常にコンテナを終了させないと、NorthboundDB上にゴミが残ります。場合によっては消せなくなるので、何度も繰り返し試したい方は必ずコンテナを終了させるようにしましょう。

以上です。

7.最後に

以下のサイトを参考にさせて頂きました。
OVN 設定サンプル | OVN config example 2015/12/27
Using OVN with KVM and Libvirt - Scott's Weblog - The weblog of an IT pro focusing on cloud computing, Kubernetes, Linux, containers, and networking
OVN - L2 Breakout Options | Blog @ Weiti.ORG
Dustin Spinhirne: The OVN Gateway Router

ovnは正直取っつきにくいかもしれません。
しかし、openstack stein以降では、ovnが実装されるようなので、今のうちから、しっかり理解しておくことは大切かなと思います。

また、今回はKVMとDockerでしたが、LXC/LXDでも試してみました。
しかし、FakeBridgeを使用する点が障壁となり疎通できませんでした。
さらに、アップリンク側にDPDKも動作させてみたのですが、設定方法は解ったものの、これまた疎通できずで断念しました。
Bridgeではなく、PAT+Routingだったら上手くいくような気がしていますが、取り急ぎ、一旦まとめてみようと思い今回の記事を書いた次第です。

なお、今回はl2gatewayという方法でBridgeさせましたが、localnetという方法もあります。こちらは、全ComputeNodeにてbr-extを作成した後、以下のコマンドでNorthboundDBに登録すれば設定可能です。

export SW_NAME=$(ovn-nbctl --db=tcp:192.168.30.101:6641 ls-list | awk '{print $2}' | sed s/\(//g | sed s/\)//g)
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-add $SW_NAME lcntport "" 301
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-addresses lcntport unknown
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-type lcntport localnet
ovn-nbctl --db=tcp:192.168.30.101:6641 lsp-set-options lcntport network_name=physnet301

localnetの場合、冗長化できそうな雰囲気はありますが、L2ループの懸念があるため、あまり推奨されていないようです。

ただ、いずれにせよ、ovn単体で使うのはあまり現実的ではないと感じたので、やはりopenstackやovirtなどと一緒に使用するのが良いと思います。

*1:例外はあります。例えば、(1')は自動で設定されますが、その後(1)を手動設定した際に初めて利用可能となる、といったケースがあります。また、(2)を手動設定した後、(3)を設定しないと、(2’)や(3’)がNorthboundDB上で認識されない、など。

*2:ここではUntagやvlan300も作成されていますが、vlan301のみでOKです。他は削除して構いません。

*3:私の環境では、正しい設定に直してもエラーが解消されなかったりしました。本編とあまり関係の無いところで時間を取られるのは、しんどいのでスナップショットやクローン化をおススメします。

CentOS7 kickstartによるインストール

kickstartによるインストールのサンプルファイルをいくつかピックアップしてみたいと思います。

サンプルとしては以下3つ。

  • CentOS7上のKVMにminimalでインストール
  • CentOS7上のKVMにServerGUIでインストール
  • DL360G8上にCentOS7をServerGUIでインストール

これ以外にも応用はいくらでもできると思います。

1.CentOS7上のKVMにminimalでインストール

1-1.kickstartファイルの作成
vi c76min.ks

cmdline
install
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8

# Network information
network  --bootproto=dhcp --device=eth0 --onboot=on --noipv6 --activate
#network  --bootproto=static --device=eth0 --ip=192.168.0.100 --netmask=255.255.255.0 --gateway=192.168.0.1 --nameserver=192.168.0.1 --noipv6 --activate
network  --bootproto=static --device=eth1 --ip=192.168.1.100 --netmask=255.255.255.0 --noipv6
network  --hostname=c7623.local.com

zerombr
bootloader --location=mbr --boot-drive=vda --append="crashkernel=auto biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8"
clearpart --none --initlabel

# Disk partitioning information
part /boot --ondisk=vda --size=1024 --fstype="xfs"
part pv.1  --ondisk=vda --size=1024 --grow
volgroup centos --pesize=4096 pv.1
logvol swap  --fstype="swap" --name=swap --vgname=centos --recommended
logvol /     --fstype="xfs"  --name=root --vgname=centos --size=1024 --grow

# Root password
rootpw --plaintext TESTPASSWORD
# System timezone
timezone Asia/Tokyo --isUtc --nontp
user --groups=wheel --name=user1 --password=TESTPASSWORD --plaintext
# X Window System configuration information
xconfig  --startxonboot

%packages
@^minimal
@core
kexec-tools
chrony

%end
reboot --eject
1-2.qcow2ファイルの作成
qemu-img create -f qcow2 /var/lib/libvirt/images/c7623.qcow2 20G
1-3.virt-installの実行
virt-install --connect=qemu:///system \
 --name=c7623 \
 --disk /var/lib/libvirt/images/c7623.qcow2,format=qcow2,bus=virtio \
 --network bridge=virbr0,model=virtio \
 --network network=ovsnw,portgroup=vlan301,model=virtio \
 --initrd-inject=./c76min.ks \
 --extra-args='ks=file:/c76min.ks biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8' \
 --vcpus=1 \
 --ram=1024 \
 --accelerate \
 --hvm \
 --location='/var/lib/libvirt/images/CentOS-7-x86_64-DVD-1810.iso' \
 --nographics \
 --os-type=linux \
 --os-variant=centos7.0 \
 --arch=x86_64
1-4.補足

上記1-3のvirt-installコマンドのうち、

 --network network=ovsnw,portgroup=vlan301,model=virtio \

の部分は
以下のようにovsにてスイッチを作成し、net-defineによって定義した場合の設定となります。

vi /tmp/ovsnw.xml

<network>
<name>ovsnw
<forward mode='bridge'/>
<bridge name='ovsbr0'/>
<virtualport type='openvswitch'/>
<portgroup name='untag' default='yes'>
</portgroup>
<portgroup name='vlan11'>
  <vlan>
    <tag id='11'/>
  </vlan>
</portgroup>
<portgroup name='vlan300'>
  <vlan>
    <tag id='300'/>
  </vlan>
</portgroup>
<portgroup name='vlan301'>
  <vlan>
    <tag id='301'/>
  </vlan>
</portgroup>
<portgroup name='vlan302'>
  <vlan>
    <tag id='302'/>
  </vlan>
</portgroup>
</network>

virsh net-define /tmp/ovsnw.xml
virsh net-start ovsnw
virsh net-autostart ovsnw
virsh net-list

2.CentOS7上のKVMにServerGUIでインストール

2-1.kickstartファイルの作成
vi c76gui.ks

cmdline
install
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8

# Network information
network  --bootproto=dhcp --device=eth0 --onboot=on --noipv6 --activate
#network  --bootproto=static --device=eth0 --ip=192.168.0.100 --netmask=255.255.255.0 --gateway=192.168.0.1 --nameserver=192.168.0.1 --noipv6 --activate
network  --bootproto=static --device=eth1 --ip=192.168.1.100 --netmask=255.255.255.0 --noipv6
network  --hostname=c7625.local.com

zerombr
bootloader --location=mbr --boot-drive=vda --append="crashkernel=auto biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8"
clearpart --none --initlabel

# Disk partitioning information
part /boot --ondisk=vda --size=1024 --fstype="xfs"
part pv.1  --ondisk=vda --size=1024 --grow
volgroup centos --pesize=4096 pv.1
logvol swap  --fstype="swap" --name=swap --vgname=centos --recommended
logvol /     --fstype="xfs"  --name=root --vgname=centos --size=1024 --grow

# Root password
rootpw --plaintext TESTPASSWORD
# System timezone
timezone Asia/Tokyo --isUtc --nontp
user --groups=wheel --name=user1 --password=TESTPASSWORD --plaintext
# X Window System configuration information
xconfig  --startxonboot

%packages
@^graphical-server-environment
@base
@core
@desktop-debugging
@development
@fonts
@gnome-desktop
@guest-agents
@guest-desktop-agents
@hardware-monitoring
@input-methods
@internet-browser
@virtualization-client
@virtualization-hypervisor
@virtualization-tools
@x11

%end
reboot --eject
2-2.qcow2ファイルの作成
qemu-img create -f qcow2 /var/lib/libvirt/images/c7625.qcow2 20G
2-3.virt-installの実行
virt-install --connect=qemu:///system \
 --name=c7625 \
 --disk /var/lib/libvirt/images/c7625.qcow2,format=qcow2,bus=virtio \
 --network bridge=virbr0,model=virtio \
 --network network=ovsnw,portgroup=vlan301,model=virtio \
 --initrd-inject=./c76gui.ks \
 --extra-args='ks=file:/c76gui.ks biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8' \
 --vcpus=1 \
 --ram=1024 \
 --accelerate \
 --hvm \
 --location='/var/lib/libvirt/images/CentOS-7-x86_64-DVD-1810.iso' \
 --nographics \
 --os-type=linux \
 --os-variant=centos7.0 \
 --arch=x86_64

3.DL360G8上にCentOS7をServerGUIでインストール

3-1.kickstartファイルの作成

作業用PCのテキストエディタなどで作成してください。*1

#version=DEVEL
# X Window System configuration information
xconfig  --startxonboot
# License agreement
eula --agreed
# Use CDROM installation media
cdrom
# Use graphical install
graphical
# Run the Setup Agent on first boot
firstboot --enable
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8

ignoredisk --only-use=sda
# Network information
network  --bootproto=static --device=eno1 --ip=192.168.0.100 --netmask=255.255.255.0 --gateway=192.168.0.1 --nameserver=192.168.0.1 --noipv6 --activate
network  --hostname=c765.local.com
#network  --bootproto=dhcp --device=eno2 --onboot=off --ipv6=auto
#network  --bootproto=dhcp --device=eno3 --onboot=off --ipv6=auto
#network  --bootproto=dhcp --device=eno4 --onboot=off --ipv6=auto
#network  --bootproto=dhcp --device=ens1f0 --onboot=off --ipv6=auto
#network  --bootproto=dhcp --device=ens1f1 --onboot=off --ipv6=auto

# Reboot after installation
reboot --eject
# Root password
rootpw --plaintext TESTPASSWORD
# System timezone
timezone Asia/Tokyo --isUtc --nontp
user --groups=wheel --name=user1 --password=TESTPASSWORD
# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=sda
# Partition clearing information
clearpart --all --initlabel --drives=sda
# Disk partitioning information
part pv.105 --fstype="lvmpv" --ondisk=sda --size=1    --grow
part /boot  --fstype="xfs"   --ondisk=sda --size=1024
volgroup centos --pesize=4096 pv.105
logvol /     --fstype="xfs"  --name=root --vgname=centos --size=1    --grow
logvol swap  --fstype="swap" --name=swap --vgname=centos --size=4096

%packages
@^graphical-server-environment
@base
@core
@desktop-debugging
@development
@dial-up
@fonts
@gnome-desktop
@guest-agents
@guest-desktop-agents
@hardware-monitoring
@input-methods
@internet-browser
@multimedia
@print-client
@virtualization-client
@virtualization-hypervisor
@virtualization-tools
@x11
kexec-tools
%end

%addon com_redhat_kdump --enable --reserve-mb=auto
%end

%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end

ファイル名をks.cfgとして、isoやimgファイルなどにイメージ化してください。
ここではイメージ化後のファイル名をks.imgとします。

3-2.イメージファイルのセット

f:id:metonymical:20190721010844p:plain
上図のうち、以下のようにイメージファイルをセットします。

ImageFile RemovalMedhia ks.img
ImageFile CD-ROM/DVD CentOS-7-x86_64-DVD-1810.iso
3-3.起動オプションの設定とインストールの実行

f:id:metonymical:20190721011159p:plain
筐体を起動後、上図が表示されたら
Install CentOS 7を選択し、Tabキーを入力してください。
次に起動オプションの入力を促されるので、以下の通り入力してください。

inst.ks=hd:sdb:/ks.cfg

以下のようにインストールが始まれば、あとは待つだけです。
f:id:metonymical:20190721011458p:plain

以上です。

10.最後に

以下のサイトを参考にさせて頂きました。
KickStartその2(ks.cfg設定ファイルの説明) - のぴぴのメモ

/root/anaconda-ks.cfgを参考にすれば色々試せると思いますので、自分なりにやってみることをおススメします。

*1:graphicalではなく、textの方がインストールは早いのですが、私の環境ではなぜか?インストール中に何度も失敗したためgraphicalにしています。

Dockerコンテナのネットワーク設定方法 OvSとSR-IOV編

DockerコンテナでOvSやSR-IOVを使用する場合の設定方法を記載します。
通常のLinuxBridgeやdockerコマンド(macvlan)を使用したネットワーク設定方法については前回記事
Dockerコンテナのネットワーク設定方法 - Metonymical Deflection
を参照してください。

また、OvSについては以下の過去記事のDocker版となります。
CentOS7 ovs(Open vSwitch)のネットワーク設定方法 - Metonymical Deflection
加えて、SR-IOVについては以下の過去記事のDocker版となります。
Linux nmcliコマンドによるKVM&LXC/LXD with SR-IOVのInterface設定 - Metonymical Deflection

なお、LXC/LXDと異なる点として、Docker側Interfaceの永続化設定までは記載していません。*1

1.構成

1-1.環境
筐体                             : ProLiant DL360p Gen8
System ROM                       : P71 01/22/2018
NIC                              : Intel X520-SR2 ens2f0
NIC                              : HP(Emulex) NC552SFP ens1f0-1
OS                               : CentOS7.6(1810)
Kernel                           : 3.10.0-957.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools 
ovs                              : 2.11.0
1-2.全体構成

f:id:metonymical:20190622154959p:plain
構成図上に(1)~(13)までの番号を割り振りました。
このうち、(3)~(11)までは、過去記事↓
CentOS7 ovs(Open vSwitch)のネットワーク設定方法 - Metonymical Deflection
と同様になるため割愛します。

スイッチ側の設定は以下となります。

interface Port-channel1
 switchport trunk encapsulation dot1q
 switchport trunk allowed vlan 11,300-302
 switchport mode trunk
 spanning-tree portfast trunk
!
interface TenGigabitEthernet0/25
 switchport trunk encapsulation dot1q
 switchport trunk allowed vlan 300-304
 switchport mode trunk
 spanning-tree portfast trunk
 channel-group 1 mode active
!
interface TenGigabitEthernet0/26
 switchport trunk encapsulation dot1q
 switchport trunk allowed vlan 300-304
 switchport mode trunk
 spanning-tree portfast trunk
 channel-group 1 mode active
!
interface TenGigabitEthernet0/27
 switchport trunk encapsulation dot1q
 switchport trunk allowed vlan 300-304
 switchport mode trunk
 spanning-tree portfast trunk
!
interface Vlan300
 ip address 192.168.30.254 255.255.255.0
!
1-3.全体の流れ ~概要~
  1. Bridge作成:(1)
  2. Bonding:(2)
  3. Dockerコンテナをovsbr0にアタッチ:(12)
  4. DockerコンテナをSR-IOVのVFにアタッチ:(13)
1-4.全体の流れ ~コマンドのみ~

以下のコマンドを投入していきます。
やりたいことが既に決まっている方は、構成図とコマンドの内容を見るだけでもよいと思います。

事前準備1:OvSのインストール
yum install -y https://repos.fedorapeople.org/repos/openstack/openstack-stein/rdo-release-stein-2.noarch.rpm && \
yum install -y openvswitch

事前準備2:Dockerのインストール
curl -sSL https://get.docker.com/ | sh

事前準備3:pipeworkのインストール
curl -sL https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework > /usr/local/bin/pipework
chmod +x /usr/local/bin/pipework

1.Bridge作成
(1)
ovs-vsctl add-br ovsbr0

2.Bonding
(2)
ovs-vsctl add-bond ovsbr0 bond0 ens1f0 ens1f1

1&2の永続化設定
vi /etc/sysconfig/network-scripts/ifcfg-ovsbr0

DEVICE=ovsbr0
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

vi /etc/sysconfig/network-scripts/ifcfg-ens1f0

DEVICE=ens1f0
NETBOOT=yes
IPV6INIT=no
BOOTPROTO=none
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

vi /etc/sysconfig/network-scripts/ifcfg-ens1f1

DEVICE=ens1f1
NETBOOT=yes
IPV6INIT=no
BOOTPROTO=none
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

[LACPの場合]
vi /etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSBond
OVS_BRIDGE=ovsbr0
BOOTPROTO=none
NM_CONTROLLED=no
BOND_IFACES="ens1f0 ens1f1"
OVS_OPTIONS="bond_mode=balance-tcp lacp=active other_config:lacp-time=fast vlan_mode=trunk trunks=300-304"
HOTPLUG=no

[固定LAGの場合]
vi /etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSBond
OVS_BRIDGE=ovsbr0
BOOTPROTO=none
NM_CONTROLLED=no
BOND_IFACES="ens1f0 ens1f1"
OVS_OPTIONS="bond_mode=balance-slb lacp=off vlan_mode=trunk trunks=300-304"
HOTPLUG=no

3.Dockerコンテナをovsbr0にアタッチ
(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc1 \
centos \
/sbin/init

(12)
pipework \
ovsbr0 \
-i eth1 \
dkc1 \
192.168.30.103/24 \
@300

4.DockerコンテナをSR-IOVのVFにアタッチ
(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc2 \
centos \
/sbin/init

(13)
pipework \
--direct-phys enp7s16 \
-i eth1 \
dkc2 \
192.168.30.104/24 \
@300

2.事前準備

2-1.事前準備1:OvSのインストール
yum install -y https://repos.fedorapeople.org/repos/openstack/openstack-stein/rdo-release-stein-2.noarch.rpm && \
yum install -y openvswitch

RDOのSteinのリポジトリをインストールした後、最新のOvSをインストールしています。

2-2.事前準備2:Dockerのインストール
curl -sSL https://get.docker.com/ | sh

最新のDcokerをインストールしています。

2-3.事前準備3:pipeworkのインストール
curl -sL https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework > /usr/local/bin/pipework
chmod +x /usr/local/bin/pipework

pieworkをインストールしています。
OvSとSR-IOVの両方とも同じコマンド体系で設定できるため、pieworkにしました。
ovs-dockerによる方法は最後に記載します。

3.Bridge作成

説明無しでザックリ書きます。
詳細な説明は過去記事を参照してください。
(1)Bridgeの作成

出力結果
[root@c761 ~]# ovs-vsctl add-br ovsbr0
[root@c761 ~]# ovs-vsctl show
b1d3d75a-2c4c-49e7-bc33-06e44a70dfe2
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
    ovs_version: "2.11.0"

4.Bonding

Bondを作成し、物理インターフェースをBondにアタッチします。
(2)Bond作成+物理アタッチ

出力結果
[root@c761 ~]# ovs-vsctl add-bond ovsbr0 bond0 ens1f0 ens1f1
[root@c761 ~]# ovs-vsctl show
b1d3d75a-2c4c-49e7-bc33-06e44a70dfe2
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "bond0"
            Interface "ens1f1"
            Interface "ens1f0"
    ovs_version: "2.11.0"

5.永続化設定

コマンドを打っただけだと、ホストOSをRebootすると消えてしまうので永続化設定を行います。

vi /etc/sysconfig/network-scripts/ifcfg-ovsbr0

DEVICE=ovsbr0
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

vi /etc/sysconfig/network-scripts/ifcfg-ens1f0

DEVICE=ens1f0
NETBOOT=yes
IPV6INIT=no
BOOTPROTO=none
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

vi /etc/sysconfig/network-scripts/ifcfg-ens1f1

DEVICE=ens1f1
NETBOOT=yes
IPV6INIT=no
BOOTPROTO=none
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no

[LACPの場合]
vi /etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSBond
OVS_BRIDGE=ovsbr0
BOOTPROTO=none
NM_CONTROLLED=no
BOND_IFACES="ens1f0 ens1f1"
OVS_OPTIONS="bond_mode=balance-tcp lacp=active other_config:lacp-time=fast vlan_mode=trunk trunks=300-304"
HOTPLUG=no

[固定LAGの場合]
vi /etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSBond
OVS_BRIDGE=ovsbr0
BOOTPROTO=none
NM_CONTROLLED=no
BOND_IFACES="ens1f0 ens1f1"
OVS_OPTIONS="bond_mode=balance-slb lacp=off vlan_mode=trunk trunks=300-304"
HOTPLUG=no

設定後はnetworkサービスをリスタート
systemctl restart network

networkサービスのリスタートを行っても正常に動作しない場合、少々ダサいですがホストOSごと再起動してみてください。

6.Dockerコンテナをovsbr0にアタッチ

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc1 \
centos \
/sbin/init

(12)
pipework \
ovsbr0 \
-i eth1 \
dkc1 \
192.168.30.103/24 \
@300

以下のようにvethが追加されていればOKです。

[root@c763 ~]# ovs-vsctl show
23cda0ca-2d97-4c3f-bd00-d143a1f3a151
    Manager "ptcp:6640"
        is_connected: true
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "bond0"
            trunks: [300, 301, 302, 303, 304]
            Interface "ens1f0"
            Interface "ens1f1"
        Port "veth1pl25675"
            tag: 300
            Interface "veth1pl25675"
    ovs_version: "2.11.0"

以下にpipeworkのSyntax出力を記載します。

[root@c763 ~]# pipework
Syntax:
pipework  [-i containerinterface] [-l localinterfacename] [-a addressfamily]  /[@default_gateway] [macaddr][@vlan]
pipework  [-i containerinterface] [-l localinterfacename]  dhcp [macaddr][@vlan]
pipework route  
pipework rule  
pipework tc  
pipework --wait [-i containerinterface]

上記Syntaxより、例えば以下のようにGWとMACを指定した設定も可能になります。
また「@300」を消せばUntagとなります。

(12')
pipework \
ovsbr0 \
-i eth1 \
dkc1 \
192.168.30.103/24@192.168.30.254 \
00:11:22:33:44:55@300

7.DockerコンテナをSR-IOVのVFにアタッチ

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc2 \
centos \
/sbin/init

(13)
pipework \
--direct-phys enp7s16 \
-i eth1 \
dkc2 \
192.168.30.104/24 \
@300

以下のようにコンテナとVFのMACアドレスが一致していればOKです。

[root@c763 ~]# ip link show enp7s16
12: enp7s16:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 1a:6a:a5:b0:49:59 brd ff:ff:ff:ff:ff:ff
[root@c763 ~]# 
[root@c763 ~]# docker container exec -it dkc2 ip link show eth1
36: eth1@if12:  mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 1a:6a:a5:b0:49:59 brd ff:ff:ff:ff:ff:ff link-netnsid 0

ポイントはオプション「--direct-phys enp7s16」にてVFを掴ませている点が、OvSとは異なります。

8.補足1:ovs-dockerによるOvSへのアタッチ

ovs-dockerのwget&実行権限付与
wget -O /usr/local/bin/ovs-docker \
https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-docker
chmod 755 /usr/local/bin/ovs-docker

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc3 \
centos \
/sbin/init

(12)-1:OvSへのアタッチとIP設定
ovs-docker add-port ovsbr0 eth1 dkc3 \
--ipaddress="192.168.30.105/24"

(12)-2:Vlanの設定
ovs-docker set-vlan ovsbr0 eth1 dkc3 300

以下のように出力されていればOKです。

[root@c763 ~]# ovs-vsctl show
23cda0ca-2d97-4c3f-bd00-d143a1f3a151
    Manager "ptcp:6640"
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "15d5c9395dab4_l"
            tag: 300
            Interface "15d5c9395dab4_l"
        Port "bond0"
            trunks: [300, 301, 302, 303, 304]
            Interface "ens1f0"
            Interface "ens1f1"
    ovs_version: "2.11.0"

一手間増えますが、SR-IOVのVFへのアタッチができないことやovs-dockerもpipeworkもdocker inspectに載ってこないことを考えると、pipeworkで良いのかなと思いました。

9.補足2:Open_vMonitor

補足というか、おまけでOpen_vMonitorをご紹介させてください。

ovs-vsctl set-manager ptcp:6640
docker run -d -p 3000:3000 --name ovsgui01 -h ovsgui01 plvisiondevs/open_vmonitor

ホストOSのIP(192.168.11.213)にアクセス

http://192.168.11.213:3000/enter
 username:admin
 password:admin
 Enter OVSDB IP:192.168.11.213

f:id:metonymical:20190622152119p:plain
以下の画面で各ポートの情報が確認できます。
f:id:metonymical:20190622152217p:plain
多数のコンテナを起動した際は見やすいのかなと思います。

以上です。

10.最後に

以下のサイトを参考にさせて頂きました。
第35回 Open vSwitchで作るDockerのネットワーク(OVSで構築する編) (1/6) - ITmedia エンタープライズ
SR-IOV in Docker containers - Anirban Mukherjee - Medium

永続化設定という課題はありますが、LXC/LXDとはそもそもの用途が異なるため、まぁ、こんなもんかなという感じです。
以下のサイトにLXC/LXDとDockerの比較表があるので参考までに。
Dockerもいいけど、LXCも使おうぜ - Qiita

次のステップとして、DPDKを実装したいと考えていますが、ovnやconsulを使用した構成となるため、CentOS8になってからにしようかなと思っています。
とはいえ、ovnを使い始めるとなると、OpenStackやokdの方がいいかなと少し悩んでいます。

*1:作りこめばできそうですが、LXC/LXDとDockerの用途の違いかなと思っているので、あまり深入りはしませんでした。

Dockerコンテナのネットワーク設定方法

DockerコンテナのトラフィックをBridgeで外部ネットワークに流して使用する場合の設定方法を記載したいと思います。
Dockerで作成するBridge*1は、ホストOSのiptablesでPATされてしまうため、コンテナと外部NW機器が同一のNWセグメントとして使用できるようにします。

以下の過去記事のDcoker版と考えてください。
LXC/LXDコンテナのネットワーク設定方法 - Metonymical Deflection

なお、設定方法が2種類あります。先に1を記載した後、2を記載したいと思います。

No 設定方法 ホストOSとの疎通性 brctlやipコマンドでの確認可否
1 LinuxBridgeを併用 可能
2 dockerコマンドのみ使用(macvlan) 不可

1.環境

1-1.VMWare
筐体                             : 自作PC(Win10pro)
CPU                           : Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
VMWare              : VMware(R) Workstation 15 Pro 15.1.0 build-13591040  
OS                               : CentOS7.6(1810)
Kernel                           : 3.10.0-957.el7.x86_64
Installed Environment Groups     : Minimal Install

ベアメタル環境でも同様に設定可能です。

1-2.全体構成

f:id:metonymical:20190616175355p:plain
上図のうちdocker0はDefaultで作成されています。
また、docker0はNATして外部ネットワークに接続されています。私の用途としては、コンテナ上でyumなどを行いたい場合のInternet接続用マネジメントインターフェースとして使用しています。*2

しかし、KVMライクにDockerコンテナを使用したいので、今回行う設定は(1)~(9)となります。
(1)(2)(5)(6)(7):nmcliコマンド
(3)(4)(8)(9):dockerコマンド
となります。

1-2.全体の流れ ~概要~
  • LinuxBridge併用の場合:(1)~(9)
  • dockerコマンドのみの場合:(3)(4)(8)(9)

 ※
 流れというよりも、それぞれ別々の設定となります。

1-3.全体の流れ ~コマンドのみ~

以下のコマンドを投入していきます。
やりたいことが既に決まっている方は、構成図とコマンドの内容を見るだけでもよいと思います。

1.LinuxBridge併用の場合
(1)
nmcli connection add type bridge autoconnect yes con-name br0 ifname br0
nmcli connection modify br0 bridge.stp no
nmcli connection modify br0 ipv6.method ignore
nmcli connection modify br0 ipv4.method manual ipv4.addresses 192.168.30.202/24
nmcli connection up br0
nmcli con show
brctl show

(2)
nmcli connection add type ethernet autoconnect yes con-name ens34 ifname ens34
nmcli connection modify ens34 connection.master br0 connection.slave-type bridge
nmcli connection up ens34
nmcli con show
brctl show

(3)
docker network create -d bridge \
--subnet=192.168.30.0/24 \
--ip-range=192.168.30.0/25 \
--gateway=192.168.30.202 \
--opt com.docker.network.bridge.name=br0 \
br0

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc1 \
centos \
/sbin/init

(4)
docker network connect br0 dkc1 \
--ip=192.168.30.100

(5)
nmcli connection add type bridge autoconnect yes con-name br301 ifname br301
nmcli connection modify br301 bridge.stp no
nmcli connection modify br301 ipv6.method ignore
nmcli connection modify br301 ipv4.method manual ipv4.addresses 192.168.31.202/24
nmcli connection up br301
nmcli con show
brctl show

(6)
nmcli connection add type vlan autoconnect yes con-name ens34.301 ifname ens34.301 dev ens34 id 301
nmcli con show
brctl show

(7)
nmcli connection modify ens34.301 connection.master br301 connection.slave-type bridge
nmcli connection up ens34.301
nmcli con show
brctl show

(8)
docker network create -d bridge \
--subnet=192.168.31.0/24 \
--ip-range=192.168.31.0/25 \
--gateway=192.168.31.202 \
--opt com.docker.network.bridge.name=br301 \
br301

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc2 \
centos \
/sbin/init

(9)
docker network connect br301 dkc2 \
--ip=192.168.31.100

2.dockerコマンドのみの場合
(3)
docker network create -d macvlan \
--subnet=192.168.30.0/24 \
--ip-range=192.168.30.0/25 \
--gateway=192.168.30.254 \
-o parent=ens34 br0

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc1 \
centos \
/sbin/init

(4)
docker network connect br0 dkc1 \
--ip=192.168.30.100

(8)
docker network create -d macvlan \
--subnet=192.168.31.0/24 \
--ip-range=192.168.31.0/25 \
--gateway=192.168.31.254 \
-o parent=ens34.301 br301

(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc2 \
centos \
/sbin/init

(9)
docker network connect br301 dkc2 \
--ip=192.168.31.100

<コンテナ起動コマンドについて補足>
「--network bridge」について、Default定義NWとユーザ定義NWを2つ同時にアタッチしようとすると、以下のようにエラーで弾かれます。このため、まずはDefault定義NWを設定しています。

[root@c76dk01 ~]# docker run -itd \
> --privileged \
> --network bridge \
> --network br0 \
> --name dkc3 \
> c76 \
> /sbin/init
docker: conflicting options: cannot attach both user-defined and non-user-defined network-modes.
See 'docker run --help'.
[root@c76dk01 ~]#

2.LinuxBridge併用の場合

2-1.通常のBridge

nmcliコマンドによりBridgeインターフェースを作成し、コンテナのNICをLinuxBridgeにアタッチします。
(1)(2)Bridgeインターフェースbr0の作成+ens34をbr0にアタッチ
(3)dockerコマンドにてbr0を作成*3
(4)br0にコンテナdkc1のeth1をアタッチ+IP設定

(1)(2)Bridgeインターフェースbr0の作成+ens34をbr0にアタッチ
(1)と(2)は過去記事などを参照してください。

投入コマンド
(1)
nmcli connection add type bridge autoconnect yes con-name br0 ifname br0
nmcli connection modify br0 bridge.stp no
nmcli connection modify br0 ipv6.method ignore
nmcli connection modify br0 ipv4.method manual ipv4.addresses 192.168.30.202/24
nmcli connection up br0
nmcli con show
brctl show
(2)
nmcli connection add type ethernet autoconnect yes con-name ens34 ifname ens34
nmcli connection modify ens34 connection.master br0 connection.slave-type bridge
nmcli connection up ens34
nmcli con show
brctl show

出力例
以下のように出力されていればOKです。
[root@c76dk01 ~]# nmcli con show
NAME       UUID                                  TYPE      DEVICE
br0        5c7da373-af73-4cda-a420-7949eeb6974e  bridge    br0
docker0    227bbb74-0c07-447a-99ec-5f84c6bf61c0  bridge    docker0
ens33      2f7e32c0-adfd-41b1-9698-dff6406af75d  ethernet  ens33
ens34      2849b0b6-1c27-4293-81b3-a07068feb36c  ethernet  ens34

br0が作成され、物理インターフェースens34にもアタッチされます。

(3)dockerコマンドにてbr0を作成

投入コマンド
(3)
docker network create -d bridge \
--subnet=192.168.30.0/24 \
--ip-range=192.168.30.0/25 \
--gateway=192.168.30.202 \
--opt com.docker.network.bridge.name=br0 \
br0

出力例
[root@c76dk01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ebc2a0612742        br0                 bridge              local
a6ae25cd104e        bridge              bridge              local
f51b9d166f07        host                host                local
d1023dacb10b        none                null                local

[root@c76dk01 ~]# docker network inspect br0
[
    {
        "Name": "br0",
        "Id": "ebc2a0612742e6b2529fde112c5b2cb465abb6d27fe8623c20b92c7242d573bb",
        "Created": "2019-06-16T18:22:29.649525689+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.30.0/24",
                    "IPRange": "192.168.30.0/25",
                    "Gateway": "192.168.30.202"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.name": "br0"
        },
        "Labels": {}
    }
]
docker network create -d bridge \ NWドライバにbridgeを選択。必須
--subnet=192.168.30.0/24 \ サブネットを定義。必須
--ip-range=192.168.30.0/25 \ DHCPで配布されるレンジを定義。任意
--gateway=192.168.30.202 \ GWアドレスを定義。任意。但し、設定しないと192.168.30.1が強制的に設定されます。また、nmcliコマンドで作成したbr0のIPも192.168.30.1に上書きされます。
--opt com.docker.network.bridge.name=br0 \ nmcliコマンドで作成したbr0にアタッチ。必須
br0 Docker上のNWの名前。必須。ですが任意の名前でOK。管理上nmcliコマンドで作成したbr0と名前を一致せています。


(4)br0にコンテナdkc1のeth1をアタッチ+IP設定
続いてコンテナを起動し、コンテナNICのeth1をbr0にアタッチさせます。

投入コマンド
(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc1 \
centos \
/sbin/init

(4)
docker network connect br0 dkc1 \
--ip=192.168.30.100

出力例
[root@c76dk01 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.000c29d40546       no              ens34
                                                        veth41095a7
docker0         8000.0242f2b40eff       no              veth24c4ace

[root@c76dk01 ~]# docker network inspect br0
[
    {
        "Name": "br0",
        "Id": "e14f9d9ab5f236adee0bfbe95760272e3bfa5d0371804b1bb880164eb7b85c3f",
        "Created": "2019-06-16T18:44:09.13402567+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.30.0/24",
                    "IPRange": "192.168.30.0/25",
                    "Gateway": "192.168.30.202"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "b4ec13912196828e074ed21ab4a349afb93a816cf6788f563f36c9e0708a00a5": {
                "Name": "dkc1",
                "EndpointID": "3ddb6c7fd885c94d75d3e7bfbf37facc37778bffb01e7eeee02d42f790bba718",
                "MacAddress": "02:42:c0:a8:1e:64",
                "IPv4Address": "192.168.30.100/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.name": "br0"
        },
        "Labels": {}
    }
]
2-2.VlanTagを付ける場合のBridge

nmcliコマンドによりVlan+Bridgeインターフェースを作成し、コンテナのNICをLinuxBridgeにアタッチします。
トラフィックがVlanインターフェースens34.301を通過する際に以下の挙動となります。

コンテナから外部NWへのトラフィック VlanTagが付けられる
外部NWからコンテナへのトラフィック VlanTagが外されたる

(5)(6)(7)Vlanインターフェースens34.301+Bridgeインターフェースbr301の作成+ens34.301をbr301にアタッチ
(8)dockerコマンドにてbr301を作成
(9)br301にコンテナdkc2のeth1をアタッチ+IP設定

(5)(6)(7)Vlanインターフェースens34.301+Bridgeインターフェースbr301の作成+ens34.301をbr301にアタッチ
(1)(2)と同様に過去記事などを参照してください。

投入コマンド
(5)
nmcli connection add type bridge autoconnect yes con-name br301 ifname br301
nmcli connection modify br301 bridge.stp no
nmcli connection modify br301 ipv6.method ignore
nmcli connection modify br301 ipv4.method manual ipv4.addresses 192.168.31.202/24
nmcli connection up br301
nmcli con show
brctl show

(6)
nmcli connection add type vlan autoconnect yes con-name ens34.301 ifname ens34.301 dev ens34 id 301
nmcli con show
brctl show

(7)
nmcli connection modify ens34.301 connection.master br301 connection.slave-type bridge
nmcli connection up ens34.301
nmcli con show
brctl show

出力例
以下のように出力されていればOKです。
[root@c76dk01 ~]# nmcli con show
NAME       UUID                                  TYPE      DEVICE
br0        5c7da373-af73-4cda-a420-7949eeb6974e  bridge    br0
br301      07f444fd-18d5-47a8-a721-39696d4fb0c6  bridge    br301
docker0    d3c2e742-6653-4d56-8b75-10d7f178fc41  bridge    docker0
ens33      2f7e32c0-adfd-41b1-9698-dff6406af75d  ethernet  ens33
ens34      2849b0b6-1c27-4293-81b3-a07068feb36c  ethernet  ens34
ens34.301  9e5eb500-f432-41fb-b72a-2492567a98c4  vlan      ens34.301

br301が作成され、VLANインターフェースens34.301にもアタッチされます。

(8)dockerコマンドにてbr301を作成

投入コマンド
(8)
docker network create -d bridge \
--subnet=192.168.31.0/24 \
--ip-range=192.168.31.0/25 \
--gateway=192.168.31.202 \
--opt com.docker.network.bridge.name=br301 \
br301

出力例
[root@c76dk01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
e14f9d9ab5f2        br0                 bridge              local
ce879f2b276f        br301               bridge              local
a6ae25cd104e        bridge              bridge              local
f51b9d166f07        host                host                local
d1023dacb10b        none                null                local

[root@c76dk01 ~]# docker network inspect br301
[
    {
        "Name": "br301",
        "Id": "ce879f2b276f71ca45f6f09b993d561f42b3297b40d2964b1518ef64280dfd0f",
        "Created": "2019-06-16T19:08:44.613109443+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.31.0/24",
                    "IPRange": "192.168.31.0/25",
                    "Gateway": "192.168.31.202"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.name": "br301"
        },
        "Labels": {}
    }
]
docker network create -d bridge \ NWドライバにbridgeを選択。必須
--subnet=192.168.31.0/24 \ サブネットを定義。必須
--ip-range=192.168.31.0/25 \ DHCPで配布されるレンジを定義。任意
--gateway=192.168.31.202 \ GWアドレスを定義。任意。但し、設定しないと192.168.31.1が強制的に設定されます。また、nmcliコマンドで作成したbr0のIPも192.168.31.1に上書きされます。
--opt com.docker.network.bridge.name=br301 \ nmcliコマンドで作成したbr301にアタッチ。必須
br301 Docker上のNWの名前。必須。ですが任意の名前でOK。管理上nmcliコマンドで作成したbr301と名前を一致せています。


(9)br301にコンテナdkc2のeth1をアタッチ+IP設定
続いてコンテナを起動し、コンテナNICのeth1をbr301にアタッチさせます。

投入コマンド
(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc2 \
centos \
/sbin/init

(4)
docker network connect br301 dkc2 \
--ip=192.168.31.100

出力例
[root@c76dk01 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.000c29d40546       no              ens34
                                                        veth41095a7
br301           8000.000c29d40546       no              ens34.301
                                                        veth2d8f44e
docker0         8000.0242f2b40eff       no              veth24c4ace
                                                        veth2cc58e3

[root@c76dk01 ~]# docker network inspect br301
[
    {
        "Name": "br301",
        "Id": "ce879f2b276f71ca45f6f09b993d561f42b3297b40d2964b1518ef64280dfd0f",
        "Created": "2019-06-16T19:08:44.613109443+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.31.0/24",
                    "IPRange": "192.168.31.0/25",
                    "Gateway": "192.168.31.202"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "2ae29b5d870975ad25f86c674113ea4ef6db077f88c9de13c35d3b9f4dc94ecc": {
                "Name": "dkc2",
                "EndpointID": "0d46e4d5f92e68613096c8103714cf90fafde1ff3145c156cc6a9b76b66dc8fa",
                "MacAddress": "02:42:c0:a8:1f:64",
                "IPv4Address": "192.168.31.100/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.name": "br301"
        },
        "Labels": {}
    }
]

以上がLinuxBridge併用の場合となります。

3.dockerコマンドのみの場合

作業工程としては、LinuxBridgeを併用する場合よりもシンプルかつ工程が少ないのでわかりやすいかもしれません。
しかし、ホストOS上では、MACアドレステーブルやarpテーブルの確認が不可能っぽいです。*4
かつ、ホストOSとの疎通性はありません。*5
なお、本項を試す場合は、前項までに作成したコンテナやBridge など*6は全て削除しておいてください。

3-1.通常のBridge

dockerコマンドによりBridgeネットワークを作成し、ens34にアタッチします。
(3)dockerコマンドにてbr0を作成
(4)br0にコンテナdkc1のeth1をアタッチ+IP設定

(3)dockerコマンドにてbr0を作成

投入コマンド
(3)
docker network create -d macvlan \
--subnet=192.168.30.0/24 \
--ip-range=192.168.30.0/25 \
--gateway=192.168.30.254 \
-o parent=ens34 br0

出力例
以下のように出力されていればOKです。
[root@c76dk01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
92bc5bdf05b4        br0                 macvlan             local
a6ae25cd104e        bridge              bridge              local
f51b9d166f07        host                host                local
d1023dacb10b        none                null                local
docker network create -d macvlan \ NWドライバにmacvlanを指定。必須
--subnet=192.168.30.0/24 \ 2.LinuxBridge併用の場合と同様
--ip-range=192.168.30.0/25 \ 2.LinuxBridge併用の場合と同様
--gateway=192.168.30.254 \ 2.LinuxBridge併用の場合と同様
-o parent=ens34 br0 ens34にアタッチ。必須。名前は2.LinuxBridge併用の場合と同様に任意の名前でOKです。


(4)br0にコンテナdkc1のeth1をアタッチ+IP設定

投入コマンド
(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc1 \
centos \
/sbin/init

(4)
docker network connect br0 dkc1 \
--ip=192.168.30.100

出力例
[root@c76dk01 ~]# docker network inspect br0
[
    {
        "Name": "br0",
        "Id": "92bc5bdf05b4371123b3562325260de03ad2133a63ee6f50a4380bd1bbeeb220",
        "Created": "2019-06-16T19:27:48.575931685+09:00",
        "Scope": "local",
        "Driver": "macvlan",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.30.0/24",
                    "IPRange": "192.168.30.0/25",
                    "Gateway": "192.168.30.254"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "a86cfcb7c7729c2f5aa0ad1c5cbae1a84229328a1342d5670a7e3eb6159c5f39": {
                "Name": "dkc1",
                "EndpointID": "cbfdff9a7d5fd97cabc408c2a2bbb5766c0192c989952997ab09996e6ba3696c",
                "MacAddress": "02:42:c0:a8:1e:64",
                "IPv4Address": "192.168.30.100/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "parent": "ens34"
        },
        "Labels": {}
    }
]
3-2.VlanTagを付ける場合のBridge

dockerコマンドによりBridgeネットワークとVlanインターフェースを作成し、ens34.301にアタッチします。
(8)dockerコマンドにてbr301とens34.301を作成
(9)br301にコンテナdkc2のeth1をアタッチ+IP設定

dockerコマンドにてbr301とens34.301を作成

投入コマンド
(8)
docker network create -d macvlan \
--subnet=192.168.31.0/24 \
--ip-range=192.168.31.0/25 \
--gateway=192.168.31.254 \
-o parent=ens34.301 br301

出力例
以下のように出力されていればOKです。
[root@c76dk01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
92bc5bdf05b4        br0                 macvlan             local
8dd7d4bfec8c        br301               macvlan             local
a6ae25cd104e        bridge              bridge              local
f51b9d166f07        host                host                local
d1023dacb10b        none                null                local
docker network create -d macvlan \ NWドライバにmacvlanを指定。必須
--subnet=192.168.31.0/24 \ 2.LinuxBridge併用の場合と同様
--ip-range=192.168.31.0/25 \ 2.LinuxBridge併用の場合と同様
--gateway=192.168.31.254 \ 2.LinuxBridge併用の場合と同様
-o parent=ens34.301 br301 ens34.301とbr301を作成。*7br301をens34.301にアタッチ。必須。名前は2.LinuxBridge併用の場合と同様に任意の名前でOKです。

(9)br301にコンテナdkc2のeth1をアタッチ+IP設定

投入コマンド
(コンテナ起動)
docker run -itd \
--privileged \
--network bridge \
--name dkc2 \
centos \
/sbin/init

(9)
docker network connect br301 dkc2 \
--ip=192.168.31.100

出力例
[root@c76dk01 ~]# docker network inspect br301
[
    {
        "Name": "br301",
        "Id": "8dd7d4bfec8c0717acec3b40bc7cdf3d49ced0e2a2ac0a737d094f1ada2eec8c",
        "Created": "2019-06-16T19:28:00.783746421+09:00",
        "Scope": "local",
        "Driver": "macvlan",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.31.0/24",
                    "IPRange": "192.168.31.0/25",
                    "Gateway": "192.168.31.254"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9a193996a6928474d792f88b9b72f21fbe8f4b46cd973e8ad2ba39b97d4adcaa": {
                "Name": "dkc2",
                "EndpointID": "279d95c111a3b33a7f8872966d15bd5af5251a4e25d46e31a64772a6930cb1e5",
                "MacAddress": "02:42:c0:a8:1f:64",
                "IPv4Address": "192.168.31.100/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "parent": "ens34.301"
        },
        "Labels": {}
    }
]

以上です。

4.最後に

以下のサイトを参考にさせて頂きました。
Use macvlan networks | Docker Documentation
macvlan_ipvlan_driver_notes.md · GitHub
外部ネットワーク側からDockerコンテナに通信できる環境を作成する - Qiita

今回の設定方法以外にも「DOCKER_OPTS=」のオプションを設定することでできるようです。

当然ながらDockerは多くのDocに恵まれているため、さほど苦労することなく、やりたい事ができるようになりました。
ただ、今回ご紹介した2種類の方法が同時に記載されているサイトは少なかったことや、過去記事からの延長として、LinuxBridgeやLXC/LXDとの比較ができるという点で、まとめた方が良いなと感じたため記載しました。

私の本職はNWエンジニアなので、最下層レイヤから上位層レイヤに昇っていく過程で、必要になりそうなポイントをクローズアップしながら記載していければいいなと考えています。
また、この流れが出来てしまったので、当然ですが、SR-IOVやDPDK、OvSによるDockerネットワークの設定方法なども、まとめられたらいいなと思います。
さらに、k8sのネットワーク周りまで踏み込んだり、OpenStackNeutron+OVNにも広げていけたら面白うそうだと考えていますので、ご期待ください。

*1:docker network create -d bridgeコマンドで作るBridgeのことです

*2:Dockerの場合はLXCとは異なり、コンテナ起動後にあまりyumなどを実行することはないと思いますが。

*3:作成というよりも、LinuxBridgeにアタッチするとか関連付けをすると言った方が良いかもしれません。

*4:RESTを使えばGETできるかもしれません

*5:トラブった際が少し不安ですね。

*6:nmcliコマンドによるBridge やVLANインターフェース、dockerコマンドによるNW設定やコンテナ

*7:-o parent=ens34.301と指定しただけで、VLANインターフェースを作成してくれるため、かなり楽です。

freeDiameterのビルドとインストール

CentOS6によるfree Daimeterのビルドとインストール方法について記載しました。
PCEFとPCRFの双方を構築しGxインターフェースの動きを確認します。

1.構成

1-1.環境
HostOS                           : Windows10pro Ver:1809 Build:17763.503
VMWare              : VMware(R) Workstation 15 Pro 15.1.0 build-13591040  
GuestOS              : CentOS6.10
Installed Environment Groups     : minimal
Kernel              : 2.6.32-754

上記GuestOS上でPCEFとPCRFを稼働させます。*1

1-2.構成概要

f:id:metonymical:20190608140611p:plain

1-3.全体の流れ

事前準備
ビルド&インストール
CAの構築
PCEFの設定
PCRFの設定
動作確認

2.事前準備

必要となるアプリなどのインストール

yum -y install gcc gcc-c++ cmake make flex bison lksctp-tools-devel gnutls-devel libidn-devel openssl libgcrypt-devel wget git

3.ビルド&インストール

freeDiameterのインストールを行います。

mkdir tmp
cd /root/tmp
wget http://www.freediameter.net/hg/freeDiameter/archive/1.2.0.tar.gz
tar zxvf 1.2.0.tar.gz
cd /root/tmp/freeDiameter-1.2.0
mkdir build
cd /root/tmp/freeDiameter-1.2.0/build

任意のPathにfreedaimeterのソースをDL
解凍後、ビルド用ディレクトリを作成してcd

cmake -D CMAKE_INSTALL_PREFIX:PATH=/opt/freeDiameter ..
make && make install

makeファイル作成後、ビルド&インストール

多少時間は掛かりますが、最後の方は以下のように出力されれば正常にインストールが完了しています。

cmake後の出力例
-- Generating done
-- Build files have been written to: /root/tmp/freeDiameter-1.2.0/build

make install後の出力例
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_eap.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_dcca.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_dcca_3gpp.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_dcca_starent.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_sip.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_mip6a.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_mip6i.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_nas_mipv6.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dict_rfc5777.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/rt_default.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/rt_redirect.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/rt_busypeers.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/rt_ignore_dh.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/rt_load_balance.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/acl_wl.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dbg_monitor.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dbg_msg_timings.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dbg_msg_dumps.fdx
-- Installing: /opt/freeDiameter/lib/freeDiameter/dbg_rt.fdx

4.CAの構築

freedaimeterは互いに証明書を使用して認証するためCAを構築します。

4-1.CAの構築前準備1
vi /etc/pki/tls/openssl.cnf

以下を修正
[ CA_default ]

#dir             = /etc/pki/CA           # Where everything is kept
dir             = .
4-2.CAの構築前準備2
mkdir -p /opt/CA
cd /opt/CA
mkdir certs private newcerts
echo '01' > serial
touch index.txt

ディレクトリ作成後にcd
各種ディレクトリ作成
シリアルファイル作成
indexファイル作成

4-3.CAの構築
openssl req -new -x509 -newkey rsa:512 -out cacert.pem -keyout private/cakey-pass.pem
openssl rsa < private/cakey-pass.pem > private/cakey.pem

CA証明書の作成
CA証明書の鍵からパスフレーズの除外

以下出力例

[root@c610diam01 CA]# openssl req -new -x509 -newkey rsa:512 -out cacert.pem -keyout private/cakey-pass.pem
Generating a 512 bit RSA private key
.++++++++++++
..++++++++++++
writing new private key to 'private/cakey-pass.pem'
Enter PEM pass phrase: 任意のパスワードを入力
Verifying - Enter PEM pass phrase: 任意のパスワードを入力
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) :Tokyo
Locality Name (eg, city) [Default City]:Minato-ku
Organization Name (eg, company) [Default Company Ltd]:local.jp
Organizational Unit Name (eg, section) :  空Enter
Common Name (eg, your name or your server's hostname) : ca.local.jp
Email Address :  空Enter

[root@c610diam01 CA]# openssl rsa < private/cakey-pass.pem > private/cakey.pem
Enter pass phrase: 上記のパスワードを入力
writing RSA key

5.PCEFの設定

5-1.PCEF用の証明書発行
cd /opt/CA
openssl req -new -newkey rsa:512 -keyout private/c610diam01-pass.key -out private/c610diam01.csr
openssl rsa < private/c610diam01-pass.key > private/c610diam01.key
openssl ca -in private/c610diam01.csr -out newcerts/c610diam01.crt

PCEF用CSR&鍵の作成
鍵からパスフレーズの除外
PCEF用CSRに署名

以下、出力例

[root@c610diam01 CA]# openssl req -new -newkey rsa:512 -keyout private/c610diam01-pass.key -out private/c610diam01.csr
Generating a 512 bit RSA private key
.++++++++++++
...........++++++++++++
writing new private key to 'private/c610diam01-pass.key'
Enter PEM pass phrase: 任意のパスワードを入力
Verifying - Enter PEM pass phrase: 任意のパスワードを入力
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) :Tokyo
Locality Name (eg, city) [Default City]:Minato-ku
Organization Name (eg, company) [Default Company Ltd]:local.jp
Organizational Unit Name (eg, section) :  空Enter
Common Name (eg, your name or your server's hostname) :c610diam01.local.jp
Email Address :  空Enter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password :  空Enter
An optional company name :  空Enter

[root@c610diam01 CA]# openssl rsa < private/c610diam01-pass.key > private/c610diam01.key
Enter pass phrase: 上記のパスワードを入力
writing RSA key

[root@c610diam01 CA]# openssl ca -in private/c610diam01.csr -out newcerts/c610diam01.crt
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Jun  8 02:41:08 2019 GMT
            Not After : Jun  7 02:41:08 2020 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = local.jp
            commonName                = c610diam01.local.jp
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                60:37:2C:A4:B6:7F:49:1D:A6:4C:22:D3:BE:BC:7F:88:1D:D4:D6:0C
            X509v3 Authority Key Identifier:
                keyid:8F:0F:1D:B8:82:F6:9F:84:26:2B:95:56:C5:7C:16:EB:55:F6:4E:DF

Certificate is to be certified until Jun  7 02:41:08 2020 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
5-2.PCEF用拡張モジュールの追加
cd /root/tmp
git clone https://github.com/kamome-e/fd_extensions.git
cd /root/tmp/fd_extensions/bin/
tar zxvf pcef.tar.gz
cd /root/tmp/fd_extensions/bin/pcef/
cp -p app_pcef.fdx dict_gx.fdx /opt/freeDiameter/lib/freeDiameter/
cp pcef-ctl.sh /opt/freeDiameter/bin/

任意のディレクトリ作成
git clone後にcd
解凍後にcd
fdx(拡張モジュール)ファイルのコピー
shファイルのコピー

5-3.freeDaimeter.confの設定
mkdir /opt/freeDiameter/etc
cd /opt/freeDiameter/etc/
vi freeDiameter.conf

#freeDiameter.conf

Identity =              "c610diam01.local.jp";
Realm =                 "local.jp";
TcTimer =               30;
TwTimer =               30;
AppServThreads =        4;

Port =                  3868;
SecPort =               5868;
SCTP_streams =          30;
ListenOn =              "0.0.0.0";

TLS_Cred =              "/opt/CA/newcerts/c610diam01.crt", "/opt/CA/private/c610diam01.key";
TLS_CA =                "/opt/CA/cacert.pem";

LoadExtension =         "/opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx";
LoadExtension =         "/opt/freeDiameter/lib/freeDiameter/dict_gx.fdx";
LoadExtension =         "/opt/freeDiameter/lib/freeDiameter/app_pcef.fdx" : "/opt/freeDiameter/etc/app_pcef.conf";

ConnectPeer =           "c610diam02.local.jp"{NO_TLS; No_SCTP; };

<補足>
最終行の

No_SCTP;

について。
本当はSCTPでやり取りしている様をPcapしたかったもののライブラリへのリンクが上手くいってないようでエラーが出力されたため、泣く泣く設定を入れました。*2

5-4.pcef.confの設定

destination_realmのみ変更してください。

cd /root/tmp/fd_extensions/bin/pcef/
cp -p app_pcef.conf /opt/freeDiameter/etc/
vi /opt/freeDiameter/etc/app_pcef.conf

signal = 10;
work_dir = "/tmp/freeDiameter";
destination_realm = "local.jp";
imsi = "017635273633";
default_charging_rule_name = "default-policy";
5-5.PCEF起動確認
export LD_LIBRARY_PATH=/opt/freeDiameter/lib
/opt/freeDiameter/bin/freeDiameterd -c /opt/freeDiameter/etc/freeDiameter.conf

以下出力例です。

[root@c610diam01 pcef]# /opt/freeDiameter/bin/freeDiameterd -c /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,11:52:45.172063  NOTI   libfdproto '1.2.0' initialized.
06/08/19,11:52:45.173929  NOTI   libgnutls '2.12.23' initialized.
06/08/19,11:52:45.174303  NOTI   libfdcore '1.2.0' initialized.
06/08/19,11:52:45.316111  NOTI   All extensions loaded.
06/08/19,11:52:45.316133  NOTI   freeDiameter configuration:
06/08/19,11:52:45.316136  NOTI     Default trace level .... : +3
06/08/19,11:52:45.316138  NOTI     Configuration file ..... : /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,11:52:45.316140  NOTI     Diameter Identity ...... : c610diam01.local.jp (l:19)
06/08/19,11:52:45.316142  NOTI     Diameter Realm ......... : local.jp (l:8)
06/08/19,11:52:45.316144  NOTI     Tc Timer ............... : 30
06/08/19,11:52:45.316146  NOTI     Tw Timer ............... : 30
06/08/19,11:52:45.316148  NOTI     Local port ............. : 3868
06/08/19,11:52:45.316150  NOTI     Local secure port ...... : 5868
06/08/19,11:52:45.316152  NOTI     Number of SCTP streams . : 30
06/08/19,11:52:45.316154  NOTI     Number of clients thr .. : 5
06/08/19,11:52:45.316156  NOTI     Number of app threads .. : 4
06/08/19,11:52:45.316158  NOTI     Local endpoints ........ : Default (use all available)
06/08/19,11:52:45.316160  NOTI     Local applications ..... : App: 16777238,AuAc,Vnd:0
06/08/19,11:52:45.316162  NOTI     Flags : - IP ........... : Enabled
06/08/19,11:52:45.316164  NOTI             - IPv6 ......... : Enabled
06/08/19,11:52:45.316184  NOTI             - Relay app .... : Enabled
06/08/19,11:52:45.316187  NOTI             - TCP .......... : Enabled
06/08/19,11:52:45.316189  NOTI             - SCTP ......... : Enabled
06/08/19,11:52:45.316191  NOTI             - Pref. proto .. : SCTP
06/08/19,11:52:45.316193  NOTI             - TLS method ... : Separate port
06/08/19,11:52:45.316195  NOTI     TLS :   - Certificate .. : /opt/CA/newcerts/c610diam01.crt
06/08/19,11:52:45.316197  NOTI             - Private key .. : /opt/CA/private/c610diam01.key
06/08/19,11:52:45.316199  NOTI             - CA (trust) ... : /opt/CA/cacert.pem (1 certs)
06/08/19,11:52:45.316201  NOTI             - CRL .......... : (none)
06/08/19,11:52:45.316203  NOTI             - Priority ..... : (default: 'NORMAL')
06/08/19,11:52:45.316205  NOTI             - DH bits ...... : 1024
06/08/19,11:52:45.316207  NOTI     Origin-State-Id ........ : 1559962365
06/08/19,11:52:45.316211  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx'[(no config file)], loaded
06/08/19,11:52:45.316213  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_gx.fdx'[(no config file)], loaded
06/08/19,11:52:45.316215  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/app_pcef.fdx'[/opt/freeDiameter/etc/app_pcef.conf], loaded
06/08/19,11:52:45.316219  NOTI   {signal:10}'app_pcef'->0x7f2921bcfa20
06/08/19,11:52:45.342450  NOTI   Local server address(es): 192.168.11.161{---L-}        192.168.30.161{---L-}
06/08/19,11:52:45.342506  NOTI   freeDiameterd daemon initialized.

6.PCRFの設定

6-1.PCRF用の証明書発行
cd /opt/CA
openssl req -new -newkey rsa:512 -keyout private/c610diam02-pass.key -out private/c610diam02.csr
openssl rsa < private/c610diam02-pass.key > private/c610diam02.key
openssl ca -in private/c610diam02.csr -out newcerts/c610diam02.crt

PCRF用CSR&鍵の作成
鍵からパスフレーズの除外
PCRF用CSRに署名

以下、出力例

[root@c610diam02 CA]# openssl req -new -newkey rsa:512 -keyout private/c610diam02-pass.key -out private/c610diam02.csr
Generating a 512 bit RSA private key
.....++++++++++++
...............................++++++++++++
writing new private key to 'private/c610diam02-pass.key'
Enter PEM pass phrase: 任意のパスワードを入力
Verifying - Enter PEM pass phrase: 任意のパスワードを入力
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) :Tokyo
Locality Name (eg, city) [Default City]:Minato-ku
Organization Name (eg, company) [Default Company Ltd]:local.jp
Organizational Unit Name (eg, section) :  空Enter
Common Name (eg, your name or your server's hostname) :c610diam02.local.jp
Email Address :  空Enter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password :  空Enter
An optional company name :  空Enter

[root@c610diam02 CA]# openssl rsa < private/c610diam02-pass.key > private/c610diam02.key
Enter pass phrase: 上記のパスワードを入力
writing RSA key

[root@c610diam02 CA]# openssl ca -in private/c610diam02.csr -out newcerts/c610diam02.crt
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Jun  8 02:58:22 2019 GMT
            Not After : Jun  7 02:58:22 2020 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = local.jp
            commonName                = c610diam02.local.jp
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                58:48:A9:29:C0:63:60:17:EA:79:49:ED:3C:62:71:69:3C:E1:9D:92
            X509v3 Authority Key Identifier:
                keyid:8F:0F:1D:B8:82:F6:9F:84:26:2B:95:56:C5:7C:16:EB:55:F6:4E:DF

Certificate is to be certified until Jun  7 02:58:22 2020 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
6-2.PCRF用拡張モジュールの追加
cd /root/tmp/fd_extensions/bin/
tar zxvf pcrf.tar.gz
cd /root/tmp/fd_extensions/bin/pcrf/
cp -p app_pcrf.fdx dict_gx.fdx /opt/freeDiameter/lib/freeDiameter/

cd後にpcrfのtarファイル解凍
cd後にコピー*3

6-3.freeDaimeter.confの設定
vi /opt/freeDiameter/etc/freeDiameter.conf

[root@c610diam02 ~]# vi /opt/freeDiameter/etc/freeDiameter.conf
#freeDiameter.conf

Identity =              "c610diam02.local.jp";
Realm =                 "local.jp";
TcTimer =               30;
TwTimer =               30;
AppServThreads =        4;

Port =                  3868;
SecPort =               5868;
SCTP_streams =          30;
ListenOn =              "0.0.0.0";

TLS_Cred =              "/opt/CA/newcerts/c610diam02.crt", "/opt/CA/private/c610diam02.key";
TLS_CA =                "/opt/CA/cacert.pem";

LoadExtension =         "/opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx";
LoadExtension =         "/opt/freeDiameter/lib/freeDiameter/dict_gx.fdx";
LoadExtension =         "/opt/freeDiameter/lib/freeDiameter/app_pcrf.fdx" : "/opt/freeDiameter/etc/app_pcrf.conf";

ConnectPeer =           "c610diam01.local.jp"{NO_TLS; No_SCTP; };
6-4.pcrf.confの設定

特に変更する箇所はありません。

cd /root/tmp/fd_extensions/bin/pcrf/
cp app_pcrf.conf /opt/freeDiameter/etc/
vi /opt/freeDiameter/etc/app_pcrf.conf

[root@c610diam02 pcrf]# vi /opt/freeDiameter/etc/app_pcrf.conf

monitoring_key = "test-monitoring-key";
initial_charging_rule_name = "high-speed-policy";
restricted_charging_rule_name = "low-speed-policy";
total_octets_threshold = 20;
input_octets_threshold = 10;
output_octets_threshold = 10;
6-5.PCRF起動確認
export LD_LIBRARY_PATH=/opt/freeDiameter/lib
/opt/freeDiameter/bin/freeDiameterd -c /opt/freeDiameter/etc/freeDiameter.conf

以下、出力例です。

[root@c610diam02 pcrf]# /opt/freeDiameter/bin/freeDiameterd -c /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,12:04:05.801044  NOTI   libfdproto '1.2.0' initialized.
06/08/19,12:04:05.801570  NOTI   libgnutls '2.12.23' initialized.
06/08/19,12:04:05.801772  NOTI   libfdcore '1.2.0' initialized.
06/08/19,12:04:05.911066  NOTI   All extensions loaded.
06/08/19,12:04:05.911114  NOTI   freeDiameter configuration:
06/08/19,12:04:05.911120  NOTI     Default trace level .... : +3
06/08/19,12:04:05.911122  NOTI     Configuration file ..... : /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,12:04:05.911124  NOTI     Diameter Identity ...... : c610diam02.local.jp (l:19)
06/08/19,12:04:05.911126  NOTI     Diameter Realm ......... : local.jp (l:8)
06/08/19,12:04:05.911128  NOTI     Tc Timer ............... : 30
06/08/19,12:04:05.911130  NOTI     Tw Timer ............... : 30
06/08/19,12:04:05.911132  NOTI     Local port ............. : 3868
06/08/19,12:04:05.911134  NOTI     Local secure port ...... : 5868
06/08/19,12:04:05.911136  NOTI     Number of SCTP streams . : 30
06/08/19,12:04:05.911138  NOTI     Number of clients thr .. : 5
06/08/19,12:04:05.911140  NOTI     Number of app threads .. : 4
06/08/19,12:04:05.911142  NOTI     Local endpoints ........ : Default (use all available)
06/08/19,12:04:05.911144  NOTI     Local applications ..... : App: 16777238,AuAc,Vnd:0
06/08/19,12:04:05.911147  NOTI     Flags : - IP ........... : Enabled
06/08/19,12:04:05.911149  NOTI             - IPv6 ......... : Enabled
06/08/19,12:04:05.911151  NOTI             - Relay app .... : Enabled
06/08/19,12:04:05.911153  NOTI             - TCP .......... : Enabled
06/08/19,12:04:05.911155  NOTI             - SCTP ......... : Enabled
06/08/19,12:04:05.911157  NOTI             - Pref. proto .. : SCTP
06/08/19,12:04:05.911159  NOTI             - TLS method ... : Separate port
06/08/19,12:04:05.911161  NOTI     TLS :   - Certificate .. : /opt/CA/newcerts/c610diam02.crt
06/08/19,12:04:05.911163  NOTI             - Private key .. : /opt/CA/private/c610diam02.key
06/08/19,12:04:05.911165  NOTI             - CA (trust) ... : /opt/CA/cacert.pem (1 certs)
06/08/19,12:04:05.911168  NOTI             - CRL .......... : (none)
06/08/19,12:04:05.911170  NOTI             - Priority ..... : (default: 'NORMAL')
06/08/19,12:04:05.911172  NOTI             - DH bits ...... : 1024
06/08/19,12:04:05.911174  NOTI     Origin-State-Id ........ : 1559963045
06/08/19,12:04:05.911178  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx'[(no config file)], loaded
06/08/19,12:04:05.911180  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_gx.fdx'[(no config file)], loaded
06/08/19,12:04:05.911182  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/app_pcrf.fdx'[/opt/freeDiameter/etc/app_pcrf.conf], loaded
06/08/19,12:04:05.938652  NOTI   Local server address(es): 192.168.11.162{---L-}        192.168.30.162{---L-}
06/08/19,12:04:05.938693  NOTI   freeDiameterd daemon initialized.

既にPCEFが起動中であれば、接続が開始されると思いますが、上記の出力例はPCEFが起動していない状態での出力となります。

7.動作確認

7-1.PCRF起動
[root@c610diam02 ~]# /opt/freeDiameter/bin/freeDiameterd -c /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,12:08:49.011248  NOTI   libfdproto '1.2.0' initialized.
06/08/19,12:08:49.011937  NOTI   libgnutls '2.12.23' initialized.
06/08/19,12:08:49.012197  NOTI   libfdcore '1.2.0' initialized.
06/08/19,12:08:49.114938  NOTI   All extensions loaded.
06/08/19,12:08:49.114959  NOTI   freeDiameter configuration:
06/08/19,12:08:49.114963  NOTI     Default trace level .... : +3
06/08/19,12:08:49.114965  NOTI     Configuration file ..... : /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,12:08:49.114967  NOTI     Diameter Identity ...... : c610diam02.local.jp (l:19)
06/08/19,12:08:49.114969  NOTI     Diameter Realm ......... : local.jp (l:8)
06/08/19,12:08:49.114971  NOTI     Tc Timer ............... : 30
06/08/19,12:08:49.114973  NOTI     Tw Timer ............... : 30
06/08/19,12:08:49.114975  NOTI     Local port ............. : 3868
06/08/19,12:08:49.114977  NOTI     Local secure port ...... : 5868
06/08/19,12:08:49.114979  NOTI     Number of SCTP streams . : 30
06/08/19,12:08:49.114981  NOTI     Number of clients thr .. : 5
06/08/19,12:08:49.114983  NOTI     Number of app threads .. : 4
06/08/19,12:08:49.114985  NOTI     Local endpoints ........ : Default (use all available)
06/08/19,12:08:49.114987  NOTI     Local applications ..... : App: 16777238,AuAc,Vnd:0
06/08/19,12:08:49.114989  NOTI     Flags : - IP ........... : Enabled
06/08/19,12:08:49.114991  NOTI             - IPv6 ......... : Enabled
06/08/19,12:08:49.114993  NOTI             - Relay app .... : Enabled
06/08/19,12:08:49.114995  NOTI             - TCP .......... : Enabled
06/08/19,12:08:49.114997  NOTI             - SCTP ......... : Enabled
06/08/19,12:08:49.114999  NOTI             - Pref. proto .. : SCTP
06/08/19,12:08:49.115001  NOTI             - TLS method ... : Separate port
06/08/19,12:08:49.115003  NOTI     TLS :   - Certificate .. : /opt/CA/newcerts/c610diam02.crt
06/08/19,12:08:49.115005  NOTI             - Private key .. : /opt/CA/private/c610diam02.key
06/08/19,12:08:49.115007  NOTI             - CA (trust) ... : /opt/CA/cacert.pem (1 certs)
06/08/19,12:08:49.115010  NOTI             - CRL .......... : (none)
06/08/19,12:08:49.115011  NOTI             - Priority ..... : (default: 'NORMAL')
06/08/19,12:08:49.115014  NOTI             - DH bits ...... : 1024
06/08/19,12:08:49.115016  NOTI     Origin-State-Id ........ : 1559963329
06/08/19,12:08:49.115019  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx'[(no config file)], loaded
06/08/19,12:08:49.115021  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_gx.fdx'[(no config file)], loaded
06/08/19,12:08:49.115023  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/app_pcrf.fdx'[/opt/freeDiameter/etc/app_pcrf.conf], loaded
06/08/19,12:08:49.115728  NOTI   Local server address(es): 192.168.11.162{---L-}        192.168.30.162{---L-}
06/08/19,12:08:49.115774  NOTI   freeDiameterd daemon initialized.

7-2.PCEF起動
[root@c610diam01 ~]# /opt/freeDiameter/bin/freeDiameterd -c /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,12:09:04.765012  NOTI   libfdproto '1.2.0' initialized.
06/08/19,12:09:04.765733  NOTI   libgnutls '2.12.23' initialized.
06/08/19,12:09:04.766007  NOTI   libfdcore '1.2.0' initialized.
06/08/19,12:09:04.949999  NOTI   All extensions loaded.
06/08/19,12:09:04.950020  NOTI   freeDiameter configuration:
06/08/19,12:09:04.950023  NOTI     Default trace level .... : +3
06/08/19,12:09:04.950026  NOTI     Configuration file ..... : /opt/freeDiameter/etc/freeDiameter.conf
06/08/19,12:09:04.950028  NOTI     Diameter Identity ...... : c610diam01.local.jp (l:19)
06/08/19,12:09:04.950030  NOTI     Diameter Realm ......... : local.jp (l:8)
06/08/19,12:09:04.950032  NOTI     Tc Timer ............... : 30
06/08/19,12:09:04.950034  NOTI     Tw Timer ............... : 30
06/08/19,12:09:04.950036  NOTI     Local port ............. : 3868
06/08/19,12:09:04.950038  NOTI     Local secure port ...... : 5868
06/08/19,12:09:04.950040  NOTI     Number of SCTP streams . : 30
06/08/19,12:09:04.950042  NOTI     Number of clients thr .. : 5
06/08/19,12:09:04.950044  NOTI     Number of app threads .. : 4
06/08/19,12:09:04.950046  NOTI     Local endpoints ........ : Default (use all available)
06/08/19,12:09:04.950048  NOTI     Local applications ..... : App: 16777238,AuAc,Vnd:0
06/08/19,12:09:04.950050  NOTI     Flags : - IP ........... : Enabled
06/08/19,12:09:04.950052  NOTI             - IPv6 ......... : Enabled
06/08/19,12:09:04.950055  NOTI             - Relay app .... : Enabled
06/08/19,12:09:04.950057  NOTI             - TCP .......... : Enabled
06/08/19,12:09:04.950058  NOTI             - SCTP ......... : Enabled
06/08/19,12:09:04.950061  NOTI             - Pref. proto .. : SCTP
06/08/19,12:09:04.950062  NOTI             - TLS method ... : Separate port
06/08/19,12:09:04.950065  NOTI     TLS :   - Certificate .. : /opt/CA/newcerts/c610diam01.crt
06/08/19,12:09:04.950067  NOTI             - Private key .. : /opt/CA/private/c610diam01.key
06/08/19,12:09:04.950069  NOTI             - CA (trust) ... : /opt/CA/cacert.pem (1 certs)
06/08/19,12:09:04.950071  NOTI             - CRL .......... : (none)
06/08/19,12:09:04.950073  NOTI             - Priority ..... : (default: 'NORMAL')
06/08/19,12:09:04.950075  NOTI             - DH bits ...... : 1024
06/08/19,12:09:04.950077  NOTI     Origin-State-Id ........ : 1559963344
06/08/19,12:09:04.950080  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_nasreq.fdx'[(no config file)], loaded
06/08/19,12:09:04.950083  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/dict_gx.fdx'[(no config file)], loaded
06/08/19,12:09:04.950085  NOTI   Loaded extensions: '/opt/freeDiameter/lib/freeDiameter/app_pcef.fdx'[/opt/freeDiameter/etc/app_pcef.conf], loaded
06/08/19,12:09:04.950089  NOTI   {signal:10}'app_pcef'->0x7f641a9f5a20
06/08/19,12:09:04.950797  NOTI   Local server address(es): 192.168.11.161{---L-}        192.168.30.161{---L-}
06/08/19,12:09:04.950838  NOTI   freeDiameterd daemon initialized.
以下はPCRFへの接続時に出力されます。
06/08/19,12:09:04.953215  NOTI   Connected to 'c610diam02.local.jp' (TCP,soc#16), remote capabilities:
06/08/19,12:09:04.953224  NOTI      'Capabilities-Exchange-Answer'
06/08/19,12:09:04.953245  NOTI        Version: 0x01
06/08/19,12:09:04.953247  NOTI        Length: 236
06/08/19,12:09:04.953249  NOTI        Flags: 0x00 (----)
06/08/19,12:09:04.953251  NOTI        Command Code: 257
06/08/19,12:09:04.953253  NOTI        ApplicationId: 0
06/08/19,12:09:04.953255  NOTI        Hop-by-Hop Identifier: 0x40404F68
06/08/19,12:09:04.953257  NOTI        End-to-End Identifier: 0x6D04E4B6
06/08/19,12:09:04.953259  NOTI         {internal data}: src:c610diam02.local.jp(19) rwb:(nil) rt:2 cb:(nil),(nil)(nil) qry:0x7f6420000ba0 asso:0 sess:(nil)
06/08/19,12:09:04.953262  NOTI         AVP: 'Result-Code'(268) l=12 f=-M val='DIAMETER_SUCCESS' (2001 (0x7d1))
06/08/19,12:09:04.953264  NOTI         AVP: 'Origin-Host'(264) l=27 f=-M val="c610diam02.local.jp"
06/08/19,12:09:04.953266  NOTI         AVP: 'Origin-Realm'(296) l=16 f=-M val="local.jp"
06/08/19,12:09:04.953268  NOTI         AVP: 'Origin-State-Id'(278) l=12 f=-M val=1559963329 (0x5cfb26c1)
06/08/19,12:09:04.953271  NOTI         AVP: 'Host-IP-Address'(257) l=14 f=-M val=192.168.11.162
06/08/19,12:09:04.953273  NOTI         AVP: 'Host-IP-Address'(257) l=14 f=-M val=192.168.30.162
06/08/19,12:09:04.953275  NOTI         AVP: 'Vendor-Id'(266) l=12 f=-M val=0 (0x0)
06/08/19,12:09:04.953277  NOTI         AVP: 'Product-Name'(269) l=20 f=-- val="freeDiameter"
06/08/19,12:09:04.953279  NOTI         AVP: 'Firmware-Revision'(267) l=12 f=-- val=10200 (0x27d8)
06/08/19,12:09:04.953281  NOTI         AVP: 'Auth-Application-Id'(258) l=12 f=-M val=16777238 (0x1000016)
06/08/19,12:09:04.953284  NOTI         AVP: 'Acct-Application-Id'(259) l=12 f=-M val=16777238 (0x1000016)
06/08/19,12:09:04.953286  NOTI         AVP: 'Auth-Application-Id'(258) l=12 f=-M val=4294967295 (0xffffffff)
06/08/19,12:09:04.953288  NOTI         AVP: 'Supported-Vendor-Id'(265) l=12 f=-M val=5535 (0x159f)
06/08/19,12:09:04.953290  NOTI         AVP: 'Supported-Vendor-Id'(265) l=12 f=-M val=10415 (0x28af)
06/08/19,12:09:04.953292  NOTI         AVP: 'Supported-Vendor-Id'(265) l=12 f=-M val=13019 (0x32db)
06/08/19,12:09:04.953299  NOTI   No TLS protection negotiated with peer 'c610diam02.local.jp'.
06/08/19,12:09:04.953396  NOTI   'STATE_WAITCEA'        -> 'STATE_OPEN' 'c610diam02.local.jp'

7-3.PCEF起動後のPCRF側の出力
06/08/19,12:09:05.045712  NOTI   Connected to 'c610diam01.local.jp' (TCP,soc#12), remote capabilities:
06/08/19,12:09:05.045726  NOTI      'Capabilities-Exchange-Request'
06/08/19,12:09:05.045729  NOTI        Version: 0x01
06/08/19,12:09:05.045731  NOTI        Length: 236
06/08/19,12:09:05.045733  NOTI        Flags: 0x80 (R---)
06/08/19,12:09:05.045735  NOTI        Command Code: 257
06/08/19,12:09:05.045737  NOTI        ApplicationId: 0
06/08/19,12:09:05.045739  NOTI        Hop-by-Hop Identifier: 0x40404F68
06/08/19,12:09:05.045741  NOTI        End-to-End Identifier: 0x6D04E4B6
06/08/19,12:09:05.045743  NOTI         {internal data}: src:(nil)(0) rwb:(nil) rt:0 cb:(nil),(nil)(nil) qry:(nil) asso:1 sess:(nil)
06/08/19,12:09:05.045746  NOTI         AVP: 'Origin-Host'(264) l=27 f=-M val="c610diam01.local.jp"
06/08/19,12:09:05.045748  NOTI         AVP: 'Origin-Realm'(296) l=16 f=-M val="local.jp"
06/08/19,12:09:05.045750  NOTI         AVP: 'Origin-State-Id'(278) l=12 f=-M val=1559963344 (0x5cfb26d0)
06/08/19,12:09:05.045752  NOTI         AVP: 'Host-IP-Address'(257) l=14 f=-M val=192.168.11.161
06/08/19,12:09:05.045754  NOTI         AVP: 'Host-IP-Address'(257) l=14 f=-M val=192.168.30.161
06/08/19,12:09:05.045756  NOTI         AVP: 'Vendor-Id'(266) l=12 f=-M val=0 (0x0)
06/08/19,12:09:05.045758  NOTI         AVP: 'Product-Name'(269) l=20 f=-- val="freeDiameter"
06/08/19,12:09:05.045761  NOTI         AVP: 'Firmware-Revision'(267) l=12 f=-- val=10200 (0x27d8)
06/08/19,12:09:05.045763  NOTI         AVP: 'Inband-Security-Id'(299) l=12 f=-M val='NO_INBAND_SECURITY' (0 (0x0))
06/08/19,12:09:05.045765  NOTI         AVP: 'Auth-Application-Id'(258) l=12 f=-M val=16777238 (0x1000016)
06/08/19,12:09:05.045767  NOTI         AVP: 'Acct-Application-Id'(259) l=12 f=-M val=16777238 (0x1000016)
06/08/19,12:09:05.045769  NOTI         AVP: 'Auth-Application-Id'(258) l=12 f=-M val=4294967295 (0xffffffff)
06/08/19,12:09:05.045771  NOTI         AVP: 'Supported-Vendor-Id'(265) l=12 f=-M val=5535 (0x159f)
06/08/19,12:09:05.045774  NOTI         AVP: 'Supported-Vendor-Id'(265) l=12 f=-M val=10415 (0x28af)
06/08/19,12:09:05.045776  NOTI         AVP: 'Supported-Vendor-Id'(265) l=12 f=-M val=13019 (0x32db)
06/08/19,12:09:05.045858  NOTI   No TLS protection negotiated with peer 'c610diam01.local.jp'.
06/08/19,12:09:05.046000  NOTI   'STATE_CLOSED' -> 'STATE_OPEN' 'c610diam01.local.jp'
7-4.PCEF側のテストコマンド

以下のコマンドは全てPCEF側で投入します。
Daimeterサービスはフォアグラウンドで起動するため、以下のコマンドを打つためには、PCEF側でもう一つターミナル画面を出してください。

/opt/freeDiameter/bin/pcef-ctl.sh dump
/opt/freeDiameter/bin/pcef-ctl.sh init
/opt/freeDiameter/bin/pcef-ctl.sh update-input
/opt/freeDiameter/bin/pcef-ctl.sh update-output
7-5.状態確認

コマンドを打つと、Daimeterサービスがフォアグラウンドで起動しているターミナル画面に以下の出力が出ます。
何もポリシーが当たっていない状態です。

/opt/freeDiameter/bin/pcef-ctl.sh dump


06/08/19,12:10:02.779425  NOTI   -------------- User session state dump --------------
06/08/19,12:10:02.779452  NOTI   IMSI:                      017635273633
06/08/19,12:10:02.779456  NOTI   Charging rule name:        default-policy
06/08/19,12:10:02.779458  NOTI   Used total octets:         0
06/08/19,12:10:02.779460  NOTI   Used input octets:         0
06/08/19,12:10:02.779480  NOTI   Used output octets:        0
06/08/19,12:10:02.779482  NOTI   =================== Dump complete ===================
7-6.初期化

以下のコマンドにて初期のポリシーを当てます。

/opt/freeDiameter/bin/pcef-ctl.sh init
06/08/19,12:11:22.635425  NOTI   Sending initial request...
06/08/19,12:11:22.636343  NOTI   Received initial answer.

/opt/freeDiameter/bin/pcef-ctl.sh dump
06/08/19,12:11:57.275226  NOTI   -------------- User session state dump --------------
06/08/19,12:11:57.275234  NOTI   IMSI:                      017635273633
06/08/19,12:11:57.275236  NOTI   Charging rule name:        default-policy
06/08/19,12:11:57.275239  NOTI   Charging rule name:        high-speed-policy
06/08/19,12:11:57.275241  NOTI   Monitoring key:            test-monitoring-key
06/08/19,12:11:57.275243  NOTI     Total octets threshold:  20
06/08/19,12:11:57.275245  NOTI     Input octets threshold:  10
06/08/19,12:11:57.275246  NOTI     Output octets threshold: 10
06/08/19,12:11:57.275248  NOTI   Used total octets:         0
06/08/19,12:11:57.275250  NOTI   Used input octets:         0
06/08/19,12:11:57.275252  NOTI   Used output octets:        0
06/08/19,12:11:57.275254  NOTI   =================== Dump complete ===================
7-7.アップデート

以下のコマンドにてアップデートしていきます。
例えるなら、PGWやDPI装置にパケットが流れることにより、データ量がカウントされているようなイメージです。*4

/opt/freeDiameter/bin/pcef-ctl.sh update-input

06/08/19,12:12:24.735514  NOTI   Updated used input octets. [0->1]

上記コマンドを繰り返し打つと以下のように閾値(Input octets threshold: 10)に近づいていきます。

06/08/19,12:12:24.735514  NOTI   Updated used input octets. [0->1]
06/08/19,12:12:48.084391  NOTI   Updated used input octets. [1->2]
06/08/19,12:12:48.668832  NOTI   Updated used input octets. [2->3]
06/08/19,12:12:49.141213  NOTI   Updated used input octets. [3->4]
06/08/19,12:12:49.624475  NOTI   Updated used input octets. [4->5]
06/08/19,12:12:50.142395  NOTI   Updated used input octets. [5->6]
06/08/19,12:12:50.669159  NOTI   Updated used input octets. [6->7]
06/08/19,12:12:51.189578  NOTI   Updated used input octets. [7->8]
06/08/19,12:12:51.743437  NOTI   Updated used input octets. [8->9]
06/08/19,12:12:52.278174  NOTI   Updated used input octets. [9->10]
06/08/19,12:12:52.278194  NOTI   Sending update request...
06/08/19,12:12:52.278843  NOTI   Received update answer.

閾値に到達した後、状態確認をすると、新しいルールが適用されています。

/opt/freeDiameter/bin/pcef-ctl.sh dump

06/08/19,12:13:18.653228  NOTI   -------------- User session state dump --------------
06/08/19,12:13:18.653236  NOTI   IMSI:                      017635273633
06/08/19,12:13:18.653239  NOTI   Charging rule name:        default-policy
06/08/19,12:13:18.653241  NOTI   Charging rule name:        low-speed-policy
06/08/19,12:13:18.653243  NOTI   Used total octets:         10
06/08/19,12:13:18.653245  NOTI   Used input octets:         10
06/08/19,12:13:18.653247  NOTI   Used output octets:        0
06/08/19,12:13:18.653249  NOTI   =================== Dump complete ===================

以上です。

8.最後に

以下の書籍を参考にさせて頂きました。
O'Reilly Japan - Diameterプロトコルガイド
以下のサイトを参考にさせて頂きました。
freeDiameterdのインストール記録 第1回:ITエンジニア兼きもの屋のフリーライフ:エンジニアライフ

上記の書籍は、Diameterプロトコルや機能拡張に関するアーキテクチャについて理解するという点では、大変よくまとまっているため本当にお勧めです。

また、最近出版された以下の書籍もちょっと気になっています。
Diameter: New Generation AAA Protocol - Design, Practice and Applications

つい先日(6/2)、freeDiameterの1.3.2がリリースされていましたので、ちょっとキャッチアップしていこうかなと考えています。

*1:CentOS7系で試したところSegmentation Faultが出てしまったので、CentOS6系になっています。。

*2:SCTP自体は、eNodeB-MME間やCiscoのBox-to-Box NATなどでも使用されているため、そこまでニッチなプロトコルではないかと思います。

*3:dict_gx.fdxの上書き確認メッセージが表示されたらyでOKです

*4:通常、通信量の管理はGyインターフェースにてOCSが行いますので、あくまでもイメージとして捉えてください。通常、通信ポリシーの管理(ルールの適用など)はGxインターフェースにてPCRFが行います。

Open Stack Neutron環境構築 その4:NW設定と確認方法

ルータ作成やネットワーク&サブネット作成、そしてインスタンスの起動などについて記載していきます。
また、構成の詳細や、その確認方法についても後述します。

  1. 構成概要
  2. ルータ作成
  3. 外部NW(GW_NET)設定
  4. 内部NW(SV_NET)設定
  5. インスタンス(srv1)作成
  6. Trunk用NW(TR_NET)設定
  7. インスタンス(srv2)作成
  8. 構成詳細

1.構成概要

以下のようなNWを構築していきます。
f:id:metonymical:20190529163243p:plain
しかし、この図だけでは内部的なことはわからないため、8.構成詳細にて詳しく記載します。

なお、ダッシュボードにログインし、プロジェクト>ネットワーク>ネットワークトポロジーと進み、上記の画面を開いておいてください。2.~7.の作業を行うたびに、ネットワークトポロジーが少しづつ変化していく過程を確認できると思います。

2.ルータ作成

対象:Controllerのみ

openstack router create \
--distributed \
DV_RT

3.外部NW(GW_NET)設定

対象:Controllerのみ

3-1.NW作成
openstack network create \
--external \
--provider-network-type vlan \
--provider-physical-network physnet1 \
--provider-segment 30 \
GW_NET
3-2.サブネット作成
openstack subnet create \
--subnet-range 10.30.0.0/24 \
--no-dhcp \
--network GW_NET \
--allocation-pool start=10.30.0.128,end=10.30.0.223 \
GW_SNET
3-3.NWをルータにアタッチ
openstack router set \
--external-gateway GW_NET \
DV_RT
3-4.ポートとMACアドレステーブルの確認
#各Bridgeのポート番号を確認
ovs-ofctl show br-ens35
ovs-ofctl show br-int

#各BridgeのMACアドレステーブルを確認
ovs-appctl fdb/show br-ens35
ovs-appctl fdb/show br-int

4.内部NW(SV_NET)設定

対象:Controllerのみ

4-1.NW作成
openstack network create \
SV_NET
4-2.サブネット作成
openstack subnet create \
--subnet-range 192.168.200.0/24 \
--network SV_NET \
--dns-nameserver 8.8.8.8 \
SV_SNET
4-3.NWをルータにアタッチ
openstack router add \
subnet DV_RT \
SV_SNET

5.インスタンス(srv1)作成

対象:Controllerのみ

5-1.Flavor作成

簡易的なFlavorを作成しておきます。

#Cirros用
openstack flavor create \
--ram 512 \
--disk 1 \
m1

#Ubuntu
openstack flavor create \
--ram 512 \
--disk 10 \
m2
5-2.インスタンス(srv1)作成

compute01上にsrv1を作成します。

openstack server create \
--flavor m1 \
--image cirros-0.4.0 \
--availability-zone nova:compute01 \
--nic net-id=SV_NET \
srv1

6.Trunk用NW(TR_NET)設定

対象:Controllerのみ

6-1.NW作成
openstack network create \
--provider-network-type vlan \
--provider-physical-network physnet1 \
--provider-segment 300 \
TR_NET
6-2.サブネット作成
openstack subnet create \
--subnet-range 192.168.30.0/24 \
--network TR_NET \
--gateway 192.168.30.254 \
--allocation-pool start=192.168.30.128,end=192.168.30.223 \
--dns-nameserver 8.8.8.8 \
TR_SNET
6-3.親ポートの作成
openstack port create \
--network SV_NET P01
6-4.サブポートの作成

任意ですがDHCPで取得するアドレスを固定にしています。

openstack port create \
--network TR_NET P01_C01 \
--fixed-ip ip-address=192.168.30.100
6-5.Trunkの作成

親ポートとサブポートを関連付けて、Trunkを作成します。

openstack network trunk create \
--parent-port P01 \
--subport port=P01_C01,segmentation-type=vlan,segmentation-id=300 \
TRK1
6-6.MACアドレスの確認

サブポートP01_C01のMACアドレスをメモっておきます。
以下の例の場合、

P01_C01 fa:16:3e:37:12:36

になります。

openstack port list

root@controller01:~# openstack port list
+--------------------------------------+---------+-------------------+-------------------------------------------------------------------------------+--------+
| ID                                   | Name    | MAC Address       | Fixed IP Addresses                                                            | Status |
+--------------------------------------+---------+-------------------+-------------------------------------------------------------------------------+--------+
| 01ae96f9-c8bd-4149-8f7f-c936d0d038b9 |         | fa:16:3e:33:c7:36 | ip_address='10.30.0.132', subnet_id='e8168d18-ed3c-43d0-a950-9c9a6b635377'    | ACTIVE |
| 2eeb7f80-786c-4ba2-bd53-734da88114fe |         | fa:16:3e:7e:02:41 | ip_address='10.30.0.141', subnet_id='e8168d18-ed3c-43d0-a950-9c9a6b635377'    | ACTIVE |
| 33af164d-654e-4923-8a09-1f41c26fee37 |         | fa:16:3e:55:11:84 | ip_address='192.168.200.1', subnet_id='72151365-841f-4e6c-8b2b-1d9ed2898e7b'  | ACTIVE |
| 40442390-2fe7-4844-95ee-4a43c0296a59 | P01_C01 | fa:16:3e:37:12:36 | ip_address='192.168.30.100', subnet_id='0b313de3-b203-471a-9c26-edfeb8e14880' | ACTIVE |
| 64457abd-f622-4a9a-a61e-ecd9a118731d |         | fa:16:3e:1a:39:83 | ip_address='10.30.0.129', subnet_id='e8168d18-ed3c-43d0-a950-9c9a6b635377'    | ACTIVE |
| 859c401f-0e2e-4d65-8fd2-5e9137d4a3a2 | P01     | fa:16:3e:db:91:fd | ip_address='192.168.200.7', subnet_id='72151365-841f-4e6c-8b2b-1d9ed2898e7b'  | ACTIVE |
| 9872b8b5-c44f-49d9-a547-982949ffd9be |         | fa:16:3e:b7:ac:a1 | ip_address='192.168.30.128', subnet_id='0b313de3-b203-471a-9c26-edfeb8e14880' | ACTIVE |
| bb5d66dc-241d-43ff-95bd-8bf5e9034b9e |         | fa:16:3e:cd:9a:f3 | ip_address='10.30.0.135', subnet_id='e8168d18-ed3c-43d0-a950-9c9a6b635377'    | ACTIVE |
| c5d7fa51-0de0-49bf-92b3-00d3e7b3c7d1 |         | fa:16:3e:08:b2:10 | ip_address='192.168.200.2', subnet_id='72151365-841f-4e6c-8b2b-1d9ed2898e7b'  | ACTIVE |
| d11c5401-13e9-46f2-9cd0-3e5c242fa995 |         | fa:16:3e:58:39:d7 | ip_address='192.168.200.3', subnet_id='72151365-841f-4e6c-8b2b-1d9ed2898e7b'  | ACTIVE |
| d55e11c2-abcf-4425-afb2-3199a90bf2dc |         | fa:16:3e:66:30:85 | ip_address='192.168.200.18', subnet_id='72151365-841f-4e6c-8b2b-1d9ed2898e7b' | ACTIVE |
+--------------------------------------+---------+-------------------+-------------------------------------------------------------------------------+--------+

7.インスタンス(srv2)作成

対象:Controllerのみ

7-1.パスワードファイル作成
vi /root/udata.txt

#cloud-config
password: ubuntu
chpasswd: { expire: False }
ssh_pwauth: True
7-2.インスタンス(srv2)作成

Compute02上にsrv2を作成します。
user-dataとして、udata.txtを読込みます。
親ポートP01に接続させます。

openstack server create \
--flavor m2 \
--image ubuntu-xenial-16.04 \
--availability-zone nova:compute02 \
--user-data udata.txt \
--nic port-id=P01 \
srv2
7-3.インスタンスの設定

対象:Compute02からsrv2コンソールログインして実施
インスタンスにログイン後、以下の設定を実施。
サブポートP01_C01にアサインされたMACアドレスfa:16:3e:37:12:36を設定してください。
最後にdhcpでアドレス取得要求を行うと、サブポートに設定した192.168.30.100が取得できます。

sudo su
ip link add link ens3 name ens3.300 type vlan id 300
ip link set dev ens3.300 address fa:16:3e:37:12:36
ip link set ens3.300 up
dhclient ens3.300

以下出力例です。

root@compute02:~# virsh list
 Id    Name                           State
----------------------------------------------------
 1     instance-00000002              running

root@compute02:~# virsh console instance-00000002
Connected to domain instance-00000002
Escape character is ^]

Ubuntu 16.04.6 LTS srv2 ttyS0

srv2 login: ubuntu
Password: ubuntu
Last login: Wed May 29 06:03:11 UTC 2019 on ttyS0
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-148-generic x86_64)

ubuntu@srv2:~$ sudo su
sudo: unable to resolve host srv2
root@srv2:/home/ubuntu# cd
root@srv2:~# ip link add link ens3 name ens3.300 type vlan id 300
root@srv2:~# ip link set dev ens3.300 address fa:16:3e:37:12:36
root@srv2:~# ip link set ens3.300 up
root@srv2:~# dhclient ens3.300
root@srv2:~# ip add show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default 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
2: ens3:  mtu 1450 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fa:16:3e:db:91:fd brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.7/24 brd 192.168.200.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fedb:91fd/64 scope link
       valid_lft forever preferred_lft forever
3: ens3.300@ens3:  mtu 1450 qdisc noqueue state UP group default qlen 1000
    link/ether fa:16:3e:37:12:36 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.100/24 brd 192.168.30.255 scope global ens3.300
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe37:1236/64 scope link
       valid_lft forever preferred_lft forever

8.構成詳細

8-1.構成

以下の図は第1回目で記載しました。
f:id:metonymical:20190527141522p:plain
各Nodeのens35より内側(左側)の詳細構成が以下となります。
f:id:metonymical:20190529175507p:plain
<補足>
Brdigeには1重下線、Routerには2重下線を入れています。
br-intよりも左側がNamespaceで作成されたRouterです。
v1~3はNeutron内部で使用されるVLAN IDです。Flowテーブルにより以下に書き換えられています。

VLAN1 VLAN56 SV_NET *1
VLAN2 VLAN30 GW_NET
VLAN3 VLAN300 TR_NET


論理構成だけを記載したものが以下となります。
f:id:metonymical:20190529175834p:plain

8-2.確認方法:L2レベルの確認

ここでは例としてController01のbr-intで行ってみます。

ovs-vsctl show
ovs-ofctl show br-int
ovs-appctl fdb/show br-int
ovs-ofctl dump-flows br-int
ovs-appctl ofproto/trace br-int in_port=n

以下出力例です。
もっと多くの補足を入れたいのですが、膨大な量になるため割愛します。

br-intのポート名や内部VLAN番号の確認*2

ovs-vsctl show

root@controller01:~# ovs-vsctl show
01a7c9a9-3ae0-45dd-8eda-f46aa41c164c
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Bridge br-int
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port "sg-d11c5401-13"
            tag: 1
            Interface "sg-d11c5401-13"
                type: internal
        Port br-int
            Interface br-int
                type: internal
        Port "qr-33af164d-65"
            tag: 1
            Interface "qr-33af164d-65"
                type: internal
        Port "int-br-ens35"
            Interface "int-br-ens35"
                type: patch
                options: {peer="phy-br-ens35"}
        Port "tapc5d7fa51-0d"
            tag: 1
            Interface "tapc5d7fa51-0d"
                type: internal
        Port "tap9872b8b5-c4"
            tag: 3
            Interface "tap9872b8b5-c4"
                type: internal
        Port "qg-2eeb7f80-78"
            tag: 2
            Interface "qg-2eeb7f80-78"
                type: internal
        Port patch-tun
            Interface patch-tun
                type: patch
                options: {peer=patch-int}
        Port "fg-bb5d66dc-24"
            tag: 2
            Interface "fg-bb5d66dc-24"
                type: internal
    ovs_version: "2.8.4"

br-intのポート番号の確認

ovs-ofctl show br-int

root@controller01:~# ovs-ofctl show br-int
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000e678379a3b46
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 1(int-br-ens35): addr:c2:7b:ab:ac:4b:1f
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 2(patch-tun): addr:7a:5e:f6:c2:45:26
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 3(qr-33af164d-65): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 4(sg-d11c5401-13): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 5(fg-bb5d66dc-24): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 6(tapc5d7fa51-0d): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 7(qg-2eeb7f80-78): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 13(tap9872b8b5-c4): addr:00:00:00:00:00:00
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
 LOCAL(br-int): addr:e6:78:37:9a:3b:46
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0

br-intのMacアドレステーブルの確認

ovs-appctl fdb/show br-int

root@controller01:~# ovs-appctl fdb/show br-int
 port  VLAN  MAC                Age
    1     2  2c:53:4a:01:27:66   38
    1     3  2c:53:4a:01:27:66   38

br-intのフローテーブルの確認
赤文字はフローテーブルによりVLANIDが書き換えられている箇所です。

ovs-ofctl dump-flows br-int

root@controller01:~# ovs-ofctl dump-flows br-int
 cookie=0xab814f17f876c4e7, duration=18281.635s, table=0, n_packets=0, n_bytes=0, priority=4,in_port="int-br-ens35",dl_src=fa:16:3f:05:7d:26 actions=resubmit(,2)
 cookie=0xab814f17f876c4e7, duration=18281.634s, table=0, n_packets=0, n_bytes=0, priority=2,in_port="patch-tun",dl_src=fa:16:3f:05:7d:26 actions=resubmit(,1)
 cookie=0xab814f17f876c4e7, duration=18281.632s, table=0, n_packets=210, n_bytes=18620, priority=4,in_port="int-br-ens35",dl_src=fa:16:3f:53:4c:80 actions=resubmit(,2)
 cookie=0xab814f17f876c4e7, duration=18281.631s, table=0, n_packets=0, n_bytes=0, priority=2,in_port="patch-tun",dl_src=fa:16:3f:53:4c:80 actions=resubmit(,1)
 cookie=0xab814f17f876c4e7, duration=18207.228s, table=0, n_packets=35, n_bytes=3684, priority=3,in_port="int-br-ens35",dl_vlan=56 actions=mod_vlan_vid:1,resubmit(,60)
 cookie=0xab814f17f876c4e7, duration=18203.240s, table=0, n_packets=1773, n_bytes=754143, priority=3,in_port="int-br-ens35",dl_vlan=30 actions=mod_vlan_vid:2,resubmit(,60)
 cookie=0xab814f17f876c4e7, duration=16350.937s, table=0, n_packets=1235, n_bytes=226168, priority=3,in_port="int-br-ens35",dl_vlan=300 actions=mod_vlan_vid:3,resubmit(,60)
 cookie=0xab814f17f876c4e7, duration=18281.646s, table=0, n_packets=310, n_bytes=41445, priority=2,in_port="int-br-ens35" actions=drop
 cookie=0xab814f17f876c4e7, duration=18281.778s, table=0, n_packets=564, n_bytes=514595, priority=0 actions=resubmit(,60)
 cookie=0xab814f17f876c4e7, duration=18281.646s, table=1, n_packets=0, n_bytes=0, priority=1 actions=drop
 cookie=0xab814f17f876c4e7, duration=18205.312s, table=2, n_packets=203, n_bytes=17846, priority=4,dl_vlan=56,dl_dst=fa:16:3e:58:39:d7 actions=mod_dl_src:fa:16:3e:55:11:84,resubmit(,60)
 cookie=0xab814f17f876c4e7, duration=16262.886s, table=2, n_packets=0, n_bytes=0, priority=4,dl_vlan=56,dl_dst=fa:16:3e:08:b2:10 actions=mod_dl_src:fa:16:3e:55:11:84,resubmit(,60)
 cookie=0xab814f17f876c4e7, duration=18281.646s, table=2, n_packets=7, n_bytes=774, priority=1 actions=drop
 cookie=0xab814f17f876c4e7, duration=18281.647s, table=23, n_packets=0, n_bytes=0, priority=0 actions=drop
 cookie=0xab814f17f876c4e7, duration=18281.777s, table=24, n_packets=0, n_bytes=0, priority=0 actions=drop
 cookie=0xab814f17f876c4e7, duration=18205.312s, table=60, n_packets=203, n_bytes=17846, priority=4,dl_vlan=56,dl_dst=fa:16:3e:58:39:d7 actions=strip_vlan,output:"sg-d11c5401-13"
 cookie=0xab814f17f876c4e7, duration=16262.885s, table=60, n_packets=0, n_bytes=0, priority=4,dl_vlan=56,dl_dst=fa:16:3e:08:b2:10 actions=strip_vlan,output:"tapc5d7fa51-0d"
 cookie=0xab814f17f876c4e7, duration=18281.777s, table=60, n_packets=3607, n_bytes=1498590, priority=3 actions=NORMAL

br-intのフローのトレース

ovs-appctl ofproto/trace br-int in_port=n
#nは、ovs-ofctl show br-intの出力で得られたポート番号

root@controller01:~# ovs-appctl ofproto/trace br-int in_port=7
Flow: in_port=7,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000

bridge("br-int")
----------------
 0. priority 0, cookie 0xab814f17f876c4e7
    goto_table:60
60. priority 3, cookie 0xab814f17f876c4e7
    NORMAL
     -> no learned MAC for destination, flooding

    bridge("br-ens35")
    ------------------
         0. in_port=2, priority 2, cookie 0xc29c894d4abba2e2
            goto_table:1
         1. priority 0, cookie 0xc29c894d4abba2e2
            goto_table:2
         2. in_port=2,dl_vlan=2, priority 4, cookie 0xc29c894d4abba2e2
            set_field:4126->vlan_vid
            NORMAL
             -> no learned MAC for destination, flooding

bridge("br-tun")
----------------
 0. in_port=1, priority 1, cookie 0x151d0b9924ed6dbf
    goto_table:1
 1. priority 0, cookie 0x151d0b9924ed6dbf
    goto_table:2
 2. dl_dst=00:00:00:00:00:00/01:00:00:00:00:00, priority 0, cookie 0x151d0b9924ed6dbf
    goto_table:20
20. priority 0, cookie 0x151d0b9924ed6dbf
    goto_table:22
22. priority 0, cookie 0x151d0b9924ed6dbf
    drop

Final flow: unchanged
Megaflow: recirc_id=0,eth,in_port=7,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
Datapath actions: push_vlan(vid=2,pcp=0),7,pop_vlan,push_vlan(vid=30,pcp=0),2,1,pop_vlan,6
8-3.確認方法:L3レベルの確認

ここでは例としてController01で確認していきます。

ip netns
ip netns exec `ip netns | awk 'NR==5'` ip add show
ip netns exec `ip netns | awk 'NR==5'` ip route show
ip netns exec `ip netns | awk 'NR==5'` ip rule show
ip netns exec `ip netns | awk 'NR==5'` ip route show table NUMEBER

以下がController01のNamespaceに作成されたRouterとなります。

ip netns

root@controller01:~# ip netns
qdhcp-8fd11879-9c07-4130-9cd5-e2f1034394dc
qdhcp-10364a89-8a6e-499d-bee3-03f4085b745e
fip-a53cf798-1c15-4597-aeca-8b8917aa81fd
snat-e83bd724-c0da-42d0-b43e-0d6a923e1c5b
qrouter-e83bd724-c0da-42d0-b43e-0d6a923e1c5b

各Routerのポートやアドレスを確認する場合、

ip netns exec qrouter-e83bd724-c0da-42d0-b43e-0d6a923e1c5b ip add show

とコマンド入力するのは大変です。

このため、awkを使って以下のようにします。
NR==5は、ip netnsの出力結果の5行目(qrouter~)に該当します。

ip netns exec `ip netns | awk 'NR==5'` ip add show

root@controller01:~# ip netns exec `ip netns | awk 'NR==5'` ip add show
1: lo:  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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: rfp-e83bd724-c:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 16:b3:ee:52:8f:c0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 169.254.106.114/31 scope global rfp-e83bd724-c
       valid_lft forever preferred_lft forever
    inet6 fe80::14b3:eeff:fe52:8fc0/64 scope link
       valid_lft forever preferred_lft forever
14: qr-33af164d-65:  mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether fa:16:3e:55:11:84 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.1/24 brd 192.168.200.255 scope global qr-33af164d-65
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe55:1184/64 scope link
       valid_lft forever preferred_lft forever

次にqrouterのRoutingTableを確認します。
Default Routeが無いため、これではInternetに出られませんので、Default Routeを確認します。

ip netns exec `ip netns | awk 'NR==5'` ip route show

root@controller01:~# ip netns exec `ip netns | awk 'NR==5'` ip route show
169.254.106.114/31 dev rfp-e83bd724-c  proto kernel  scope link  src 169.254.106.114
192.168.200.0/24 dev qr-33af164d-65  proto kernel  scope link  src 192.168.200.1

以下のコマンドでruleを表示させます。
最終行の番号をメモしておいてください。

ip netns exec `ip netns | awk 'NR==5'` ip rule show

root@controller01:~# ip netns exec `ip netns | awk 'NR==5'` ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
3232286721:     from 192.168.200.1/24 lookup 3232286721

以下のコマンドで3232286721のRoutingTableを確認します。

ip netns exec `ip netns | awk 'NR==5'` ip route show table NUMBER

root@controller01:~# ip netns exec `ip netns | awk 'NR==5'` ip route show table 3232286721
default via 192.168.200.3 dev qr-33af164d-65

これらのコマンドを全Nodeの全Bridgeや全Namespaceに対して行っていくと、詳細構成が明らかになってきます。

8-4.トラフィックフロー:FlotingIP使用時

f:id:metonymical:20190529190803p:plain
FlotingIPを使用している場合は、ComputeNodeから外部NWへそのまま送信されます。

8-5.トラフィックフロー:SourceNAT使用時

f:id:metonymical:20190529190824p:plain
一方、NAT(PAT)を使用している場合は、一度ControllerNodeのsnatへ行った後、NATされて外部NWへ送信されます。

なお、特に触れませんが、Trunkした箇所*3については、論理構成に記載した通り、VLAN ID300が付与されRoutingされることなく、Compute02から、そのまま外部NWへ送信されます。

以上です。

9.最後に

以下のサイトを参考にさせて頂きました。
運用する際に理解しておきたい OpenStack Neutron DVR の Packet Flow - Qiita
OpenStack Docs: Keystone Installation Tutorial(Keystone)
OpenStack Docs: Installation(Glance)
OpenStack Docs: Compute service(Nova)
OpenStack Docs: Networking service(Neutron)
OpenStack Docs: Installation Guide(Horizon)

Open Stack Neutron環境構築は今回で最後ですが、まだモヤっとしている部分があると思っていますので、時間があればAppendixとして、もう一回くらい書きたいなと考えています。
MACアドレステーブル、ARPテーブル、Routingテーブルに加えて、Flowテーブルを読み解いていくことにより、詳細なトラフィックフローを完全に理解するというDeepDive的なことができればいいなと。

また、今回は基本的なところしか記載しませんでしたが、今後の発展として、これをベースにGREやVXLANを導入すると、さらに面白くなってきます。
また、OVNを導入してGeneveを使用してみるのも面白いかもしれません。
さらに、SR-IOVやDPDKを導入するのも面白いと思いますので、以下の過去記事などを参考にしてみてください。
Linux nmcliコマンドによるKVM&LXC/LXD with SR-IOVのInterface設定 - Metonymical Deflection
CentOS7 ovs(Open vSwitch)+DPDKのビルドとネットワーク設定方法 - Metonymical Deflection

*1:VLAN56は、前回記事で設定した32~63より自動でアサインされています。

*2:br-tunとbr-ens35も表示されますが削っています。

*3:srv2のens3.300

Open Stack Neutron環境構築 その3:Neutron+OvS+DVR のインストール

Neutron, OvS, DVRのインストールを実施します。*1
ここから徐々に複雑になりますので、ネットワーク、サブネット、ポート、インスタンスなどの作成は次回以降に記載します。

  1. Neutronのインストール
  2. Open vSwitch(L2agent)のインストール
  3. DVR(L3agent)のインストール
  4. その他設定

構成概要やOpen Stackのインストールは、前々回前回の記事を参照してください。

また、前回以上に今回は、Controllerで設定したり、Computeで設定したり、といったことが頻繁に発生するため、今何をやっているのか?が分からなくなってくると思います。
このため、以下の図を参考にしてみてください。ControllerとComputeの役割や機能の違いが少しづつ明確になってくると思います。
f:id:metonymical:20190530073758p:plain

1.Neutronのインストール

1-1.DBの設定・ユーザ登録・サービス登録・Endpoint作成・インストール

対象:Controllerのみ

#DBの設定
mysql

CREATE DATABASE neutron;
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' IDENTIFIED BY 'neutron';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' IDENTIFIED BY 'neutron';
quit;

#ユーザ登録
openstack user create --domain Default --password=neutron neutron
openstack role add --project service --user neutron admin

#サービス登録
openstack service create --name neutron \
--description "OpenStack Networking" network

#Endpoint作成
openstack endpoint create --region RegionOne \
network public http://controller01:9696
openstack endpoint create --region RegionOne \
network internal http://controller01:9696
openstack endpoint create --region RegionOne \
network admin http://controller01:9696

#インストール(NeutronServer, DHCP Agent, Metadata Agent, ML2 Plugin, NeutronClient)
apt -y install neutron-server neutron-dhcp-agent \
neutron-metadata-agent neutron-plugin-ml2 \
python-neutronclient
1-2.neutron.confの設定

対象:Controllerのみ

vi /etc/neutron/neutron.conf

[DEFAULT]
auth_strategy = keystone
transport_url = rabbit://openstack:rabbit@controller01

[database]
#connection = sqlite:////var/lib/neutron/neutron.sqlite
connection = mysql+pymysql://neutron:neutron@controller01/neutron

[keystone_authtoken]
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = neutron

[nova]
auth_url = http://controller01:35357
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = nova
password = nova
1-3.ML2 Pluginのインストール・neutron.confの設定

対象:Computeのみ

apt -y install neutron-plugin-ml2

vi /etc/neutron/neutron.conf

[DEFAULT]
auth_strategy = keystone
transport_url = rabbit://openstack:rabbit@controller01

[database]
#connection = sqlite:////var/lib/neutron/neutron.sqlite
connection = mysql+pymysql://neutron:neutron@controller01/neutron

[keystone_authtoken]
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = neutron
1-4.nova.confの設定

対象:全Node

vi /etc/nova/nova.conf

[neutron]
url= http://controller01:9696
auth_url = http://controller01:35357
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = neutron
password = neutron
1-5.DB登録・設定読込み

対象:Controllerのみ

su -s /bin/sh -c "neutron-db-manage \
--config-file /etc/neutron/neutron.conf \
--config-file /etc/neutron/plugins/ml2/ml2_conf.ini \
upgrade head" neutron

systemctl restart nova-api nova-scheduler nova-conductor

以下出力例です。

root@controller01:~# su -s /bin/sh -c "neutron-db-manage \
> --config-file /etc/neutron/neutron.conf \
> --config-file /etc/neutron/plugins/ml2/ml2_conf.ini \
> upgrade head" neutron
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
  Running upgrade for neutron ...
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> kilo, kilo_initial
INFO  [alembic.runtime.migration] Running upgrade kilo -> 354db87e3225, nsxv_vdr_metadata.py
INFO  [alembic.runtime.migration] Running upgrade 354db87e3225 -> 599c6a226151, neutrodb_ipam
INFO  [alembic.runtime.migration] Running upgrade 599c6a226151 -> 52c5312f6baf, Initial operations in support of address scopes
INFO  [alembic.runtime.migration] Running upgrade 52c5312f6baf -> 313373c0ffee, Flavor framework

~一部省略~

INFO  [alembic.runtime.migration] Running upgrade kilo -> 67c8e8d61d5, Initial Liberty no-op script.
INFO  [alembic.runtime.migration] Running upgrade 67c8e8d61d5 -> 458aa42b14b, fw_table_alter script to make  column case sensitive
INFO  [alembic.runtime.migration] Running upgrade 458aa42b14b -> f83a0b2964d0, rename tenant to project
INFO  [alembic.runtime.migration] Running upgrade f83a0b2964d0 -> fd38cd995cc0, change shared attribute for firewall resource
  OK
root@controller01:~#
1-6.設定読込み

対象:Computeのみ

systemctl restart nova-compute
1-7.DCHP Agentの設定・nova.conf追記・設定読込み

対象:Controllerのみ

#DCHP Agentの設定
vi /etc/neutron/dhcp_agent.ini

[DEFAULT]
enable_isolated_metadata = True

#設定読込み
systemctl restart neutron-server neutron-dhcp-agent


#nova.conf追記
vi /etc/nova/nova.conf

[neutron]
service_metadata_proxy = true
metadata_proxy_shared_secret = MetadataAgentPasswd123
1-8.MetadataAgentの設定

対象:Controllerのみ

#MetadataAgentの設定
vi /etc/neutron/metadata_agent.ini

[DEFAULT]
nova_metadata_host = controller01
metadata_proxy_shared_secret = MetadataAgentPasswd123

#設定読込み
systemctl restart nova-api neutron-metadata-agent
1-9.簡易動作確認

対象:Controllerのみ
以下のようになっていればOKです。

openstack network agent list

root@controller01:~# openstack network agent list
+--------------------------------------+----------------+--------------+-------------------+-------+-------+------------------------+
| ID                                   | Agent Type     | Host         | Availability Zone | Alive | State | Binary                 |
+--------------------------------------+----------------+--------------+-------------------+-------+-------+------------------------+
| 11fca003-8bb0-49b3-9e39-bc60b1a4cf17 | DHCP agent     | controller01 | nova              | :-)   | UP    | neutron-dhcp-agent     |
| b4cd6ed6-2321-4525-9ffa-b52dcbfe7293 | Metadata agent | controller01 | None              | :-)   | UP    | neutron-metadata-agent |
+--------------------------------------+----------------+--------------+-------------------+-------+-------+------------------------+

2.Open vSwitch(L2agent)のインストール

2-1.ML2の設定

対象:Controllerのみ

vi /etc/neutron/plugins/ml2/ml2_conf.ini

[ml2]
mechanism_drivers = l2population,openvswitch
type_drivers = local,flat,vlan,vxlan
tenant_network_types= vlan,vxlan

[ml2_type_vlan]
network_vlan_ranges = physnet1:32:63

[ml2_type_vxlan]
vni_ranges = 128:255

<補足1>
VlanやVxlanのレンジは任意に変更可能です。

[ml2_type_vlan]
network_vlan_ranges = physnet1:1024:2047

[ml2_type_vxlan]
vni_ranges = 512:4095

<補足2>
ens35以外にも外部NW用NICを複数増やしたい場合は以下のような設定も可能です。

[ml2_type_vlan]
network_vlan_ranges = physnet1:32:63,physnet2:64:95

<補足3>
今回は取り上げませんが、flatネットワークを使用する際は以下の設定を行います。

[ml2_type_flat]
flat_networks = physnet1
2-2.ドライバとOvSエージェントの設定

対象:全Node

apt install neutron-plugin-openvswitch-agent -y

vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[agent]
tunnel_types = vxlan
l2_population = true
vxlan_udp_port = 8472

[ovs]
bridge_mappings = physnet1:br-ens35
local_ip = 10.20.0.10x
##xは、Nodeごとに変更##

[securitygroup]
firewall_driver = noop

ovs-vsctl add-br br-ens35
ovs-vsctl add-port br-ens35 ens35
ovs-vsctl show

以下出力例です。

ovs-vsctl show

root@compute02:~# ovs-vsctl show
9a905c31-1f4a-48cd-aa3e-9d2fcb50bdf9
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Bridge "br-ens35"
        Port "br-ens35"
            Interface "br-ens35"
                type: internal
        Port "ens35"
            Interface "ens35"
    Bridge br-int
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    ovs_version: "2.8.4"
2-3.DHCPエージェントの設定

対象:Controller

#dhcp_agent.iniの設定
vi /etc/neutron/dhcp_agent.ini

[DEFAULT]
interface_driver = openvswitch
dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf


#dnsmasq-neutron.confの設定
vi /etc/neutron/dnsmasq-neutron.conf

dhcp-option-force=26,1450


#設定読込み
systemctl restart neutron-dhcp-agent
2-4.簡易動作確認

対象:Controller
以下のように出力されていればOKです。

openstack network agent list

root@controller01:~# openstack network agent list
+--------------------------------------+--------------------+--------------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host         | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+--------------+-------------------+-------+-------+---------------------------+
| 11fca003-8bb0-49b3-9e39-bc60b1a4cf17 | DHCP agent         | controller01 | nova              | :-)   | UP    | neutron-dhcp-agent        |
| 16807ec4-c816-47cd-92eb-45e9e1410705 | Open vSwitch agent | controller01 | None              | :-)   | UP    | neutron-openvswitch-agent |
| 980aa42b-562f-47ae-97e1-015d5b600088 | Open vSwitch agent | compute02    | None              | :-)   | UP    | neutron-openvswitch-agent |
| b4cd6ed6-2321-4525-9ffa-b52dcbfe7293 | Metadata agent     | controller01 | None              | :-)   | UP    | neutron-metadata-agent    |
| ddc78656-71f5-40fc-a9e1-66b03d6de317 | Open vSwitch agent | compute01    | None              | :-)   | UP    | neutron-openvswitch-agent |
+--------------------------------------+--------------------+--------------+-------------------+-------+-------+---------------------------+

3.DVR(L3agent)のインストール

3-1.DVRのインストール&設定・OvS&Neutronの追加設定・Horizon設定

対象:Controllerのみ

#DVRのインストール&設定
apt install neutron-l3-agent -y

vi /etc/neutron/l3_agent.ini

[DEFAULT]
interface_driver = openvswitch
agent_mode = dvr_snat
handle_internal_only_routers = false

#OvSの追加設定
vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[agent]
enable_distributed_routing = True

#Neutronの追加設定
vi /etc/neutron/neutron.conf

[DEFAULT]
service_plugins = router,trunk

#Horizon設定
vi /etc/openstack-dashboard/local_settings.py

OPENSTACK_NEUTRON_NETWORK = {
    'enable_router': True,
    'enable_quotas': False,
    'enable_ipv6': False,
    'enable_distributed_router': True,
    'enable_ha_router': False,
    'enable_lb': False,
    'enable_firewall': False,
    'enable_vpn': False,
    'enable_fip_topology_check': False,
}

#設定読込み
systemctl restart neutron-l3-agent neutron-openvswitch-agent neutron-server apache2
3-2.DVRのインストール&設定・OvSの追加設定

対象:Computeのみ

#DVRのインストール&設定
apt install neutron-l3-agent -y

vi /etc/neutron/l3_agent.ini

[DEFAULT]
interface_driver = openvswitch
agent_mode = dvr
handle_internal_only_routers = false


#OvSの追加設定
vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[agent]
enable_distributed_routing = True

#設定読込み
systemctl restart neutron-l3-agent neutron-openvswitch-agent
3-3.簡易動作確認

対象:Controllerのみ
この時点で以下のように登録されていればOKです。

openstack network agent list

root@controller01:~# openstack network agent list
+--------------------------------------+--------------------+--------------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host         | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+--------------+-------------------+-------+-------+---------------------------+
| 0fdbdf3d-978a-4698-87f5-1d9ec71ccdd7 | Metadata agent     | compute01    | None              | :-)   | UP    | neutron-metadata-agent    |
| 11fca003-8bb0-49b3-9e39-bc60b1a4cf17 | DHCP agent         | controller01 | nova              | :-)   | UP    | neutron-dhcp-agent        |
| 16807ec4-c816-47cd-92eb-45e9e1410705 | Open vSwitch agent | controller01 | None              | :-)   | UP    | neutron-openvswitch-agent |
| 514136b2-cfa0-42ca-8ee5-fe768c895c7c | L3 agent           | controller01 | nova              | :-)   | UP    | neutron-l3-agent          |
| 980aa42b-562f-47ae-97e1-015d5b600088 | Open vSwitch agent | compute02    | None              | :-)   | UP    | neutron-openvswitch-agent |
| b4cd6ed6-2321-4525-9ffa-b52dcbfe7293 | Metadata agent     | controller01 | None              | :-)   | UP    | neutron-metadata-agent    |
| bb83830a-dd80-4ab8-b030-ce1dc1999643 | Metadata agent     | compute02    | None              | :-)   | UP    | neutron-metadata-agent    |
| ddc78656-71f5-40fc-a9e1-66b03d6de317 | Open vSwitch agent | compute01    | None              | :-)   | UP    | neutron-openvswitch-agent |
| e31f5012-53c0-4e84-9c00-37b361a16a82 | L3 agent           | compute02    | nova              | :-)   | UP    | neutron-l3-agent          |
| fbae2b3d-5641-444f-a8eb-00ffc4f45a91 | L3 agent           | compute01    | nova              | :-)   | UP    | neutron-l3-agent          |
+--------------------------------------+--------------------+--------------+-------------------+-------+-------+---------------------------+

<補足>
L3 agentが表示されるまでに多少時間が掛かる場合があります。
そのときは、各Nodeで以下のように確認してみてください。

cat /var/log/neutron/neutron-l3-agent.log

root@controller01:~# cat /var/log/neutron/neutron-l3-agent.log
2019-05-28 08:40:40.631 9773 INFO neutron.common.config [-] Logging enabled!
2019-05-28 08:40:40.631 9773 INFO neutron.common.config [-] /usr/bin/neutron-l3-agent version 11.0.6
2019-05-28 08:40:40.754 9773 ERROR neutron.agent.l3.agent [-] An interface driver must be specified
2019-05-28 08:41:53.553 9847 INFO neutron.common.config [-] Logging enabled!
2019-05-28 08:41:53.553 9847 INFO neutron.common.config [-] /usr/bin/neutron-l3-agent version 11.0.6
2019-05-28 08:42:53.709 9847 ERROR neutron.common.rpc [req-58acf3df-e1c2-47a0-b83f-2aafa1e53e56 - - - - -] Timeout in RPC method get_service_plugin_list. Waiting for 10 seconds before next attempt. If the server is not down, consider increasing the rpc_response_timeout option as Neutron server(s) may be overloaded and unable to respond quickly enough.: MessagingTimeout: Timed out waiting for a reply to message ID 69bdb30bcf314476942d06106fa0b5f2
2019-05-28 08:42:53.711 9847 WARNING neutron.common.rpc [req-58acf3df-e1c2-47a0-b83f-2aafa1e53e56 - - - - -] Increasing timeout for get_service_plugin_list calls to 120 seconds. Restart the agent to restore it to the default value.: MessagingTimeout: Timed out waiting for a reply to message ID 69bdb30bcf314476942d06106fa0b5f2
2019-05-28 08:43:03.252 9847 WARNING neutron.agent.l3.agent [req-58acf3df-e1c2-47a0-b83f-2aafa1e53e56 - - - - -] l3-agent cannot contact neutron server to retrieve service plugins enabled. Check connectivity to neutron server. Retrying... Detailed message: Timed out waiting for a reply to message ID 69bdb30bcf314476942d06106fa0b5f2.: MessagingTimeout: Timed out waiting for a reply to message ID 69bdb30bcf314476942d06106fa0b5f2
2019-05-28 08:43:03.269 9847 INFO neutron.agent.agent_extensions_manager [req-f6aa92b3-2ba4-4cb4-9273-8cb9f54c5f43 - - - - -] Loaded agent extensions: []
2019-05-28 08:43:03.282 9847 INFO eventlet.wsgi.server [-] (9847) wsgi starting up on http:/var/lib/neutron/keepalived-state-change
2019-05-28 08:43:03.347 9847 INFO neutron.agent.l3.agent [-] L3 agent started
3-4.L2構成確認

対象:全Node
どのNodeでも構いませんので、以下のコマンドを打ってみてください。

ovs-vsctl show

root@compute02:~# ovs-vsctl show
c560fe9b-ea3c-4be6-8e94-109299e797aa
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Bridge "br-ens35"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port "br-ens35"
            Interface "br-ens35"
                type: internal
        Port "phy-br-ens35"
            Interface "phy-br-ens35"
                type: patch
                options: {peer="int-br-ens35"}
        Port "ens35"
            Interface "ens35"
    Bridge br-tun
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}
    Bridge br-int
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
        Port patch-tun
            Interface patch-tun
                type: patch
                options: {peer=patch-int}
        Port "int-br-ens35"
            Interface "int-br-ens35"
                type: patch
                options: {peer="phy-br-ens35"}
    ovs_version: "2.8.4"

上記出力より、br-ens35, br-tun, br-intの3つのBridgeが全Nodeで作成されています。
図にすると、こんな↓イメージです。
f:id:metonymical:20190528110237p:plain
これが素の状態で、全Nodeで同一のBridge 構成となっています。
ここから、Network, Subnet, Port, VMインスタンスを作ったり、VMインスタンスからTrunkしてみたりすると、少しづつ複雑になり始めます。

3-5.各種確認

対象:全Node
以下のコマンドでPortやMacアドレステーブル、フローテーブルが確認可能です。

#Port確認
ovs-ofctl show br-ens35
ovs-ofctl show br-int
ovs-ofctl show br-tun

root@controller01:~# ovs-ofctl show br-ens35
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000000c294300d2
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 1(ens35): addr:00:0c:29:43:00:d2
     config:     0
     state:      0
     current:    1GB-FD COPPER AUTO_NEG
     advertised: 10MB-HD 10MB-FD 100MB-HD 100MB-FD 1GB-FD COPPER AUTO_NEG
     supported:  10MB-HD 10MB-FD 100MB-HD 100MB-FD 1GB-FD COPPER AUTO_NEG
     speed: 1000 Mbps now, 1000 Mbps max
 2(phy-br-ens35): addr:62:2f:61:76:05:b2
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 LOCAL(br-ens35): addr:00:0c:29:43:00:d2
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0


#Macアドレステーブル確認
ovs-appctl fdb/show br-ens35
ovs-appctl fdb/show br-int
ovs-appctl fdb/show br-tun

root@controller01:~# ovs-appctl fdb/show br-ens35
 port  VLAN  MAC                Age
    1    30  6c:50:4d:d5:07:da  141
    1     0  2c:53:4a:01:27:67   94
    1   300  6c:50:4d:d5:07:da   92
    1    30  2c:53:4a:01:27:66   65
    1   300  2c:53:4a:01:27:66   65


#フローテーブル確認
ovs-ofctl dump-flows br-ens35
ovs-ofctl dump-flows br-int
ovs-ofctl dump-flows br-tun

root@controller01:~# ovs-ofctl dump-flows br-ens35
 cookie=0xa3dbef6a19c99333, duration=5955.130s, table=0, n_packets=0, n_bytes=0, priority=2,in_port="phy-br-ens35" actions=resubmit(,1)
 cookie=0xa3dbef6a19c99333, duration=5955.218s, table=0, n_packets=0, n_bytes=0, priority=0 actions=NORMAL
 cookie=0xa3dbef6a19c99333, duration=5955.130s, table=0, n_packets=4058, n_bytes=366211, priority=1 actions=resubmit(,3)
 cookie=0xa3dbef6a19c99333, duration=5955.130s, table=1, n_packets=0, n_bytes=0, priority=0 actions=resubmit(,2)
 cookie=0xa3dbef6a19c99333, duration=5955.129s, table=2, n_packets=0, n_bytes=0, priority=2,in_port="phy-br-ens35" actions=drop
 cookie=0xa3dbef6a19c99333, duration=5576.007s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:05:7d:26 actions=output:"phy-br-ens35"
 cookie=0xa3dbef6a19c99333, duration=5529.828s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:53:4c:80 actions=output:"phy-br-ens35"
 cookie=0xa3dbef6a19c99333, duration=5955.129s, table=3, n_packets=4058, n_bytes=366211, priority=1 actions=NORMAL

4.その他設定

直接Neutronには関係ありませんが、インスタンス周りで困るときがあるため、以下の設定を行っておきます。

4-1.NovaDB登録

対象:Controllerのみ
インスタンスが作成できたけど起動しない場合の対処。

openstack compute service list
su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova
systemctl restart nova-api nova-consoleauth nova-scheduler nova-conductor nova-novncproxy

以下出力例です。

root@controller01:~# openstack compute service list
+----+------------------+--------------+----------+---------+-------+----------------------------+
| ID | Binary           | Host         | Zone     | Status  | State | Updated At                 |
+----+------------------+--------------+----------+---------+-------+----------------------------+
|  1 | nova-scheduler   | controller01 | internal | enabled | up    | 2019-05-28T01:26:14.000000 |
|  2 | nova-consoleauth | controller01 | internal | enabled | up    | 2019-05-28T01:26:17.000000 |
|  3 | nova-conductor   | controller01 | internal | enabled | up    | 2019-05-28T01:26:17.000000 |
|  7 | nova-compute     | compute01    | nova     | enabled | up    | 2019-05-28T01:26:14.000000 |
|  8 | nova-compute     | compute02    | nova     | enabled | up    | 2019-05-28T01:26:17.000000 |
+----+------------------+--------------+----------+---------+-------+----------------------------+

#上記のようにcompute01&02が表示されている状態であることを確認の上、以下のようにNovaDBへ登録します。

root@controller01:~# su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova
Found 2 cell mappings.
Skipping cell0 since it does not contain hosts.
Getting computes from cell 'cell1': e0e3f86a-8b85-4184-9287-7e4dcd53db81
Checking host mapping for compute host 'compute01': 521aeaf7-1d0e-4aa9-81b4-d7f39397c33c
Creating host mapping for compute host 'compute01': 521aeaf7-1d0e-4aa9-81b4-d7f39397c33c
Checking host mapping for compute host 'compute02': d32c9aee-af7b-4b90-a767-56dc9897de5f
Creating host mapping for compute host 'compute02': d32c9aee-af7b-4b90-a767-56dc9897de5f
Found 2 unmapped computes in cell: e0e3f86a-8b85-4184-9287-7e4dcd53db81
4-2.MetadataAgent設定

対象:Computeのみ
インスタンスが起動したけど、メタデータ(KeypairとかPasswd設定ファイルなど)が取得できないときの対処。

#MetadataAgent設定
vi /etc/neutron/metadata_agent.ini

[DEFAULT]
nova_metadata_host = controller01
metadata_proxy_shared_secret = MetadataAgentPasswd123

#設定読込み
systemctl restart neutron-metadata-agent

<補足>
インスタンスUbuntuなど(Cirros以外)を使用する場合、Defaultで鍵認証となっているため、Keypairを取得させるか、Passwd設定&許可ファイルを取得されるなどの方法で、インスタンスssh接続します。*2

以上です。

5.最後に

少しづつ出来てきた感が出ていれば良いなと思います。
3-4.や3-5.に記載した素の状態をよく確認し構成を理解しておくと良いと思います。

*1:進める前に現段階での仮想マシンのクローンやスナップショットは取得しておくことをお勧めします。

*2:vncやvirsh consoleでも、Passwd設定ファイルを取得させないとログインできない場合もあるため。