天天看點

Docker實踐 -- 使用Open vSwitch實作跨主機通信

作為目前最火熱的容器技術,docker在網絡實作和管理方面還存在不足。最開始的docker是依賴于Linux Bridge實作的網絡設定,隻能在容器裡建立一個網卡。後來随着docker/libnetwork項目的進展,docker的網絡管理功能逐漸多了起來。盡管如此,跨主機通信對于docker來說還是一個需要面對的問題,這一點對于kubernetes類的容器管理系統異常重要。目前市面上主流的解決方法有flannel, weave, Pipework, Open vSwitch等。

Open vSwitch實作比較簡單,成熟且功能強大,是以很适合作為解決docker底層網絡互聯互通的工具。言歸正傳,如下是基本架構圖:

具體的實作步驟如下:

1. 安裝docker, bridge-utils和openvswitch

<code>[root@dockerserver1 ~]</code><code># yum install docker bridge-utils -y </code>

<code>[root@dockerserver1 ~]</code><code># yum install wget openssl-devel -y </code>

<code>[root@dockerserver1 ~]</code><code># yum groupinstall "Development Tools"</code>

<code>[root@dockerserver1 ~]</code><code># adduser ovswitch</code>

<code>[root@dockerserver1 ~]</code><code># su - ovswitch</code>

<code>[ovswitch@dockerserver1 ~]$ wget http:</code><code>//openvswitch</code><code>.org</code><code>/releases/openvswitch-2</code><code>.3.0.</code><code>tar</code><code>.gz</code>

<code>[ovswitch@dockerserver1 ~]$ </code><code>tar</code> <code>-zxvpf openvswitch-2.3.0.</code><code>tar</code><code>.gz</code>

<code>[ovswitch@dockerserver1 ~]$ </code><code>mkdir</code> <code>-p ~</code><code>/rpmbuild/SOURCES</code>

<code>[ovswitch@dockerserver1 ~]$ </code><code>sed</code> <code>'s/openvswitch-kmod, //g'</code> <code>openvswitch-2.3.0</code><code>/rhel/openvswitch</code><code>.spec &gt; openvswitch-2.3.0</code><code>/rhel/openvswitch_no_kmod</code><code>.spec</code>

<code>[ovswitch@dockerserver1 ~]$ </code><code>cp</code> <code>openvswitch-2.3.0.</code><code>tar</code><code>.gz rpmbuild</code><code>/SOURCES/</code>

<code>     </code> 

<code>[ovswitch@dockerserver1 ~]$ rpmbuild -bb --without check ~</code><code>/openvswitch-2</code><code>.3.0</code><code>/rhel/openvswitch_no_kmod</code><code>.spec</code>

<code>[ovswitch@dockerserver1 ~]$ </code><code>exit</code>

<code>[root@dockerserver1 ~]</code><code># yum localinstall /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.0-1.x86_64.rpm -y</code>

<code>[root@dockerserver1 ~]</code><code># mkdir /etc/openvswitch</code>

<code>[root@dockerserver1 ~]</code><code># setenforce 0</code>

2. 在dockerserver1上編輯/usr/lib/systemd/system/docker.service檔案,添加docker啟動選項"--bip=10.0.0.1/24",如下:

<code>[root@dockerserver1 ~]</code><code># cat /usr/lib/systemd/system/docker.service</code>

<code>[Unit]</code>

<code>Description=Docker Application Container Engine</code>

<code>Documentation=http:</code><code>//docs</code><code>.docker.com</code>

<code>After=network.target rhel-push-plugin.socket registries.service</code>

<code>Wants=docker-storage-setup.service</code>

<code>Requires=docker-cleanup.timer</code>

<code>[Service]</code>

<code>Type=notify</code>

<code>NotifyAccess=all</code>

<code>EnvironmentFile=-</code><code>/run/containers/registries</code><code>.conf</code>

<code>EnvironmentFile=-</code><code>/etc/sysconfig/docker</code>

<code>EnvironmentFile=-</code><code>/etc/sysconfig/docker-storage</code>

<code>EnvironmentFile=-</code><code>/etc/sysconfig/docker-network</code>

<code>Environment=GOTRACEBACK=crash</code>

<code>Environment=DOCKER_HTTP_HOST_COMPAT=1</code>

<code>Environment=PATH=</code><code>/usr/libexec/docker</code><code>:</code><code>/usr/bin</code><code>:</code><code>/usr/sbin</code>

<code>ExecStart=</code><code>/usr/bin/dockerd-current</code> <code>\</code>

<code>          </code><code>--add-runtime docker-runc=</code><code>/usr/libexec/docker/docker-runc-current</code> <code>\</code>

<code>          </code><code>--default-runtime=docker-runc \</code>

<code>          </code><code>--</code><code>exec</code><code>-opt native.cgroupdriver=systemd \</code>

<code>          </code><code>--userland-proxy-path=</code><code>/usr/libexec/docker/docker-proxy-current</code> <code>\</code>

<code>          </code><code>--bip=10.0.0.1</code><code>/24</code> <code>\</code>

<code>          </code><code>$OPTIONS \</code>

<code>          </code><code>$DOCKER_STORAGE_OPTIONS \</code>

<code>          </code><code>$DOCKER_NETWORK_OPTIONS \</code>

<code>          </code><code>$ADD_REGISTRY \</code>

<code>          </code><code>$BLOCK_REGISTRY \</code>

<code>          </code><code>$INSECURE_REGISTRY\</code>

<code>          </code><code>$REGISTRIES  </code>

<code>ExecReload=</code><code>/bin/kill</code> <code>-s HUP $MAINPID</code>

<code>LimitNOFILE=1048576</code>

<code>LimitNPROC=1048576</code>

<code>LimitCORE=infinity</code>

<code>TimeoutStartSec=0</code>

<code>Restart=on-abnormal</code>

<code>MountFlags=slave</code>

<code>KillMode=process</code>

<code>[Install]</code>

<code>WantedBy=multi-user.target</code>

<code>[root@dockerserver1 ~]</code><code>#</code>

3. 在dockerserver2上編輯/usr/lib/systemd/system/docker.service檔案,添加docker啟動選項"--bip=10.0.1.1/24",如下:

<code>[root@dockerserver2 ~]</code><code># cat /usr/lib/systemd/system/docker.service   </code>

<code>          </code><code>--bip=10.0.1.1</code><code>/24</code> <code>\</code>

<code>          </code><code>$REGISTRIES</code>

<code>[root@dockerserver2 ~]</code><code>#</code>

4. 在兩個主機上啟動docker服務

<code># systemctl start docker  </code>

<code># systemctl enable docker</code>

5. docker服務啟動後,可以看到一個新的bridge docker0被建立出來,并且被賦予了我們之前配置的IP位址:

<code>[root@dockerserver1 ~]</code><code># brctl show</code>

<code>bridge name     bridge </code><code>id</code>               <code>STP enabled     interfaces</code>

<code>docker0         8000.02427076111e       no</code>

<code>[root@dockerserver1 ~]</code><code># ifconfig docker0</code>

<code>docker0: flags=4099&lt;UP,BROADCAST,MULTICAST&gt;  mtu 1500</code>

<code>        </code><code>inet 10.0.0.1  netmask 255.255.255.0  broadcast 0.0.0.0</code>

<code>        </code><code>ether 02:42:70:76:11:1e  txqueuelen 0  (Ethernet)</code>

<code>        </code><code>RX packets 0  bytes 0 (0.0 B)</code>

<code>        </code><code>RX errors 0  dropped 0  overruns 0  frame 0</code>

<code>        </code><code>TX packets 0  bytes 0 (0.0 B)</code>

<code>        </code><code>TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0</code>

<code>[root@dockerserver2 ~]</code><code># brctl show</code>

<code>docker0         8000.0242ba00c394       no</code>

<code>[root@dockerserver2 ~]</code><code># ifconfig docker0</code>

<code>        </code><code>inet 10.0.1.1  netmask 255.255.255.0  broadcast 0.0.0.0</code>

<code>        </code><code>ether 02:42:ba:00:c3:94  txqueuelen 0  (Ethernet)</code>

6. 在兩個主機上啟動openvswitch

<code># systemctl start openvswitch</code>

<code># chkconfig openvswitch on</code>

7. 在兩個主機上建立隧道網橋br-tun,并通過VXLAN協定建立隧道

<code>[root@dockerserver1 ~]</code><code># ovs-vsctl add-br br-tun</code>

<code>[root@dockerserver1 ~]</code><code># ovs-vsctl add-port br-tun vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip=10.10.172.204</code>

<code>[root@dockerserver1 ~]</code><code># brctl show </code>

<code>docker0         8000.02427076111e       no              br-tun</code>

<code>[root@dockerserver2 ~]</code><code># ovs-vsctl add-br br-tun </code>

<code>[root@dockerserver2 ~]</code><code># ovs-vsctl add-port br-tun vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip=10.10.172.203</code>

<code>docker0         8000.0242ba00c394       no              br-tun</code>

8. 将br-tun作為接口加入docker0網橋

<code>[root@dockerserver1 ~]</code><code># brctl addif docker0 br-tun </code>

<code>[root@dockerserver2 ~]</code><code># brctl addif docker0 br-tun</code>

9. 由于兩個主機的容器處于不同的網段,需要添加路由才能讓兩邊的容器互相通信

<code>[root@dockerserver1 ~]</code><code># ip route add 10.0.1.0/24 via 10.10.172.204 dev eth0 </code>

<code>[root@dockerserver2 ~]</code><code># ip route add 10.0.0.0/24 via 10.10.172.203 dev eth0</code>

10. 在兩個主機上各自啟動一個docker容器,驗證互相能否通信。

<code>[root@dockerserver1 ~]</code><code># docker run --rm -it centos /bin/bash         </code>

<code>[root@8f3cac41a7d5 /]</code><code># yum install net-tools -y</code>

<code>[root@8f3cac41a7d5 /]</code><code># ifconfig eth0</code>

<code>eth0: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500</code>

<code>        </code><code>inet 10.0.0.2  netmask 255.255.255.0  broadcast 0.0.0.0</code>

<code>        </code><code>inet6 fe80::42:aff:fe00:2  prefixlen 64  scopeid 0x20&lt;link&gt;</code>

<code>        </code><code>ether 02:42:0a:00:00:02  txqueuelen 0  (Ethernet)</code>

<code>        </code><code>RX packets 4266  bytes 13337782 (12.7 MiB)</code>

<code>        </code><code>TX packets 4144  bytes 288723 (281.9 KiB)</code>

<code>[root@8f3cac41a7d5 /]</code><code>#</code>

<code>[root@dockerserver2 ~]</code><code># docker run --rm -it centos /bin/bash</code>

<code>[root@3edc0ed8f805 /]</code><code># yum install net-tools -y</code>

<code>[root@3edc0ed8f805 /]</code><code># ifconfig eth0</code>

<code>        </code><code>inet 10.0.1.2  netmask 255.255.255.0  broadcast 0.0.0.0</code>

<code>        </code><code>inet6 fe80::42:aff:fe00:102  prefixlen 64  scopeid 0x20&lt;link&gt;</code>

<code>        </code><code>ether 02:42:0a:00:01:02  txqueuelen 0  (Ethernet)</code>

<code>        </code><code>RX packets 4536  bytes 13344451 (12.7 MiB)</code>

<code>        </code><code>TX packets 4381  bytes 301685 (294.6 KiB)</code>

<code>[root@3edc0ed8f805 /]</code><code># ping 10.0.0.2</code>

<code>PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.</code>

<code>64 bytes from 10.0.0.2: icmp_seq=1 ttl=62 </code><code>time</code><code>=1.68 ms</code>

<code>^C</code>

<code>--- 10.0.0.2 </code><code>ping</code> <code>statistics ---</code>

<code>1 packets transmitted, 1 received, 0% packet loss, </code><code>time</code> <code>0ms</code>

<code>rtt min</code><code>/avg/max/mdev</code> <code>= 1.683</code><code>/1</code><code>.683</code><code>/1</code><code>.683</code><code>/0</code><code>.000 ms</code>

<code>[root@3edc0ed8f805 /]</code><code>#</code>

11.檢視兩個docker主控端的網卡資訊

<code>[root@dockerserver1 ~]</code><code># ip addr list</code>

<code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN </code>

<code>    </code><code>link</code><code>/loopback</code> <code>00:00:00:00:00:00 brd 00:00:00:00:00:00</code>

<code>    </code><code>inet 127.0.0.1</code><code>/8</code> <code>scope host lo</code>

<code>       </code><code>valid_lft forever preferred_lft forever</code>

<code>    </code><code>inet6 ::1</code><code>/128</code> <code>scope host </code>

<code>2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP qlen 1000</code>

<code>    </code><code>link</code><code>/ether</code> <code>00:50:56:86:3e:d8 brd ff:ff:ff:ff:ff:ff</code>

<code>    </code><code>inet 10.10.172.203</code><code>/24</code> <code>brd 10.10.172.255 scope global eth0</code>

<code>    </code><code>inet6 fe80::250:56ff:fe86:3ed8</code><code>/64</code> <code>scope link </code>

<code>3: docker0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN </code>

<code>    </code><code>link</code><code>/ether</code> <code>02:42:70:76:11:1e brd ff:ff:ff:ff:ff:ff</code>

<code>    </code><code>inet 10.0.0.1</code><code>/24</code> <code>scope global docker0</code>

<code>    </code><code>inet6 fe80::42:70ff:fe76:111e</code><code>/64</code> <code>scope link </code>

<code>4: ovs-system: &lt;BROADCAST,MULTICAST&gt; mtu 1500 qdisc noop state DOWN </code>

<code>    </code><code>link</code><code>/ether</code> <code>06:19:20:ae:f6:61 brd ff:ff:ff:ff:ff:ff</code>

<code>5: br-tun: &lt;BROADCAST,MULTICAST&gt; mtu 1500 qdisc noop master docker0 state DOWN </code>

<code>    </code><code>link</code><code>/ether</code> <code>42:2c:39:7f:a2:4a brd ff:ff:ff:ff:ff:ff</code>

<code>[root@dockerserver2 ~]</code><code># ip addr</code>

<code>    </code><code>link</code><code>/ether</code> <code>00:50:56:86:22:d8 brd ff:ff:ff:ff:ff:ff</code>

<code>    </code><code>inet 10.10.172.204</code><code>/24</code> <code>brd 10.10.172.255 scope global eth0</code>

<code>    </code><code>inet6 fe80::250:56ff:fe86:22d8</code><code>/64</code> <code>scope link </code>

<code>    </code><code>link</code><code>/ether</code> <code>02:42:ba:00:c3:94 brd ff:ff:ff:ff:ff:ff</code>

<code>    </code><code>inet 10.0.1.1</code><code>/24</code> <code>scope global docker0</code>

<code>    </code><code>inet6 fe80::42:baff:fe00:c394</code><code>/64</code> <code>scope link </code>

<code>    </code><code>link</code><code>/ether</code> <code>be:d4:64:ee:cb:29 brd ff:ff:ff:ff:ff:ff</code>

<code>    </code><code>link</code><code>/ether</code> <code>6e:3d:3e:1a:6a:4e brd ff:ff:ff:ff:ff:ff</code>

<code></code>

本文轉自 dengaosky 51CTO部落格,原文連結:http://blog.51cto.com/dengaosky/2067784,如需轉載請自行聯系原作者