Pipeworkで作ったネットワークを実ネットワークにL2延伸する

Jun 30, 2015   #docker  #pipework  #linux bridge 

Pipeworkで作ったネットワークをブリッジして、コンテナでもホストと同じIPアドレス帯を使えるようにします。 オンプレ的な発想ですが、割とスッキリした構成でマルチホスト通信が組めたりします。

構成

今回は理由があってCentOS6.6で検証します。 プロミスキャスは有効にしておいてください。

DockerとPipeworkを導入する

Dockerインストール

yum install epel-release
yum install docker-io
service docker start

Pipeworkインストール

yum install git
cd /usr/local/src
git clone https://github.com/jpetazzo/pipework.git
ln -sv /usr/local/src/pipework/pipework /usr/local/bin/
pipework
Syntax:
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> dhcp [macaddr][@vlan]
pipework --wait [-i containerinterface]

iprouteパッケージを置き換える

CentOS6系の場合は、iprouteがnetnsに対応していないため、上記の手順だけだとPipeworkが動きません。 netnsに対応しているiprotueは、OpenStackのリポジトリから入手できます。

rpm -qa | grep iproute
iproute-2.6.32-32.el6_5.x86_64

curl -O https://repos.fedorapeople.org/repos/openstack/openstack-icehouse/epel-6/iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm
yum localinstall ./iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm

ブリッジを作る

ブリッジを作るので、ホストのインターフェース設定を書き換えます。

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

DEVICE=eth0
HWADDR=00:0C:29:7C:49:9C
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=none
BRIDGE=br0

コンテナが接続する仮想ブリッジを作成します。 IP等はホストのeth0で使っていたものをそのまま引き継いでます。

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

DEVICE=br0
TYPE=Bridge
BOOTPROTO=no
IPADDR=192.168.79.52
NETMASK=255.255.255.0
NETWORK=192.168.79.0
BROADCAST=192.168.79.255
DELAY=0
GATEWAY=192.168.79.254
ONBOOT=yes

設定できたらネットワークを再起動します。

service network restart

iptablesにルールを追記する

今のままだとブリッジ系のトラフィックが落とされるので、iptablesにルールを1行追加します。

iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
service iptables save
service iptables restart

下記の状態になっていれば正常です。

iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere            PHYSDEV match --physdev-is-bridged
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere            ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (1 references)
target     prot opt source               destination

まずは普通にコンテナを立ち上げる

普通にdocker runをしてコンテナを起動します。 コンテナのネットワークはdocker0に繋がるインターフェースがある普通の感じです。

docker run -it --name pipetest centos:6
ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:3 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:238 (238.0 b)  TX bytes:238 (238.0 b)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0
0.0.0.0         172.17.42.1     0.0.0.0         UG        0 0          0 eth0

Pipeworkでコンテナにインターフェースを追加する

ホスト側でPipeworkを使ってコンテナにインターフェースを追加します。 コマンドの書式は下記の通りです。

pipework
Syntax:
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> dhcp [macaddr][@vlan]
pipework --wait [-i containerinterface]
  • 先ほど作ったブリッジ(br0)とコンテナ(pipetest)を接続する。
  • コンテナ側に追加するインターフェース名はeth1とする。
  • コンテナに割り当てるIPは192.168.79.60/24とする。
  • コンテナのデフォルトゲートウェイ(192.168.79.254)を、今回追加するeth1方向に変更する。

の場合、下記のコマンドになります。

pipework br0 -i eth1 pipetest 192.168.79.60/24@192.168.79.254

ちなみに、-iオプションで指定しない場合はeth1という名前でインターフェースを作成します。 既にコンテナにeth1がある状態の場合は-iで別の名前を指定しないと処理が止まりますので、注意が必要です。

実行したらコンテナに入って確認してみます。 先ほどは無かったeth1が出現しました。

ifconfig eth1
eth1      Link encap:Ethernet  HWaddr 82:D4:55:7E:0D:01  
          inet addr:192.168.79.60  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::80d4:55ff:fe7e:d01/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:127 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:9422 (9.2 KiB)  TX bytes:1093 (1.0 KiB)

ルーティングも変わっています。

netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.79.0    0.0.0.0         255.255.255.0   U         0 0          0 eth1
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0
0.0.0.0         192.168.79.254  0.0.0.0         UG        0 0          0 eth1

別のセグメントにも通信できています。

ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=3.41 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=3.60 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=56 time=3.56 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2066ms
rtt min/avg/max/mdev = 3.419/3.529/3.607/0.105 ms

別セグの端末からコンテナ宛のPingも通りました。

オンプレの場合、Weaveとか使うよりこちらの方が親和性高そうで良いかもです。 フロントとバックのネットワークを物理的に分離できたりもしますし。