作为目前最火热的容器技术,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 > 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<UP,BROADCAST,MULTICAST> 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<UP,BROADCAST,RUNNING,MULTICAST> 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<link></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<link></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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> 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: <BROADCAST,MULTICAST> 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: <BROADCAST,MULTICAST> 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,如需转载请自行联系原作者