Metonymical Deflection

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

CentOS7 OpenStack Neutron SR-IOV設定方法

CentOS7.7上でOpenStackを構築した後、SR-IOVの設定方法を記載します。*1

1.概要

1-1.環境
筐体                             : ProLiant DL360e Gen8
System ROM                       : P73 01/22/2018
NIC                              : Intel X540-AT2
OS                               : CentOS7.7(1908)
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools 
1-2.構成

f:id:metonymical:20191014185533p:plain

1-3.全体の流れ

SR-IOVの設定項目だけであれば以下の公式Docで十分ですが、
OpenStack Docs: SR-IOV
再現性が怪しいので、素の状態からの設定方法を記載します。*2
とはいえ、SR-IOV設定がメインなため、それ以外の細かい説明は省略します。

  • 事前設定
  • Controller事前準備
  • Keystone設定
  • Glance設定
  • Nova設定:Controller
  • Nova設定:Compute
  • Neutron設定:Controller
  • Neutron設定:Compute
  • Horizon設定
  • SR-IOV設定:Controller
  • SR-IOV設定:Compute
  • SR-IOVによるインスタンスの起動

2.全体的な事前準備

  • ControllerとComputeのhostsファイルなどを編集の上、名前解決できるようにしておいてください。
  • firewalldとNetworkManagerはDisableとし、networkをEnableにしてください。
  • SELinuxはDisableとしてください。
  • ens33とeno1に相当するインターフェースは、Internetへの疎通性を確保しておいてください。*3
  • ens36とeno2に相当するインターフェースは、OvSのアップリンクとして使用しますが、現段階では設定不要です。
  • ens1f0とens1f1については、過去記事などを参照の上、ComputeにてSR-IOVの設定を行っておいてください。*4
  • ControllerとComputeのMgmtIPやホスト名は以下とします。
Controller c76os11 192.168.11.101/24
Compute c76os12 192.168.11.102/24

3.Controller事前準備

Controllerのみ

3-1.リポジトリの設定
yum install -y centos-release-openstack-queens && \
yum upgrade -y

sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-OpenStack-queens.repo

reboot
3-2.MariaDBのインスト
yum --enablerepo=centos-openstack-queens -y install mariadb mariadb-server python2-PyMySQL

vi /etc/my.cnf

#Charsetを追記
[mysqld]
character-set-server=utf8

systemctl start mariadb && \
systemctl enable mariadb

#初期設定
mysql_secure_installation

#初期設定時の出力例

[root@c76os11 ~]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 空Enter
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y
New password: 任意のパスワード設定
Re-enter new password: 任意のパスワード設定
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
3-3.RabbitMQ&Memcachedのインスト
yum --enablerepo=centos-openstack-queens -y install rabbitmq-server memcached

vi /etc/sysconfig/memcached

#ControllerのIPアドレスを追記
OPTIONS="-l 127.0.0.1,::1,192.168.11.101"

systemctl start rabbitmq-server memcached && \
systemctl enable rabbitmq-server memcached

rabbitmqctl add_user openstack password
rabbitmqctl set_permissions openstack ".*" ".*" ".*"

4.Keystone設定

Controllerのみ

4-1.MariaDBに登録
mysql -u root -p

create database keystone;
grant all privileges on keystone.* to keystone@'localhost' identified by 'password';
grant all privileges on keystone.* to keystone@'%' identified by 'password';
flush privileges;
exit
4-2.Keystoneのインスト
yum --enablerepo=centos-openstack-queens -y install openstack-keystone openstack-utils python-openstackclient httpd mod_wsgi

vi /etc/keystone/keystone.conf

#以下を追記*5
[DEFAULT]
memcache_servers = 192.168.11.101:11211
[database]
connection = mysql+pymysql://keystone:password@192.168.11.101/keystone
[token]
provider = fernet

#db sync
su -s /bin/bash keystone -c "keystone-manage db_sync"

#初期化
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
keystone-manage credential_setup --keystone-user keystone --keystone-group keystone

4-3.bootstepの設定
# ControllerのIPを定義
export controller=192.168.11.101

# keystoneのbootstep (TESTPASSWD は任意のパスワード)
keystone-manage bootstrap --bootstrap-password TESTPASSWD \
--bootstrap-admin-url http://$controller:5000/v3/ \
--bootstrap-internal-url http://$controller:5000/v3/ \
--bootstrap-public-url http://$controller:5000/v3/ \
--bootstrap-region-id RegionOne
4-4.httpdの起動
ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/
systemctl start httpd && \
systemctl enable httpd
4-5.ログイン用環境変数ファイル設定(任意)

任意設定ですが、都度Credentialを求められるため、実施しておいた方が良いと思います。
「export OS_PASSWORD=」は、4-3.bootstepの設定と同一のPasswdを設定してください。

vi ~/keystonerc

export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=TESTPASSWD
export OS_AUTH_URL=http://192.168.11.101:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export PS1='[\u@\h \W(ks)]\$ '

chmod 600 ~/keystonerc
source ~/keystonerc
echo "source ~/keystonerc " >> ~/.bash_profile
4-6.Project作成
openstack project create --domain default --description "Default Project" service
openstack project list

5.Glance設定

Controllerのみ

5-1.ユーザ登録&Endpoint設定
openstack user create --domain default --project service --password servicepassword glance
openstack role add --project service --user glance admin
openstack service create --name glance --description "OpenStack Image service" image

export controller=192.168.11.101
openstack endpoint create --region RegionOne image public http://$controller:9292
openstack endpoint create --region RegionOne image internal http://$controller:9292
openstack endpoint create --region RegionOne image admin http://$controller:9292
5-2.MariaDBに登録
mysql -u root -p

create database glance;
grant all privileges on glance.* to glance@'localhost' identified by 'password';
grant all privileges on glance.* to glance@'%' identified by 'password';
flush privileges;
exit
5-3.Glanceのインストと設定
yum --enablerepo=centos-openstack-queens -y install openstack-glance

#glance-api.confの設定
mv /etc/glance/glance-api.conf /etc/glance/glance-api.conf.org
vi /etc/glance/glance-api.conf

[DEFAULT]
bind_host = 0.0.0.0

[glance_store]
stores = file,http
default_store = file
filesystem_store_datadir = /var/lib/glance/images/

[database]
connection = mysql+pymysql://glance:password@192.168.11.101/glance

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = glance
password = servicepassword

[paste_deploy]
flavor = keystone


#glance-registry.confの設定
mv /etc/glance/glance-registry.conf /etc/glance/glance-registry.conf.org
vi /etc/glance/glance-registry.conf

[DEFAULT]
bind_host = 0.0.0.0

[database]
connection = mysql+pymysql://glance:password@192.168.11.101/glance

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = glance
password = servicepassword

[paste_deploy]
flavor = keystone

#Permissionや起動設定*6
chmod 640 /etc/glance/glance-api.conf /etc/glance/glance-registry.conf
chown root:glance /etc/glance/glance-api.conf /etc/glance/glance-registry.conf
su -s /bin/bash glance -c "glance-manage db_sync"
systemctl start openstack-glance-api openstack-glance-registry && \
systemctl enable openstack-glance-api openstack-glance-registry
5-4.イメージ登録
mkdir /tmp/images

#cirrosの登録
wget -P /tmp/images http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img

openstack image create "cirros-0.4.0" \
--file /tmp/images/cirros-0.4.0-x86_64-disk.img \
--disk-format qcow2 \
--container-format bare \
--public

openstack image list

#centos7の登録
wget -P /tmp/images http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2

openstack image create "centos7" \
--file /tmp/images/CentOS-7-x86_64-GenericCloud.qcow2 \
--disk-format qcow2 \
--container-format bare \
--public

openstack image list

6.Nova設定:Controller

Controllerのみ

6-1.ユーザ登録&Endpoint設定
openstack user create --domain default --project service --password servicepassword nova
openstack role add --project service --user nova admin
openstack user create --domain default --project service --password servicepassword placement
openstack role add --project service --user placement admin
openstack service create --name nova --description "OpenStack Compute service" compute
openstack service create --name placement --description "OpenStack Compute Placement service" placement

export controller=192.168.11.101
openstack endpoint create --region RegionOne compute public http://$controller:8774/v2.1/%\(tenant_id\)s && \
openstack endpoint create --region RegionOne compute internal http://$controller:8774/v2.1/%\(tenant_id\)s && \
openstack endpoint create --region RegionOne compute admin http://$controller:8774/v2.1/%\(tenant_id\)s && \
openstack endpoint create --region RegionOne placement public http://$controller:8778 && \
openstack endpoint create --region RegionOne placement internal http://$controller:8778 && \
openstack endpoint create --region RegionOne placement admin http://$controller:8778
6-2.MariaDB登録
mysql -u root -p

create database nova;
grant all privileges on nova.* to nova@'localhost' identified by 'password';
grant all privileges on nova.* to nova@'%' identified by 'password';
create database nova_api;
grant all privileges on nova_api.* to nova@'localhost' identified by 'password';
grant all privileges on nova_api.* to nova@'%' identified by 'password';
create database nova_placement;
grant all privileges on nova_placement.* to nova@'localhost' identified by 'password';
grant all privileges on nova_placement.* to nova@'%' identified by 'password';
create database nova_cell0;
grant all privileges on nova_cell0.* to nova@'localhost' identified by 'password';
grant all privileges on nova_cell0.* to nova@'%' identified by 'password';
flush privileges;
exit
6-3.Novaのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-nova

#nova.confの設定
mv /etc/nova/nova.conf /etc/nova/nova.conf.org
vi /etc/nova/nova.conf

[DEFAULT]
my_ip = 192.168.11.101
state_path = /var/lib/nova
enabled_apis = osapi_compute,metadata
log_dir = /var/log/nova
transport_url = rabbit://openstack:password@192.168.11.101

[api]
auth_strategy = keystone

[glance]
api_servers = http://192.168.11.101:9292

[oslo_concurrency]
lock_path = $state_path/tmp

[api_database]
connection = mysql+pymysql://nova:password@192.168.11.101/nova_api

[database]
connection = mysql+pymysql://nova:password@192.168.11.101/nova

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = servicepassword

[placement]
auth_url = http://192.168.11.101:5000
os_region_name = RegionOne
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = placement
password = servicepassword

[placement_database]
connection = mysql+pymysql://nova:password@192.168.11.101/nova_placement

[wsgi]
api_paste_config = /etc/nova/api-paste.ini

#Permission変更
chmod 640 /etc/nova/nova.conf
chgrp nova /etc/nova/nova.conf

#00-nova-placement-api.confの設定
vi /etc/httpd/conf.d/00-nova-placement-api.conf

#</VirtualHost>の直上に追記
<Directory /usr/bin>
    Require all granted
</Directory>
6-4.DB登録とサービス起動
#novaコマンドは、一行づつ投入してください。
su -s /bin/bash nova -c "nova-manage api_db sync"
su -s /bin/bash nova -c "nova-manage cell_v2 map_cell0"
su -s /bin/bash nova -c "nova-manage db sync"
su -s /bin/bash nova -c "nova-manage cell_v2 create_cell --name cell1"

systemctl restart httpd
chown nova. /var/log/nova/nova-placement-api.log

for service in api consoleauth conductor scheduler novncproxy; do
systemctl start openstack-nova-$service
systemctl enable openstack-nova-$service
done

openstack compute service list

#一旦Reboot
reboot

#出力例:以下のコマンド(su -s /bin/bash nova -c "nova-manage db sync")投入時にWarningが出力されますが、気にせず先に進んでください。

[root@c76os11 images(keystone)]# su -s /bin/bash nova -c "nova-manage db sync"
/usr/lib/python2.7/site-packages/pymysql/cursors.py:166: Warning: (1831, u'Duplicate index `block_device_mapping_instance_uuid_virtual_name_device_name_idx`. This is deprecated and will be disallowed in a future release.')
  result = self._query(query)
/usr/lib/python2.7/site-packages/pymysql/cursors.py:166: Warning: (1831, u'Duplicate index `uniq_instances0uuid`. This is deprecated and will be disallowed in a future release.')
  result = self._query(query)

7.Nova設定:Compute

Computeのみ

7-1.事前準備
yum install -y centos-release-openstack-queens && \
yum upgrade -y

sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-OpenStack-queens.repo

reboot
7-2.Novaインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-nova-compute

#nova.confの設定
mv /etc/nova/nova.conf /etc/nova/nova.conf.org
vi /etc/nova/nova.conf

[DEFAULT]
my_ip = 192.168.11.102
state_path = /var/lib/nova
enabled_apis = osapi_compute,metadata
log_dir = /var/log/nova
transport_url = rabbit://openstack:password@192.168.11.101
compute_driver = libvirt.LibvirtDriver

[libvirt]
virt_type=kvm
cpu_mode=host-passthrough
hw_machine_type=x86_64=pc-i440fx-rhel7.6.0

[api]
auth_strategy = keystone

[vnc]
enabled = True
server_listen = 0.0.0.0
server_proxyclient_address = $my_ip
novncproxy_base_url = http://192.168.11.101:6080/vnc_auto.html

[glance]
api_servers = http://192.168.11.101:9292

[oslo_concurrency]
lock_path = $state_path/tmp

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = servicepassword

[placement]
auth_url = http://192.168.11.101:5000
os_region_name = RegionOne
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = placement
password = servicepassword

[wsgi]
api_paste_config = /etc/nova/api-paste.ini


#Permission変更
chmod 640 /etc/nova/nova.conf
chgrp nova /etc/nova/nova.conf

#サービス起動
systemctl start openstack-nova-compute && \
systemctl enable openstack-nova-compute
7-3.ComputeNodeのDiscovery

Controllerのみ

su -s /bin/bash nova -c "nova-manage cell_v2 discover_hosts"
openstack compute service list

#出力例
[root@c76os11 ~(keystone)]# openstack compute service list
+----+------------------+---------------+----------+----------+-------+----------------------------+
| ID | Binary           | Host          | Zone     | Status   | State | Updated At                 |
+----+------------------+---------------+----------+----------+-------+----------------------------+
|  7 | nova-consoleauth | c76os11.md.jp | internal | enabled  | up    | 2019-10-14T01:49:01.000000 |
|  8 | nova-conductor   | c76os11.md.jp | internal | enabled  | up    | 2019-10-14T01:49:01.000000 |
| 10 | nova-scheduler   | c76os11.md.jp | internal | enabled  | up    | 2019-10-14T01:49:02.000000 |
| 11 | nova-compute     | c76os12.md.jp | nova     | enabled  | up    | 2019-10-14T01:49:00.000000 |
+----+------------------+---------------+----------+----------+-------+----------------------------+

8.Neutron設定:Controller

Controllerのみ

8-1.ユーザ&Endpoint登録
openstack user create --domain default --project service --password servicepassword neutron
openstack role add --project service --user neutron admin
openstack service create --name neutron --description "OpenStack Networking service" network

export controller=192.168.11.101
openstack endpoint create --region RegionOne network public http://$controller:9696 && \
openstack endpoint create --region RegionOne network internal http://$controller:9696 && \
openstack endpoint create --region RegionOne network admin http://$controller:9696
8-2.DB登録
mysql -u root -p

create database neutron_ml2;
grant all privileges on neutron_ml2.* to neutron@'localhost' identified by 'password';
grant all privileges on neutron_ml2.* to neutron@'%' identified by 'password';
flush privileges;
exit
8-3.Neutronのインストと設定
yum --enablerepo=centos-openstack-queens -y install openstack-neutron openstack-neutron-ml2

#neutron.conf設定
mv /etc/neutron/neutron.conf /etc/neutron/neutron.conf.org
vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2
service_plugins = router
auth_strategy = keystone
state_path = /var/lib/neutron
dhcp_agent_notification = True
allow_overlapping_ips = True
notify_nova_on_port_status_changes = True
notify_nova_on_port_data_changes = True
transport_url = rabbit://openstack:password@192.168.11.101

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = servicepassword

[database]
connection = mysql+pymysql://neutron:password@192.168.11.101/neutron_ml2

[nova]
auth_url = http://192.168.11.101:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = nova
password = servicepassword

[oslo_concurrency]
lock_path = $state_path/tmp

#Permission設定
chmod 640 /etc/neutron/neutron.conf
chgrp neutron /etc/neutron/neutron.conf
8-4.metadata_agent.ini設定
vi /etc/neutron/metadata_agent.ini

[DEFAULT]
nova_metadata_host = 192.168.11.101
metadata_proxy_shared_secret = metadata_secret

[cache]
memcache_servers = 192.168.11.101:11211
8-5.ml2_conf.ini設定
vi /etc/neutron/plugins/ml2/ml2_conf.ini

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

[ml2_type_vlan]
network_vlan_ranges = physnet8:4000:4094

<補足>
physnet8:4000:4094は任意の名前と値です。
今回の構成においては以下の定義とします。

  • physnet8は、InstanceのMgmt用として使用します。
  • 4000:4094は、OvS内部で使用されるVLANレンジとなります。
8-6.nova.confの追加設定
vi /etc/nova/nova.conf

#追記
[DEFAULT]
use_neutron = True
linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver

#[neutron]セクションを最終行へ追記
[neutron]
auth_url = http://192.168.11.101:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = neutron
password = servicepassword
service_metadata_proxy = True
metadata_proxy_shared_secret = metadata_secret

#サービス起動
ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini
su -s /bin/bash neutron -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini upgrade head"
systemctl start neutron-server neutron-metadata-agent && \
systemctl enable neutron-server neutron-metadata-agent && \
systemctl restart openstack-nova-api
8-7.その他Agent&OVSのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-neutron openstack-neutron-ml2 openstack-neutron-openvswitch

#L3agent設定
vi /etc/neutron/l3_agent.ini

[DEFAULT]
interface_driver = openvswitch

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

[DEFAULT]
interface_driver = openvswitch
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
enable_isolated_metadata = true

#ovs設定&サービス起動
ovs-vsctl add-br br-int

systemctl start openvswitch && \
systemctl enable openvswitch

for service in dhcp-agent l3-agent metadata-agent openvswitch-agent; do
systemctl start neutron-$service
systemctl enable neutron-$service
done

9.Neutron設定:Compute

Computeのみ

9-1.Neutronのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-neutron openstack-neutron-ml2 openstack-neutron-openvswitch

#neutron.conf設定
mv /etc/neutron/neutron.conf /etc/neutron/neutron.conf.org
vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2
service_plugins = router
auth_strategy = keystone
state_path = /var/lib/neutron
allow_overlapping_ips = True
transport_url = rabbit://openstack:password@192.168.11.101

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = servicepassword

[oslo_concurrency]
lock_path = $state_path/lock

#Permission変更
chmod 640 /etc/neutron/neutron.conf
chgrp neutron /etc/neutron/neutron.conf
9-2.ml2_conf.ini設定
vi /etc/neutron/plugins/ml2/ml2_conf.ini

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

[ml2_type_vlan]
network_vlan_ranges = physnet8:4000:4094
9-3.nova.confの追加設定
vi /etc/nova/nova.conf

#追記
[DEFAULT]
use_neutron = True
linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver
vif_plugging_is_fatal = True
vif_plugging_timeout = 300

#[neutron]セクションを最終行へ追記
[neutron]
auth_url = http://192.168.11.101:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = neutron
password = servicepassword
service_metadata_proxy = True
metadata_proxy_shared_secret = metadata_secret

#サービス起動
ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini
systemctl start openvswitch && \
systemctl enable openvswitch
9-4.OvS設定
ovs-vsctl add-br br-int
systemctl restart openstack-nova-compute

systemctl start neutron-openvswitch-agent && \
systemctl enable neutron-openvswitch-agent
9-5.Mgmtインターフェース設定

ControllerとCompute
metadata-agent & dhcp-agentの通信用NWインターフェースとして利用します。

#Controllerにて設定
ovs-vsctl add-br br-ens36
ovs-vsctl add-port br-ens36 ens36


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

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


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

NAME=ens36
DEVICE=ens36
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ens36
BOOTPROTO=none
NM_CONTROLLED=no
HOTPLUG=no


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

[ml2_type_flat]
flat_networks = *


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

[ovs]
bridge_mappings = physnet8:br-ens36

systemctl restart neutron-openvswitch-agent


#Computeにて設定
ovs-vsctl add-br br-eno2
ovs-vsctl add-port br-eno2 eno2

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

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


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

NAME=eno2
DEVICE=eno2
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-eno2
BOOTPROTO=none
NM_CONTROLLED=no
HOTPLUG=no


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

[ml2_type_flat]
flat_networks = *


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

[ovs]
bridge_mappings = physnet8:br-eno2

systemctl restart neutron-openvswitch-agent

10.Horizon設定

Controllerのみ

10-1.Horizonのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-dashboard

#local_settingsの設定
vi /etc/openstack-dashboard/local_settings

ALLOWED_HOSTS = ['dlp.srv.world', 'localhost', '*']

OPENSTACK_API_VERSIONS = {
    "data-processing": 1.1,
    "identity": 3,
    "image": 2,
    "volume": 2,
    "compute": 2,
}

OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True

OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '192.168.11.101:11211',
    },
}

OPENSTACK_HOST = "192.168.11.101"

#openstack-dashboard.confの設定
#WSGISocketPrefix run/wsgiの直下に追記
vi /etc/httpd/conf.d/openstack-dashboard.conf

WSGIApplicationGroup %{GLOBAL}

#サービス再起動
systemctl restart httpd.service memcached.service
10-2.flavorの作成

事前にflavorを作成しておきます。

openstack flavor create --id 0 --vcpus 1 --ram 1024 --disk 10 m1.small
openstack flavor list
10-3.簡易動作確認

動作確認用として、mgmtネットワークを作成し、テストインスタンスの起動確認をしてください。

#nw-mgmt作成
openstack network create \
--share \
--no-default \
--enable \
--project admin \
--external \
--provider-network-type flat \
--provider-physical-network physnet8 \
nw-mgmt

#subnet-mgmt作成
openstack subnet create \
--project admin \
--gateway 10.10.0.254 \
--subnet-range 10.10.0.0/24 \
--allocation-pool start=10.10.0.16,end=10.10.0.127 \
--network nw-mgmt \
subnet-mgmt

#インスタンス起動
netID=$(openstack network list | grep nw-mgmt | awk '{ print $2 }')
openstack server create --flavor m1.small --image cirros-0.4.0 --nic net-id=$netID inst01
openstack server list

#出力例
[root@c76os11 ~(keystone)]# openstack server list
+--------------------------------------+---------+---------+----------------------------------------------------------------------------+---------------------+----------+
| ID                                   | Name    | Status  | Networks                                                                   | Image               | Flavor   |
+--------------------------------------+---------+---------+----------------------------------------------------------------------------+---------------------+----------+
| 2d2af2b3-89eb-4508-b425-49e67b3dbcaa | inst01  | ACTIVE  | nw-mgmt=10.10.0.28                                                         | cirros-0.4.0        | m1.small |
+--------------------------------------+---------+---------+----------------------------------------------------------------------------+---------------------+----------+

#Dashboradの動作確認
http://192.168.11.101/dashboard/
f:id:metonymical:20191014120535p:plain
ユーザ名:admin
パスワード:TESTPASSWD 

ここまででSR-IOVを設定する準備ができました。
上記インスタンスへの疎通確認なども実施しておいてください。
上手く疎通確認が取れない場合は、Controller&Computeを再起動してみてください。

11.SR-IOV設定:Controller

Controllerのみ

#nova.confの追加設定
vi /etc/nova/nova.conf

[DEFAULT]
scheduler_default_filters = RetryFilter, AvailabilityZoneFilter, RamFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, PciPassthroughFilter
scheduler_available_filters = nova.scheduler.filters.all_filters

#ml2_conf.iniの追加設定
#青文字の箇所を追記してください。
vi /etc/neutron/plugins/ml2/ml2_conf.ini
[ml2]
type_drivers = flat,vlan,gre,vxlan
tenant_network_types = flat,vlan
mechanism_drivers = openvswitch,l2population,sriovnicswitch

[ml2_type_vlan]
network_vlan_ranges = physnet8:4000:4094,physnet0:300:304,physnet1:300:304

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

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

#openvswitch-agent再起動
systemctl restart neutron-openvswitch-agent

12.SR-IOV設定:Compute

Computeのみ

#sriov-nic-agentのインスト
yum --enablerepo=centos-openstack-queens -y install openstack-neutron-sriov-nic-agent

#nova.confの追加設定
vi /etc/nova/nova.conf

[DEFAULT]
pci_passthrough_whitelist = {"devname":"ens1f0","physical_network":"physnet0"}
pci_passthrough_whitelist = {"devname":"ens1f1","physical_network":"physnet1"}


#sriov_agent.ini設定
vi /etc/neutron/plugins/ml2/sriov_agent.ini

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

[sriov_nic]
physical_device_mappings = physnet0:ens1f0,physnet1:ens1f1


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

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

#サービス起動
systemctl restart neutron-openvswitch-agent && \
systemctl start neutron-sriov-nic-agent && \
systemctl enable neutron-sriov-nic-agent

#NIC設定
vi /etc/sysconfig/network-scripts/ifcfg-ens1f0

TYPE=Ethernet
BOOTPROTO=none
NAME=ens1f0
DEVICE=ens1f0
ONBOOT=yes

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

TYPE=Ethernet
BOOTPROTO=none
NAME=ens1f1
DEVICE=ens1f1
ONBOOT=yes

systemctl restart network

13.SR-IOVによるインスタンスの起動

Controllerのみ

13-1.VLAN300のNW,Subnet,Portの作成

ここからSR-IOV用のNWなどを作成していきますが、Errorで弾かれる場合には、ControllerとComputeを一度再起動してみてください。*7

openstack network create \
--share \
--no-default \
--enable \
--project admin \
--external \
--provider-network-type vlan \
--provider-physical-network physnet0 \
--provider-segment 300 \
sriov300

openstack subnet create \
--project admin \
--no-dhcp \
--gateway 192.168.30.254 \
--subnet-range 192.168.30.0/24 \
--allocation-pool start=192.168.30.16,end=192.168.30.127 \
--network sriov300 \
sriov300_sb

openstack port create \
--network sriov300 \
--vnic-type direct \
--fixed-ip subnet=sriov300_sb,ip-address=192.168.30.128 \
--no-security-group \
--enable \
sriov300_port128

openstack port create \
--network sriov300 \
--vnic-type direct \
--fixed-ip subnet=sriov300_sb,ip-address=192.168.30.129 \
--no-security-group \
--enable \
sriov300_port129
13-2.VLAN301のNW,Subnet,Portの作成
openstack network create \
--share \
--no-default \
--enable \
--project admin \
--external \
--provider-network-type vlan \
--provider-physical-network physnet1 \
--provider-segment 301 \
sriov301

openstack subnet create \
--project admin \
--no-dhcp \
--gateway 192.168.31.254 \
--subnet-range 192.168.31.0/24 \
--allocation-pool start=192.168.31.16,end=192.168.31.127 \
--network sriov301 \
sriov301_sb

openstack port create \
--network sriov301 \
--vnic-type direct \
--fixed-ip subnet=sriov301_sb,ip-address=192.168.31.128 \
--no-security-group \
--enable \
sriov301_port128

openstack port create \
--network sriov301 \
--vnic-type direct \
--fixed-ip subnet=sriov301_sb,ip-address=192.168.31.129 \
--no-security-group \
--enable \
sriov301_port129

<補足>
Portの作成はCLI or APIにて実施してください。
公式Docに以下の記載があります。
SR-IOV is not integrated into the OpenStack Dashboard (horizon). Users must use the CLI or API to configure SR-IOV interfaces.

13-3.UserDataの作成
vi udata.txt

#cloud-config
password: TESTPASSWD
chpasswd: { expire: False }
ssh_pwauth: True
13-4.CLIによるインスタンスの起動
netID=$(openstack network list | grep nw-mgmt | awk '{ print $2 }')
portID01=$(openstack port list |grep sriov300_port128 | awk '{ print $2 }')
portID02=$(openstack port list |grep sriov301_port128 | awk '{ print $2 }')

openstack server create \
--flavor m1.small \
--image centos7 \
--user-data udata.txt \
--nic net-id=$netID \
--nic port-id=$portID01 \
--nic port-id=$portID02 \
inst02

<補足>
SR-IOVインターフェースはnet-idではなく、port-idとして指定してください。
次項のGUIによるインスタンスの起動においても同様に、「ネットワークのポート」画面にて設定してください。*8

13-5.GUIによるインスタンスの起動

プロジェクト>コンピュート>インスタンスインスタンスの起動をクリック。
f:id:metonymical:20191014182457p:plain
インスタンス名を入力。次へをクリック。
f:id:metonymical:20191014182538p:plain
centos7を割り当てし、次へをクリック。
f:id:metonymical:20191014182649p:plain
m1.smallを割り当てし、次へをクリック。
f:id:metonymical:20191014182739p:plain
nw-mgmtを割り当てし、次へをクリック。
f:id:metonymical:20191014182822p:plain
作成したPortを割り当てし、次へをクリック。「設定」まで次へをクリック。
f:id:metonymical:20191014182855p:plain
13-3.UserDataの作成の内容をコピペし、インスタンスの起動をクリック。f:id:metonymical:20191014183035p:plain
以下の通り起動すればOKです。
f:id:metonymical:20191014183107p:plain

13-5.NICの確認
[root@c76os11 ~(keystone)]# openstack server list
+--------------------------------------+--------+---------+----------------------------------------------------------------------+--------------+----------+
| ID                                   | Name   | Status  | Networks                                                             | Image        | Flavor   |
+--------------------------------------+--------+---------+----------------------------------------------------------------------+--------------+----------+
| a6f54ee9-6c3d-4497-b2f5-61ab0b493e94 | inst03 | ACTIVE  | sriov300=192.168.30.129; sriov301=192.168.31.129; nw-mgmt=10.10.0.22 | centos7      | m1.small |
| afe80655-2c2c-4349-82cb-5843256d1d05 | inst02 | ACTIVE  | sriov300=192.168.30.128; sriov301=192.168.31.128; nw-mgmt=10.10.0.21 | centos7      | m1.small |
| c13aeb0a-85b3-4174-a977-d317b7c84cc3 | inst01 | SHUTOFF | nw-mgmt=10.10.0.18                                                   | cirros-0.4.0 | m1.small |
+--------------------------------------+--------+---------+----------------------------------------------------------------------+--------------+----------+

#ここでは例としてinst02にssh接続します。
[root@c76os11 ~(keystone)]# ip netns
qdhcp-5561d190-1fbf-4d06-aa54-253935fdce59 (id: 0)
[root@c76os11 ~(keystone)]# ip netns exec qdhcp-5561d190-1fbf-4d06-aa54-253935fdce59 ssh centos@10.10.0.21
centos@10.10.0.21's password:
Last login: Mon Oct 14 09:15:26 2019 from host-10-10-0-16.openstacklocal
[centos@inst02 ~]$ sudo su -
Last login: Mon Oct 14 09:15:29 UTC 2019 on pts/0

#inst02のens5とens6のMACアドレスを確認します。
[root@inst02 ~]# ip link show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens5:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether fa:16:3e:43:a0:c5 brd ff:ff:ff:ff:ff:ff
3: ens6:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether fa:16:3e:43:f0:66 brd ff:ff:ff:ff:ff:ff
4: eth0:  mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether fa:16:3e:13:21:cb brd ff:ff:ff:ff:ff:ff

#ComputeNodeのVFのMACアドレスと一致していることを確認します。
[root@c76os12 ~]# ip link show
6: ens1f0:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:68 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC fa:16:3e:ae:b4:91, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC fa:16:3e:43:a0:c5, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
7: ens1f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:6a brd ff:ff:ff:ff:ff:ff
    vf 0 MAC fa:16:3e:b7:1f:74, vlan 301, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC fa:16:3e:43:f0:66, vlan 301, spoof checking on, link-state auto, trust off, query_rss off
13-6.NICの設定

inst02のens5とens6にIPの設定し、networkサービスの再起動をしてください。

[root@inst02 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens5

NAME=ens5
DEVICE=ens5
BOOTPROTO=none
ONBOOT=yes
HOTPLUG=no
IPADDR=192.168.30.128
PREFIX=24

[root@inst02 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens6

NAME=ens6
DEVICE=ens6
BOOTPROTO=none
ONBOOT=yes
HOTPLUG=no
IPADDR=192.168.31.128
PREFIX=24


以上です。

14.最後に

以下のサイトを参考にさせて頂きました。
CentOS 7 : OpenStack Queens インストールと設定 : Server World
OpenStack Docs: SR-IOV

一度でも成功していれば勘所がわかってくるのですが、一度も成功したことがないと、ControllerとComputeのiniファイルやconfファイルを何度も編集したり、再起動したりと、ハマりやすいと思います。

*1:図はc76となっていますが、7.7でも動作確認を行っています。ちなみに最近、CentOSミラーサイトの7.6関連のファイルが軒並み削除されているため、7.7を使用しないとyum updateでもコケる可能性があります。

*2:個人的にとても苦労したので、この方法で最初から構築したら上手くいった、という内容を記載したいと思います。

*3:yum updateなどを実行するので。

*4:過去記事を参照する場合、10は設定しないでください。環境によっては、9も設定不要です。

*5:正確にどのセクションの何行目くらいかを知りたい場合は、memcache_serversやmysql+pymysqlなどで検索してください。

*6:待ちが必要な箇所には、&& \を記載しています

*7:各agentの整合性が取れてない可能性があるためです。

*8:net-idで指定すると失敗します。理由を考察するに、SR-IOVのVFを動的に割り当てているためではないかな、と考えています。

CentOS8 小ネタ集その4:SR-IOVの設定

CentOS8のSR-IOV設定方法を記載します。

基本的な注意事項などは過去記事と同様となりますので、そちらを参照してください。

1.環境

筐体                           :ProLiant DL360e Gen8
System ROM                     :P73 01/22/2018
NIC                            :Intel X540-AT2 *1
OS                             :CentOS8.0
Installed Environment Groups:
  @^graphical-server-environment
  @container-management
  @development
  @virtualization-client
  @virtualization-hypervisor
  @virtualization-tools

BIOS上でSR-IOVを有効化する方法はHPガイドを参照してください。

2.iommuの有効化

vi /etc/default/grub

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt pci=realloc"

もしくは
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub


以下のコマンドでgrub2.cfgに反映

grub2-mkconfig -o /etc/grub2.cfg

3.SR-IOVの自動起動設定

vi /etc/rc.local

echo 2 > /sys/class/net/ens1f0/device/sriov_numvfs
echo 2 > /sys/class/net/ens1f1/device/sriov_numvfs
exit 0

chmod +x /etc/rc.d/rc.local

4.modprobeのblacklistへの追加

ixgbevfを外すことによりホストOS上でVFがNICとして認識されるのを防ぎます。
但し、ホストOS上ではPCIバイスとして認識しているため、ゲストOSにアタッチすることは可能です。

vi /lib/modprobe.d/dist-blacklist.conf

# ixgbevf driver
blacklist ixgbevf

もしくは

cat << EOF >> /lib/modprobe.d/dist-blacklist.conf

# ixgbevf driver
blacklist ixgbevf
EOF


ここで一旦再起動してください。

5.仮想マシンでの設定方法

Cockpitでは設定できないため、Virt-Managerで設定していきます。
f:id:metonymical:20191013214413p:plain
仮想マシンをOpenで開き、Add Hardwareをクリック。
f:id:metonymical:20191013214505p:plain
PCI Host Deviceを選択。
Host Device:から、Virtual Functionを選択。

以下の通り、VFとPFのポートは偶数と奇数で分かれています。*2

Domain:Bus:Slot:Function -> PFのポート
0000  :08 :10  :0        -> enp1s0(0000:08:00:0)
0000  :08 :10  :1        -> enp1s1(0000:08:00:1)
0000  :08 :10  :2        -> enp1s0(0000:08:00:0)
0000  :08 :10  :3        -> enp1s1(0000:08:00:1)
0000  :08 :10  :4        -> enp1s0(0000:08:00:0)
0000  :08 :10  :5        -> enp1s1(0000:08:00:1)
0000  :08 :10  :6        -> enp1s0(0000:08:00:0)
0000  :08 :10  :7        -> enp1s1(0000:08:00:1)

f:id:metonymical:20191013215103p:plain
上記のようになっていればOKです。
仮想マシンを起動してください。

仮想マシン起動後にホストOSにて、ip link showコマンドにより、仮想マシンがVFを掴んでいることが確認できます。
仮想マシン上でも同一MACアドレスになっていればOKです。

[root@c80g240 ~]# ip link show
6: ens1f0:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:68 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 12:af:d7:6e:fa:20, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
7: ens1f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:6a brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off


以上です。

6.最後に

小ネタ集は一旦終了しようと思いますが、今後もちょくちょく追加できればと考えています。

*1:X540-T2として販売されているもので、HP純正ではなくAmazonで購入したOEM提供のものです。

*2:Slotの箇所は、Deviceと記載されている場合もあります。

CentOS8 小ネタ集その3:Nested KVMの設定

CentOS8におけるNested KVMの設定です。

1.Nestedの設定

sed -i -e "s/#options kvm_intel nested=1/options kvm_intel nested=1/g" /etc/modprobe.d/kvm.conf

上記はIntelCPUの場合の設定です。
AMDの場合は、/etc/modprobe.d/kvm.confを直接開けば設定可能です。

2.仮想マシン側の設定

virsh edit vm-name

<cpu mode='custom' match='exact'> 
を
<cpu mode='host-passthrough'>
に変更して保存。

以上です。

3.最後に

大した内容ではありませんが、CentOS7からほんの少しだけ変更されていたため、知っておくと何かと便利なので記載しました。

小ネタ集その1~3以外にも、SELinuxやchrony、HugePage、run-level変更など小ネタはあるのですが、CentOS7からの変更はないので、あえて記載するほどでもないかなと思っています。

ちなみに、CentOS8ではnmcliコマンドに変更はないため、NW系コマンドはnmcliに統一してしまった方が効率的だと思います。

CentOS8 小ネタ集その2:Cockpit machineのインストール

Cockpit上で仮想マシンを管理できるようになります。

Defaultではcockpit-machinesがインストールされていないようなので、インストールした後にCockpitのサービス起動設定を実施するだけです。

1.インストール&自動起動設定

dnf -y install cockpit-machines && \
systemctl enable --now cockpit.socket && \
systemctl start --now cockpit.socket

2.Cockpitへのログイン

ブラウザを起動した後、CentOS8上のCockpitにアクセスします。

https://CentOS8のIP:9090/

ブラウザに以下の画面が表示されますので、ssh接続時と同様のCredential(Username/Passwd)でログインしてください。
f:id:metonymical:20191013120213p:plain

3.仮想マシン設定画面

以下の通り、Cockpit上で仮想マシンの作成や編集などができるようになります。
f:id:metonymical:20191013120343p:plain


以上です。

3.最後に

Virt-Managerほど柔軟に設定できないようなので、VNC serverなどと併用するのがよいかと思います。
しかし、起動中の仮想マシンのステータスが見たいときなどは重宝すると思います。

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

CentOS8におけるtigervnc-serverの設定方法を記載します。
2021/04/14追記
CentOS8.3における設定方法を追記しました。6.5.CentOS8.3の設定方法を参照してください。

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

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

6.5.CentOS8.3の設定方法

CentOS8.3におけるVNC Serverの設定方法が少し変わっています。*1

dnf -y install tigervnc-server && \
echo "session=gnome" >> /etc/tigervnc/vncserver-config-defaults && \
echo ":1=root" >> /etc/tigervnc/vncserver.users && \
mkdir /root/.vnc && \
echo "geometry=1600x1200" >> /root/.vnc/config && \
cp -p /usr/lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:1.service && \
vncpasswd

上記コマンドにてパスワード入力後、以下のようにサービスの自動起動設定を行ってください。

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

以上です。

7.最後に

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

*1:インストールから解像度設定やサービスファイルのコピー、パスワード設定までワンラインで設定可能です。

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

*3: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が異なります。