古いバージョンのブラウザーを使用しています。MSN を最適にご利用いただくために、サポートされているバージョンをご使用ください。

第35回 Open vSwitchで作るDockerのネットワーク(OVSで構築する編)

ITmedia エンタープライズ のロゴ ITmedia エンタープライズ 2017/02/07
第35回 Open vSwitchで作るDockerのネットワーク(OVSで構築する編): 今回構成するネットワーク構成 © ITmedia エンタープライズ 提供 今回構成するネットワーク構成

 今回は、前回ご紹介したOpen vSwitch(Open Virtual Switch、通称「OVS」)を利用するネットワークを構築していきます。以下では、実際にOVSを使ってホストOSとDockerコンテナを同一LANセグメントに所属させることで、マルチホストのコンテナ間通信を行う設定の手順を示します。OSは、CentOS 7.3を想定します。ネットワーク構成は次の通りです。

 今回は、コンテナc2にWebサーバをインストールし、コンテナc1および同一LANセグメント上のCentOS 7.2がインストールされたクライアントマシンから、コンテナc2の提供するテスト用のWebコンテンツにアクセスできるかどうかをテストします。

OVSのインストール

 まずは、ホストOS上にOVSをインストールします。OVSは、OpenStackのコミュニティーの1つである「RDO」が提供するリポジトリを追加することで入手できます。リポジトリは、以下のようにyumコマンドで追加可能です。一般的にOpenStackコミュニティーが提供するリポジトリのURLは、OpenStackのバージョンによって異なりますが、今回は2017年1月時点でのOpenStackコミュニティーの最新版「Newton」に対応したリポジトリを追加します。

# yum install -y https://repos.fedorapeople.org/repos/openstack/openstack-newton/rdo-release-newton-4.noarch.rpm

 RDOが提供するリポジトリを追加し、ホストOSにOVSをインストールします。

# yum install -y openvswitch

 ホストOSにOVSをインストールできたら、次にホストOS用のブリッジ・インタフェース「br-ex」の設定ファイル「ifcfg-br-ex」と、それに対応するNICのeth0の設定ファイル「ifcfg-eth0」を作成します。今回は、br-exの固定IPアドレスとして「172.16.1.100/16」を割り当てます。ifcfg-eth0ファイル内の「HWADDR=」の行には、物理NICのMACアドレスを指定しますので注意してください。

# cd /etc/sysconfig/network-scripts/

# cp ifcfg-eth0 org.ifcfg-eth0

# vi ifcfg-eth0

NAME="eth0"

HWADDR="6C:3B:E5:50:3B:30"

ONBOOT=yes

TYPE=OVSPort

DEVICETYPE=ovs

NM_CONTROLLED=no

OVS_BRIDGE=br-ex

 OVSブリッジbr-ex用のifcfg-br-exを編集します。OVSブリッジの設定では、「DEVICETYPE=ovs」を指定し、さらに、「TYPE=OVSBridge」を指定します。OVSブリッジの設定ファイルには、通常の物理NICの場合と同様に、IPアドレス、ネットマスク、デフォルトゲートウェイ、参照先DNSサーバを記述できます。

# vi ifcfg-br-ex

DEVICE=br-ex

DEVICETYPE=ovs

TYPE=OVSBridge

BOOTPROTO=static

IPADDR=172.16.1.100

NETMASK=255.255.0.0

GATEWAY=172.16.1.1

DNS1=172.16.1.254

ONBOOT=yes

 OVSブリッジの設定ファイルを用意したら、ホストOSを再起動します。この際に、OVSブリッジのみで外部と通信を行う設定になっている場合は、設定に不備があると、リモートからホストOSにログインできなくなります。必ずローカルのキーボードとディスプレイで再設定できるようにしておくか、サーバのマザーボードに搭載された遠隔管理チップ(HPE iLO4など)が提供する仮想コンソール経由のリモート接続ができる状態であることを確認してください。

# reboot

 ホストOSが再起動した後、IPアドレスを確認します。

# ip -4 a

inet 127.0.0.1/8 scope host lo

valid_lft forever preferred_lft forever

inet 172.16.1.100/16 brd 172.16.255.255 scope global br-ex

valid_lft forever preferred_lft forever

inet 172.17.0.1/16 scope global docker0

valid_lft forever preferred_lft forever

 次に、OVSの状況を確認します。以下のように、OVSが提供する「ovs-vsctl」コマンドに「show」を付与して実行します。

# ovs-vsctl show

25d8ffb2-b620-469f-9944-df87cb829aa7

Bridge br-ex

Port "eth0"

Interface "eth0"

Port br-ex

Interface br-ex

type: internal

ovs_version: "2.5.0"

 上記のように、eth0のポートと仮想ブリッジbr-exのポートが両方表示されていることを確認してください。またipコマンドで、IPアドレスの付与状況と、仮想ブリッジのbr-ex経由で外部のネットワークと通信できるかどうかも併せて確認してください。

Bashスクリプト「ovs-docker」のインストール

 OVSを構成したホストOS環境でコンテナに固定IPアドレスを付与するために、前回記事の最後に紹介したBashスクリプトの「ovs-docker」をインストールします。wgetコマンドを使ってovs-dockerを入手し、ホストOS上の/usr/local/bin/ディレクトリに保存します。

# export http_proxy=http://proxy.your.site.com:8080 ←適宜プロキシサーバを設定

# export https_proxy=http://proxy.your.site.com:8080 ←適宜プロキシサーバを設定

# wget -O /usr/local/bin/ovs-docker \

https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-docker

 正しく入手できているか、念のため中身を確認します。

# less /usr/local/bin/ovs-docker

#!/bin/bash

...

...

# file /usr/local/bin/ovs-docker

/usr/local/bin/ovs-docker: Bourne-Again shell script, ASCII text executable

 ホストOS上に保存したovs-dockerに実行権を付与します。

# chmod 755 /usr/local/bin/ovs-docker

# ls -l /usr/local/bin/ovs-docker

-rwxr-xr-x 1 root root 8064 1月 8 11:16 /usr/local/bin/ovs-docker

 以上で、Dockerコンテナに固定IPアドレスを付与する準備が整いました。

ホストOSにおけるDockerエンジンの設定

 ホストOS上に、最新のDockerエンジンをインストールします。以下のように、curlコマンドでインストールすることが可能です。ホストOSがプロキシサーバ経由でインターネットにアクセスする場合は、適宜プロキシサーバの環境変数を事前に設定してください。

# export http_proxy=http://proxy.your.site.com:8080 ←適宜プロキシサーバを設定

# export https_proxy=http://proxy.your.site.com:8080 ←適宜プロキシサーバを設定

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

 連載33回でご紹介したのと同様に、「/etc/sysconfig/docker」ファイルを読み込むように設定ファイル「docker.service」を記述します。もし、以下の設定ファイル「docker.service」が「/etc/systemd/system」ディレクトリに存在しない場合は、事前に「/usr/lib/systemd/system」ディレクトリからコピーしておく必要があります。

# cd /etc/systemd/system/

# cp /usr/lib/systemd/system/docker.service .

# vi ./docker.service

# cat /etc/systemd/system/docker.service |grep -v ^# |grep -v ^$

[Unit]

Description=Docker Application Container Engine

Documentation=https://docs.docker.com

After=network.target

[Service]

Type=notify

EnvironmentFile=-/etc/sysconfig/docker ←設定ファイルを定義

EnvironmentFile=-/etc/sysconfig/docker-storage ←設定ファイルを定義

EnvironmentFile=-/etc/sysconfig/docker-network ←設定ファイルを定義

ExecStart=/usr/bin/dockerd \ ←複数行にわたるため、「\」を追加

$OPTIONS \ ←設定ファイル内で定義される環境変数を追加

$DOCKER_STORAGE_OPTIONS \ ←設定ファイル内で定義される環境変数を追加

$DOCKER_NETWORK_OPTIONS \ ←設定ファイル内で定義される環境変数を追加

$ADD_REGISTRY \ ←設定ファイル内で定義される環境変数を追加

$BLOCK_REGISTRY \ ←設定ファイル内で定義される環境変数を追加

$INSECURE_REGISTRY ←設定ファイル内で定義される環境変数を追加

ExecReload=/bin/kill -s HUP $MAINPID

LimitNOFILE=infinity

LimitNPROC=infinity

LimitCORE=infinity

TimeoutStartSec=0

Delegate=yes

KillMode=process

[Install]

WantedBy=multi-user.target

 ホストOSのsystemdに、上記の設定ファイルの変更を通知します。

# systemctl daemon-reload

 これでDockerデーモン(/usr/bin/dockerd)が、各設定ファイルに記載された文字列をオプションとして認識できるようになりました。次に、Dockerの設定ファイル「/etc/sysconfig/docker-network」内で、プロキシサーバなどを適切に設定しておきます。

# vi /etc/sysconfig/docker-network

http_proxy=http://proxy.your.site.com:8080

https_proxy=http://proxy.your.site.com:8080

no_proxy=localhost,172.16.1.100,/var/run/docker.sock

 今回は、「/etc/sysconfig/docker」ファイル内の「OPTIONS行」では何も指定しません。

# vi /etc/sysconfig/docker

OPTIONS='' ←今回は、オプションを付与しない

DOCKER_CERT_PATH=/etc/docker

 ホストOSが起動したら、Dockerエンジンのサービスが自動的に起動するよう設定します。

# systemctl restart docker

# systemctl enable docker

# systemctl status docker

 ホストOSの再起動後、Dockerのバージョンを確認します。

# reboot

# docker version

Client:

Version: 1.12.5

API version: 1.24

Go version: go1.6.4

Git commit: 7392c3b

Built: Fri Dec 16 02:23:59 2016

OS/Arch: linux/amd64

Server:

Version: 1.12.5

API version: 1.24

Go version: go1.6.4

Git commit: 7392c3b

Built: Fri Dec 16 02:23:59 2016

OS/Arch: linux/amd64

仮想NICを持たないDockerコンテナの起動

 今回はテスト用に、CentOS 6.8のDockerイメージを入手します。

# docker pull centos:6.8

# docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

centos 6.8 0cd976dc0a98 4 months ago 194.5 MB

 入手したCentOS 6.8のDockerイメージから、コンテナc1(ホスト名はc1)とコンテナc2(ホスト名はc2)を起動します。コンテナのホスト名は、コンテナ起動時に「-h」オプションで付与可能です。Dockerでは、コンテナ起動時に「--net=」でコンテナのネットワークモードを明示的に指定できますが、ここではコンテナにネットワークインタフェース(仮想NIC)が自動的に付与されないように、「--net=none」を指定しておきます。

# docker run -itd --name c1 -h c1 --net=none centos:6.8

# docker run -itd --name c2 -h c2 --net=none centos:6.8

 コンテナc1とc2が稼働しているかを確認します。

# docker ps -a

CONTAINER ID IMAGE COMMAND ... STATUS ... NAMES

72caf53bc996 centos:6.8 "/bin/bash" ... Up 25 minutes ... c2

7ae9edf17dea centos:6.8 "/bin/bash" ... Up 25 minutes ... c1

Dockerコンテナに仮想NICを追加し、固定IPアドレスを設定する

 現時点では、ネットワークインタフェースの存在しないコンテナが2つ稼働している状態です。それでは、先ほどインストールしたovs-dockerコマンドを使って、コンテナc1に固定IPアドレスを付与します。今回は、コンテナc1のIPアドレスとして「172.16.1.171/16」、デフォルトゲートウェイを「172.16.1.1」に設定します。また、MACアドレスも明示的に設定しておきます。

# ovs-docker add-port br-ex eth0 c1 \

> --ipaddress=172.16.1.171/16 \

> --gateway=172.16.1.1 \

> --macaddress="00:01:02:03:04:05"

 同様に、コンテナc2にもIPアドレス、デフォルトゲートウェイ、MACアドレスを設定します。

# ovs-docker add-port br-ex eth0 c2 \

> --ipaddress=172.16.1.172/16 \

> --gateway=172.16.1.1 \

> --macaddress="00:01:02:03:04:06"

 以上で、コンテナc1とc2に固定IPアドレスが付与されました。稼働中のコンテナc1とc2のIPアドレスをホストOS上から確認します。

# docker inspect \

> --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \

> c1

172.16.1.171

# docker inspect \

> --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \

> c2

172.16.1.172

 再びovs-vsctlコマンドにshowを付与し、OVSブリッジの状態を確認します。

# ovs-vsctl show

25d8ffb2-b620-469f-9944-df87cb829aa7

Bridge br-ex

Port "eth0"

Interface "eth0"

Port br-ex

Interface br-ex

type: internal

Port "ad078bb715764_l"

Interface "ad078bb715764_l"

Port "6d88c5d59f814_l"

Interface "6d88c5d59f814_l"

ovs_version: "2.5.0"

コンテナc1のIPアドレスの確認、疎通確認

 コンテナc1にログインします。以下では、コンテナc1のrootアカウントのコマンドプロンプトを「c1 #」、コンテナc2のrootアカウントのコマンドプロンプトを「c2 #」とします。

# docker exec -it c1 /bin/bash

c1 #

 コンテナc1上で、yumコマンドを使ってRPMパッケージをインストールします。コンテナc1がプロキシサーバ経由でインターネットにアクセスする場合は、コンテナc1上の「/etc/yum.conf」ファイルにプロキシサーバの設定を追記しておきます。

c1 # echo "proxy=http://proxy.your.site.com:8080" >> /etc/yum.conf

 コンテナc1上でipコマンドを使ってIPアドレスを確認するため、コンテナc1上にiproute RPMパッケージをインストールします。

c1 # yum install -y iproute

 コンテナc1でIPアドレスとMACアドレスが正しく設定されているかを確認します。

c1 # ip a

...

link/ether 00:01:02:03:04:05 brd ff:ff:ff:ff:ff:ff

inet 172.16.1.171/16 scope global eth0

valid_lft forever preferred_lft forever

inet6 fe80::9c6c:c3ff:fed7:eaa8/64 scope link

valid_lft forever preferred_lft forever

 さらに、コンテナc1のデフォルトゲートウェイが正しく設定されているかを確認します。

c1 # netstat -rn

Kernel IP routing table

Destination Gateway Genmask Flags MSS Window irtt Iface

0.0.0.0 172.16.1.1 0.0.0.0 UG 0 0 0 eth0

172.16.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0

 コンテナc1からコンテナc2のIPアドレス(172.16.1.172/16)に対して、pingコマンドで疎通確認を行います。

c1 # ping -c 3 172.16.1.172

PING 172.16.1.172 (172.16.1.172) 56(84) bytes of data.

64 bytes from 172.16.1.172: icmp_seq=1 ttl=64 time=0.250 ms

64 bytes from 172.16.1.172: icmp_seq=2 ttl=64 time=0.050 ms

64 bytes from 172.16.1.172: icmp_seq=3 ttl=64 time=0.042 ms

--- 172.16.1.172 ping statistics ---

3 packets transmitted, 3 received, 0% packet loss, time 1999ms

rtt min/avg/max/mdev = 0.042/0.114/0.250/0.096 ms

 以上で、コンテナc1とc2の通信が可能であることを確認できました。

コンテナc2をWebサーバにする

 Webサーバが稼働するコンテナc2を構築します。コンテナc2にApache Webサーバのhttpd RPMパッケージをインストールします。稼働中のコンテナc2にログインし、作業します。

# docker exec -it c2 /bin/bash

c2 # echo "proxy=http://proxy.your.site.com:8080" >> /etc/yum.conf

c2 # yum install -y httpd iproute

 テスト用のWebコンテンツ「test.html」を、コンテナc2上の「/var/www/html」ディレクトリに作成します。

c2 # echo "Hello OVS with Docker." > /var/www/html/test.html

 コンテナc2でIPアドレスとMACアドレスが正しく設定されているかを確認します。

c2 # ip a

...

link/ether 00:01:02:03:04:06 brd ff:ff:ff:ff:ff:ff

inet 172.16.1.172/16 scope global eth0

valid_lft forever preferred_lft forever

inet6 fe80::c414:28ff:feb4:f845/64 scope link

valid_lft forever preferred_lft forever

コンテナc2が提供するWebコンテンツtest.htmlを確認

 コンテナc1と同一LANセグメントに存在するクライアントから、コンテナc1に疎通確認を行います。Linuxが稼働するクライアントのコマンドプロンプトを「client $」で表すとします。

client $ ping -c 3 172.16.1.172

...

...

 クライアントから、コンテナc2が提供するWebコンテンツにアクセスできるかを確認します。

client $ curl http://172.16.1.172/test.html

Hello OVS with Docker.

 同様にコンテナc1からも、コンテナc2が提供するWebコンテンツにアクセスできるかを確認します。

c1 # curl http://172.16.1.172/test.html

Hello OVS with Docker.

 以上で、ホストOSと同一LANセグメントに所属するコンテナc1、c2を作成し、コンテナc1とクライアントからコンテナc2が提供するWebコンテンツtest.htmlを閲覧することができました。

 今回は単純なネットワーク構成ですが、OVSを利用することで、簡単に構築できることがお分かりいただけたかと思います。次回はOVSの管理や変更方法を解説します。

●古賀政純(こが・まさずみ)

日本ヒューレット・パッカード株式会社 オープンソース・Linuxテクノロジーエバンジェリスト。兵庫県伊丹市出身。1996年頃からオープンソースに携わる。2000年よりUNIXサーバーのSE及びスーパーコンピューターの並列計算プログラミング講師、SIを経験。2006年、米国ヒューレット・パッカードからLinux技術の伝道師として「OpenSource and Linux Ambassador Hall of Fame」を2年連続受賞。プリセールスMVPを4度受賞。現在は日本ヒューレット・パッカードにて、Hadoop、Spark、Docker、Linux、FreeBSDなどのサーバー基盤のプリセールスSE、文書執筆を担当。日本ヒューレット・パッカードが認定するオープンソース・Linux テクノロジーエバンジェリストとして、メディアでの連載記事執筆、講演活動なども行っている。Red Hat Certified Virtualization Administrator, Novell Certified Linux Professional, Red Hat Certified System Administrator in Red Hat OpenStack, Cloudera Certified Administrator for Apache Hadoopなどの技術者認定資格を保有。著書に「OpenStack 実践ガイド」「Docker 実践ガイド」「CentOS 7実践ガイド」「Ubuntu Server実践入門」などがある。趣味はレーシングカートとビリヤード。古賀氏の最新記事が読めるブログはこちら。

ITmedia エンタープライズの関連記事

image beaconimage beaconimage beacon