` docker(五) | 听云轩

docker(五)

跨主机通信

    通过docker网络驱动:

  • Overlay:基于vxlan封装实现docker原生overlay网络
  • Macvlan:docker主机网卡接口逻辑上分为多个子接口,每个子接口标识一个vlan。容器接口直接连接docker主机
  • 网卡接口:通过路由策略转发到另一台docker主机

    通过第三方网络项目:

  • 隧道方案:

    • Flannel:支持UDP和VLAN封装传输方式
    • Weave:支持UDP(sleeve模式)和VXLAN(优先fastdb模式)
    • OpenvSwitch:支持VXLAN和GRE封装
  • 路由方案:

    • Calico:支持BGP协议和IPIP隧道。每台宿主机作为虚拟路由,通过BGP协议实现不同主机容器间通信。
直接路由方式(通过内核转发)

    实验环境:

    由于使用容器的ip进行路由,就需要避免不同主机上的容器使用了相同的ip,为此我们应该为不同的主机分配不同的子网来保证。

    主机1的地址为:192.168.248.128

    主机2的地址为:192.168.248.129

    主机1上docker容器分配的子网:172.17.1.0/24

    主机2上docker容器分配的子网:172.17.2.0/24

    思路:

    从container1发送container2的数据包,首先发往container1的网关docker0,然后通过查找主机1的路由表得知需要将数据包发往主机2,数据包达到主机2后再转发给主机2的docker0,最后到达container2 。

    过程:

1、配置docker0的ip地址

主机一修改daemon.json文件,添加:

1
2
3
{
"bip":"172.17.1.252/24"
}

主机二同理,但是修改成2.252/24,然后重启docker

2、添加路由规则

主机一:

1
route add -net 172.17.2.0 netmask 255.255.255.0 gw 192.168.248.128

主机二:

1
route add -net 172.17.1.0 netmask 255.255.255.0 gw 192.168.248.129

3、配置路由转发

如果有iptables的话:

主机一:

1
2
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.1.0/24 ! -d 172.17.0.0/16 -j MASQUERADE

主机二:

1
2
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.2.0/24 ! -d 172.17.0.0/16 -j MASQUERADE

没有的话:

1
echo 1 > /proc/sys/net/ipv4/ip_forward

4、启动容器测试

主机一:

1
docker run -it --name container1 centos /bin/bash

主机二:

1
docker run -it --name container2 centos /bin/bash

Zy0K8H.png

通过Overlay网络

    这块参照这位博主,万分感谢。

  • 先提一下overlay网络

    overlay在网络技术领域,指的是一种网络架构上叠加的虚拟化,其大体框架是对基础不进行大规模修改的条件下,实现应用在网络上的承载,并能与其他网络业务进行分离,并且以基于ip的基础网络技术为主。overlay技术是在现有的物理网络之上构建一个虚拟网络,上层应用只与虚拟网络相关。主要有三部分构成:

  • 边缘设备:与虚拟机之间相连的设备
  • 控制平面:主要负责虚拟隧道的建立维护以及主机可达性信息的通告
  • 转发平面:承载overlay报文的物理网络

ZyrKGF.png

要想使用docker原生overlay网络,需要满足下列条件:

  • docker运行在swarm
  • 使用key-value存储的docker主机集群

使用键值存储搭建docker主机集群需要满足:

  • 集群中主机连接到键值存储,docker支持consul、etcd和zookeeper等
  • 集群中主机运行一个docker守护进程
  • 集群中主机必须具有唯一的主机名,因为键值存储使用主机名来标识群成员
  • 集群中Linux主机内核版本在3.12+,支持vxlan数据包处理,否则无法通行

(注:关于这块我在其他地方看的,也没做过测试,反正最好这样吧,如果有问题告诉我)

    由于docker overlay网络需要一个key-value数据库用于保存网络状态信息,包括network、endpoint、ip等。consul、etcd和zookeeper都是。consul是一种键值数据库,我们这可以用它存储系统的状态信息。

实验环境:
server:192.168.248.129 kernel:4.4
client:192.168.248.130 kernel:4.4

1、安装consul(server上)

方式一:

1
2
3
wget https://releases.hashicorp.com/consul/0.9.2/consul_0.9.2_linux_386.zip
unzip consul_0.9.2_linux_386.zip
mv consul /usr/bin/ && chmod a+x /usr/bin/consul

方式二:

1
docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap

2、启动consul(如果上一步用方法二就跳过)

1
2
nohup consul agent -server -bootstrap -ui -data-dir /data/docker/consul \
> -client=192.168.248.129 -bind=192.168.248.129 &> /var/log/consul.log &

注:-ui:consul的管理界面;-datadir:数据存储路径

3、各节点配置docker守护进程连接consul

server上:

1
2
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store consul://192.168.248.129:8500 --cluster-advertise 192.168.248.129:2375

其中:
–cluster-store 指定 consul 的地址。
–cluster-advertise 告知 consul 自己的连接地址。

client上:

1
2
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store consul://192.168.248.129:8500 --cluster-advertise 192.168.248.130:2375

4、放行防火墙

1
2
3
4
5
firewall-cmd --add-port=8500/tcp --permanent 
firewall-cmd --add-port=2375/tcp --permanent
firewall-cmd --add-port=4789/udp --permanent //容器之间流量的vxlan端口
firewall-cmd --add-port=7946/tcp --permanent //docker守护进程端口
firewall-cmd --add-port=7946/udp --permanent

5、打开web进行检查

ZyyrUP.png

6、创建一个overlay网络

1
docker network create -d overlay ov_net

Zyy5Eq.png

此时详细查看这个网络的信息:

ZyyH8U.png

Zyyqv4.png

由于consul的自动发现,另一台主机会自动同步新建的网络。

7、使用overlay网络创建容器

server和client上:

1
docker run -it --net=ov_net busybox

此时我们可以查看容器内的网卡信息:

Zy6mIP.png

其中:eth0是和overlay进行通信,eth1是和主机的docker_gwbridge通信(docker_gwbridge为使用overlay网络的容器提供上外网的能力)

这里使用的是自动分配的ip,如果需要静态固定ip:

1
2
3
4
5
6
创建网络的时候:
docker network create -d overlay --subnet=192.168.2.0/24 ov_net

启动容器的时候:

docker run -d --name host1 --net=ov_net --ip=192.168.2.2 centos7

8、测试

Zy6aGT.png

通信过程:

ZyWt8P.png

1、docker为每一个overlay网络创建一个单独的命名空间,在这个命名空间里面创建一个br0的bridge。

2、在这个命名空间内创建网口并挂载到br0上,分别是vxlan0和一对veth pair端口(一端在br0上,另一端在container上)

3、vxlan0用于建立vxlan tunnel,vxlan端口的vni由docker-daemon创建时分配,只有具有相同的vni才能通信。

4、docker主机集群通过key/value存储共享数据,在7946端口上,相互之间通过gossip协议学
习各个宿主机上运行了哪些容器。守护进程根据这些数据来vxlan设备上生成静态MAC转发表。

5、vxlan设备根据MAC转发表,通过主机上的4789端口将数据发到目标节点。

6、根据流量包的vxlan隧道ID,将流量转发到对端宿主机的overlay网络的网络命名空间中。

7、宿主机的overlay网络的网络命名空间中的br0网桥,起到虚拟交换机的作用,在对端网络中,将流量根据MAC地址转发到对应容器内部。

    查看namespace由于容器和overlay的网络的网络命名空间文件不在操作系统默认的/var/run/netns下,只能手动通过软连接的方式查看(此时要保证两个容器在运行):

1
ln -s /var/run/docker/netns /var/run/netns

ZyfxyT.png

    在另外一台设备上进行查看会发现,都有一个2-9ff9fe9875的命名空间。

    然后我们可以进入到这里面去查看相应的网桥和网口信息:

Zyhrpq.png

网桥上的插的网口:

ZyhXAH.png

然后查看vxlan接口的详细信息:

Zy4FHg.png

可以看见它的vni号为256

总结:

    关于使用overlay通信存在着一下缺点:

    1、由于vxlan网络与宿主机网络默认不再同一网络环境下,为了解决宿主机与容器的通信问题,docker为overlay网络中的容器额外增加了网卡eth1作为宿主机与容器通信的通道。这样在使用容器服务时,就必须根据访问性质的不同,选择不同的网卡地址,造成使用上的不便。

    2、容器对外暴露服务仍然只能使用端口绑定的方式,外界无法简单地直接使用容器IP访问容器服务。

    3、从上面的通信过程中来看,原生的overlay网络通信必须依赖docker守护进程及key/value存储来实现网络通信,约束较多,容器在启动后的一段时间内可能无法跨主机通信,这对一些比较敏感的应用来说是不可靠的。

------ 本文结束 ------
您的支持将鼓励我继续创作