Metonymical Deflection

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

CentOS8 小ネタ集その1:VNC serverの設定

CentOS8におけるtigervnc-serverの設定方法を記載します。

小ネタ集ってほどでもないですが、サクサクっと記載します。

1.インストールと設定ファイルコピー

dnf -y install tigervnc-server && \
cp -a /usr/lib/systemd/user/vncserver@.service /etc/systemd/system/vncserver@:1.service

2.設定ファイルの編集

=追記、=コメントアウト

vi /etc/systemd/system/vncserver@:1.service

[Service]
Type=forking
PIDFile=/root/.vnc/%H%i.pid

ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
#ExecStart=/usr/bin/vncserver %i
ExecStart=/usr/sbin/runuser -l root -c "/usr/bin/vncserver %i"
ExecStop=/usr/bin/vncserver -kill %i

sedでサクッと設定したい場合は以下の通り。

sed -i -e '/^Type/a PIDFile=/root/.vnc/%H%i.pid' /etc/systemd/system/vncserver@:1.service
sed -i -e 's/ExecStart=/#ExecStart=/g' /etc/systemd/system/vncserver@:1.service
sed -i -e '/^#ExecStart=/a ExecStart=/usr/sbin/runuser -l root -c "/usr/bin/vncserver %i"' /etc/systemd/system/vncserver@:1.service

3.Passwd設定と一時起動&停止

vncpasswd
vncserver :1
vncserver -kill :1

4.ロックファイルの削除

rm /tmp/.X11-unix/X

⇒Tabで/Xのあとを補完すると、以下のような数字が表示される
rm /tmp/.X11-unix/X1024

上記のようにXのあとが1024であれば、合わせて以下のファイルも削除しておく。
rm /tmp/.X1024-lock

5.Service自動起動&起動

systemctl daemon-reload
systemctl enable vncserver@:1.service
systemctl start vncserver@:1.service

6.解像度変更

vi /usr/bin/vncserver

#$geometry = "1024x768";
$geometry = "1600x1200";

sedでサクッと設定したい場合は以下の通り。

sed -i -e '/$geometry/s/1024x768/1600x1200/g' /usr/bin/vncserver

以上です。

7.最後に

VNC serverが必要なケースとしては、Virt-Managerを起動するときなのですが、CentOS8からはCockpitの使用が推奨されています。
しかし、実際にCockpitでVMを作成したところ、NWインターフェース周りが柔軟に設定*1できないようだった*2ので、引き続きVNCのお世話になっています。

*1:virsh editでxmlファイルをゴリゴリ編集すればよいだけなのですが。。

*2:SR-IOVの設定ができずでした

CentOS8 kickstartによるインストール

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

サンプルとしては以下の通り。*1

  • KVM(CentOS7.6)上にCentOS8をServerGUIでインストール
  • DL360G8上にCentOS8をServerGUIでインストール
  • KVM(CentOS7.6)上にCentOS8をminimalでインストール

2019/10/14追記*2

  • KVM(CentOS8.0)上にCentOS8をServerGUIでインストール
  • KVM(CentOS8.0)上にCentOS8をminimalでインストール


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

1.KVM(CentOS7.6)上にCentOS8をServerGUIでインストール

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

# Network information
network  --bootproto=static --device=eth0 --onboot=on --ip=192.168.0.100 --gateway=192.168.0.1 --netmask=255.255.255.0 --nameserver=192.168.0.1 --noipv6
network  --bootproto=dhcp --device=eth1 --onboot=off --noipv6
network  --hostname=c80mas.md.jp

# Root password
rootpw --plaintext TESTPASSWD
user --groups=wheel --name=rsadmin --password=TESTPASSWD --plaintext

# System services
services --disabled="bolt,colord,cups,fwupd,ModemManager,packagekit,smartd,sssd-kcm,sssd,wpa_supplicant" --enabled="chronyd"
# Firewall configuration
firewall --disabled
# SELinux configuration
selinux --disabled

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

cmdline
install
eula --agreed
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8
# System timezone
timezone Asia/Tokyo --isUtc --nontp
# X Window System configuration information
xconfig  --startxonboot
zerombr
bootloader --location=mbr --boot-drive=vda --append="crashkernel=auto biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8"
clearpart --none --initlabel

# repo
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
ignoredisk --only-use=vda

%packages
@^graphical-server-environment
@container-management
@development
@virtualization-client
@virtualization-hypervisor
@virtualization-tools
kexec-tools
%end

%post
dnf -y install cockpit-machines
systemctl enable --now cockpit.socket
systemctl start --now cockpit.socket
dnf -y install epel-release
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
dnf -y install https://www.elrepo.org/elrepo-release-8.0-2.el8.elrepo.noarch.rpm
sed -i -e "s/#options kvm_intel nested=1/options kvm_intel nested=1/g" /etc/modprobe.d/kvm.conf
sed -i -e '/^pool/a server 192.168.0.1 iburst' /etc/chrony.conf
sed -i -e 's/^pool/#pool/g' /etc/chrony.conf
dnf -y install tigervnc-server
cp -a /usr/lib/systemd/user/vncserver@.service /etc/systemd/system/vncserver@:1.service
sed -i -e '/^Type/a PIDFile=/root/.vnc/%H%i.pid' /etc/systemd/system/vncserver@:1.service
sed -i -e 's/ExecStart=/#ExecStart=/g' /etc/systemd/system/vncserver@:1.service
sed -i -e '/^#ExecStart=/a ExecStart=/usr/sbin/runuser -l root -c "/usr/bin/vncserver %i"' /etc/systemd/system/vncserver@:1.service
sed -i -e '/$geometry/s/1024x768/1600x1200/g' /usr/bin/vncserver
systemctl set-default multi-user.target

#dnf update -y

%end
reboot --eject

<補足1>

  1. NW, Credential, Service, Diskなど環境によって変更する頻度が多いパラメータを上位に記載しています。
  2. Serviceのうちdisabledは、私が不要ものを記載しているため、素の状態で使用したい場合はコメントアウトしてください。
  3. eulaが効かず、OSインストール&Reboot後に手動でContinueしないとダメな場合があります。
  4. %packagesのうち、"@^graphical-server-environment"以下は、私が必要なものを記載しているため、素の状態で使用したい場合はコメントアウトしてください。
  5. %postには、私が必要なものを記載しているため、素の状態で使用したい場合はコメントアウトしてください。
1-2.qcow2ファイルの作成
qemu-img create -f qcow2 /var/lib/libvirt/images/c80mas.qcow2 20G
1-3.virt-installの実行
virt-install --connect=qemu:///system \
 --name=c80mas \
 --disk /var/lib/libvirt/images/c80mas.qcow2,format=qcow2,bus=virtio \
 --network bridge=br0,model=virtio \
 --network bridge=br0,model=virtio \
 --initrd-inject=./c80gui.ks \
 --extra-args='ks=file:/c80gui.ks biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8' \
 --vcpus=2 \
 --ram=2048 \
 --accelerate \
 --hvm \
 --location='/var/lib/libvirt/images/CentOS-8-x86_64-1905-dvd1.iso' \
 --nographics \
 --os-type=linux \
 --os-variant=centos7.0 \
 --arch=x86_64

<補足2>
"--network"にPortGroupを使用したい場合は、過去記事を参照してください。

2.DL360G8上にCentOS8をServerGUIでインストール

2-1.kickstartファイルの作成
# Network information
network  --bootproto=static --device=eno1 --ip=192.168.0.240 --netmask=255.255.255.0 --gateway=192.168.0.1 --nameserver=192.168.0.1 --noipv6 --activate
network  --hostname=c80mas.md.jp
#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

# Root password
rootpw --plaintext TESTPASSWD
user --groups=wheel --name=rsadmin --password=TESTPASSWD

# System services
services --disabled="bolt,colord,cups,fwupd,ModemManager,packagekit,smartd,sssd-kcm,sssd,wpa_supplicant" --enabled="chronyd"
# Firewall configuration
firewall --disabled
# SELinux configuration
selinux --disabled

# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=sda
# Partition clearing information
clearpart --all --initlabel --drives=sda
# Disk partitioning information
part /boot --fstype="xfs"   --ondisk=sda --size=1024
part pv.1  --fstype="lvmpv" --ondisk=sda --size=1    --grow
volgroup cl --pesize=4096 pv.1
logvol /    --fstype="xfs"  --name=root --vgname=cl --size=1 --grow
logvol swap --fstype="swap" --name=swap --vgname=cl --recommended

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

# System timezone
timezone Asia/Tokyo --isUtc --nontp
# repo
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
ignoredisk --only-use=sda

%packages
@^graphical-server-environment
@container-management
@development
@virtualization-client
@virtualization-hypervisor
@virtualization-tools
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
# Reboot after installation
reboot --eject

<補足3>

  1. 基本的には補足2に記載した内容と同様です。
  2. "reboot --eject"のうち、ejectオプションが効かないときがあるようなので、手動でejectしてください。

あとの操作方法は過去記事と同様です。
<補足4>
以下の起動オプションを入力する際、DL360G8pとDL360G8eで挙動が少し異なりました。

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

DL360G8pの場合

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

DL360G8eの場合

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

上記に伴いDL360G8eの場合にはkickstartファイルにおいても、"sda"を"sdb"に置換してください。

3.KVM(CentOS7.6)上にCentOS8をminimalでインストール

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

さほど検証していないため、参考程度として記載します。

vi c80cui.ks


cmdline
install
eula --agreed
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable

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

# Network information
network  --bootproto=static --device=eth0 --onboot=on --ip=192.168.0.100 --gateway=192.168.0.1 --netmask=255.255.255.0 --nameserver=192.168.0.1 --noipv6
network  --bootproto=dhcp --device=eth1 --onboot=off --noipv6
network  --hostname=c80mas.md.jp

# System services
#services --enabled=chronyd
# Firewall configuration
firewall --disabled
# SELinux configuration
selinux --disabled

# repo
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
ignoredisk --only-use=vda

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 --fstype="ext4" --ondisk=vda --size=1024
part pv.1 --fstype="lvmpv" --ondisk=vda --size=1024 --grow
volgroup cl --pesize=4096 pv.1
logvol swap --fstype="swap" --recommended --name=swap --vgname=cl
logvol / --fstype="xfs" --grow --size=1024 --name=root --vgname=cl

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

%packages
@^minimal-environment
kexec-tools
%end

%post

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

以下、2019/10/14に追記しました。
NWインターフェース名を変更していますが、それに伴い「--append」や「--extra-args」の設定も変更しています。

4.KVM(CentOS8.0)上にCentOS8をServerGUIでインストール

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

# Network information
network  --bootproto=static --device=enp1s0 --onboot=on --ip=192.168.0.100 --gateway=192.168.0.1 --netmask=255.255.255.0 --nameserver=192.168.0.1 --noipv6
network  --bootproto=dhcp --device=enp2s0 --onboot=off --noipv6
network  --hostname=c80mas.md.jp

# Root password
rootpw --plaintext TESTPASSWD
user --groups=wheel --name=rsadmin --password=TESTPASSWD --plaintext

# System services
services --disabled="bolt,colord,cups,fwupd,ModemManager,packagekit,smartd,sssd-kcm,sssd,wpa_supplicant" --enabled="chronyd"
# Firewall configuration
firewall --disabled
# SELinux configuration
selinux --disabled

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


cmdline
install
eula --agreed
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8
# System timezone
timezone Asia/Tokyo --isUtc --nontp
# X Window System configuration information
xconfig  --startxonboot
zerombr
bootloader --location=mbr --boot-drive=vda --append="crashkernel=auto console=tty0 console=ttyS0,115200n8"
clearpart --none --initlabel

# repo
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
ignoredisk --only-use=vda

%packages
@^graphical-server-environment
@container-management
@development
@virtualization-client
@virtualization-hypervisor
@virtualization-tools
kexec-tools
%end

%post
dnf -y install cockpit-machines
systemctl enable --now cockpit.socket
systemctl start --now cockpit.socket
dnf -y install epel-release
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
dnf -y install https://www.elrepo.org/elrepo-release-8.0-2.el8.elrepo.noarch.rpm
sed -i -e "s/#options kvm_intel nested=1/options kvm_intel nested=1/g" /etc/modprobe.d/kvm.conf
sed -i -e '/^pool/a server 192.168.0.1 iburst' /etc/chrony.conf
sed -i -e 's/^pool/#pool/g' /etc/chrony.conf
dnf -y install tigervnc-server
cp -a /usr/lib/systemd/user/vncserver@.service /etc/systemd/system/vncserver@:1.service
sed -i -e '/^Type/a PIDFile=/root/.vnc/%H%i.pid' /etc/systemd/system/vncserver@:1.service
sed -i -e 's/ExecStart=/#ExecStart=/g' /etc/systemd/system/vncserver@:1.service
sed -i -e '/^#ExecStart=/a ExecStart=/usr/sbin/runuser -l root -c "/usr/bin/vncserver %i"' /etc/systemd/system/vncserver@:1.service
sed -i -e '/$geometry/s/1024x768/1600x1200/g' /usr/bin/vncserver
systemctl set-default multi-user.target

#dnf update -y

%end
reboot --eject
4-2.qcow2ファイルの作成
qemu-img create -f qcow2 /var/lib/libvirt/images/c80mas.qcow2 20G
4-3.virt-installの実行
virt-install --connect=qemu:///system \
 --name=c80mas \
 --disk /var/lib/libvirt/images/c80mas.qcow2,format=qcow2,bus=virtio \
 --network bridge=br0,model=virtio \
 --network bridge=br0,model=virtio \
 --initrd-inject=./c80gui.ks \
 --extra-args='ks=file:/c80gui.ks console=tty0 console=ttyS0,115200n8' \
 --vcpus=2 \
 --ram=2048 \
 --accelerate \
 --hvm \
 --location='/var/lib/libvirt/images/CentOS-8-x86_64-1905-dvd1.iso' \
 --nographics \
 --os-type=linux \
 --os-variant=rhel8.0 \
 --arch=x86_64

5.KVM(CentOS8.0)上にCentOS8をminimalでインストール

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

# Network information
network  --bootproto=static --device=enp1s0 --onboot=on --ip=192.168.0.100 --gateway=192.168.0.1 --netmask=255.255.255.0 --nameserver=192.168.0.1 --noipv6
network  --bootproto=dhcp --device=enp2s0 --onboot=off --noipv6
network  --hostname=c80mas.md.jp

# Root password
rootpw --plaintext TESTPASSWD
user --groups=wheel --name=rsadmin --password=TESTPASSWD --plaintext

# Firewall configuration
firewall --disabled
# SELinux configuration
selinux --disabled

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

cmdline
install
eula --agreed
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8
# System timezone
timezone Asia/Tokyo --isUtc --nontp
# X Window System configuration information
xconfig  --startxonboot
zerombr
bootloader --location=mbr --boot-drive=vda --append="crashkernel=auto console=tty0 console=ttyS0,115200n8"
clearpart --none --initlabel

# repo
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
ignoredisk --only-use=vda

%packages
@^minimal-environment
kexec-tools
%end

%post

%end
reboot --eject
5-2.qcow2ファイルの作成
qemu-img create -f qcow2 /var/lib/libvirt/images/c80mas.qcow2 20G
5-3.virt-installの実行
virt-install --connect=qemu:///system \
 --name=c80mas \
 --disk /var/lib/libvirt/images/c80mas.qcow2,format=qcow2,bus=virtio \
 --network bridge=br0,model=virtio \
 --network bridge=br0,model=virtio \
 --initrd-inject=./c80cui.ks \
 --extra-args='ks=file:/c80cui.ks console=tty0 console=ttyS0,115200n8' \
 --vcpus=2 \
 --ram=2048 \
 --accelerate \
 --hvm \
 --location='/var/lib/libvirt/images/CentOS-8-x86_64-1905-dvd1.iso' \
 --nographics \
 --os-type=linux \
 --os-variant=rhel8.0 \
 --arch=x86_64


以上です。

10.最後に

以下のサイトを参考にさせて頂きました。
virt-install で KVM に CentOS8 を無人インストール - Qiita

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

*1:minimalはもうあまり使わないかなと思ったので重要度下げてます。

*2:libvirtdなどのVersionの違いにより、インターフェース名の指定方法が変わっているため追記しました。NW周りは重要度高いので。

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

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

*4:上記(4)と(5)のコマンドは同じですが、それぞれのComputeNodeにて実行するため取得するIDが異なります。

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が行います。