docker的跨主机网络

前言

这篇文件分两种方式介绍docker跨主机通信,overlaymacvlan,macvlan的方式给大家做个参考,生产环境下不推荐大家使用这种方式 🐴 。。。。

解决方案一:overlay的解决方案

默认的自定义网络的类型就是bridge,但是无法在单宿主机网络里面的可以通过docker network connect的命令互通;但是跨主机的时候bridge就明显不可用的;可以使用overlaymacvlan实现

为支持容器跨主机通信,Docker 提供了 overlay driver,使用户可以创建基于 VxLAN 的 overlay 网络。VxLAN 可将二层数据封装到 UDP 进行传 输,VxLAN 提供与 VLAN 相同的以太网二层服务,但是拥有更强的扩展性和灵活性

Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。这样不但能够充分利用成熟的IP路由协议进程数据分发;而且在Overlay技术中采用扩展的隔离标识位数,能够突破VLAN的4000数量限制支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。

因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案

Docker overlay 网络需要一个 key-value数据库用于保存网络状态信息, 包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件,我们这里使用 Consul

环境限制:

  • 必须安装key-value存储服务,如consul
  • 宿主机已经安装docker engine
  • 宿主机的hostname必须不同

前提准备:

关闭防火墙,关闭selinux

运行consul服务

选择任意一台节点安装consul节点,这里安装consul只用到的是key-value值的动态配置,功能标记的特性

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

PS: -server -bootstrap 单节点使用

容器生产之后,我们可以通过浏览器访问consul服务,验证consul服 务是否正常。访问dockerHost加映射端口

安装完成后浏览器访问,发现只有一台节点

mac Docker没有任何反应 docker macvlan不通_网络

修改其他的节点的配置文件,,使得每一台都通过本机的2376端口被转发到172.16.46.111:8500,consul收集存储并使用这些信息实现网络一致。

修改docker配置文件

[root@docker03 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://172.16.46.111:8500 --cluster-advertise=ens33:2376
[root@docker03 ~]# systemctl daemon-reload
[root@docker03 ~]# systemctl restart docker

加入其它的2个节点,配置文件添加以下即可😎

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://172.16.46.111:8500 --cluster-advertise=ens33:2376

[root@docker01 ~]# scp /usr/lib/systemd/system/docker.service root@172.16.46.112:/usr/lib/systemd/system/docker.service
The authenticity of host '172.16.46.112 (172.16.46.112)' can't be established.
ECDSA key fingerprint is 7c:a2:0a:5e:4b:a0:f7:3f:7b:e1:09:dc:6c:07:1a:07.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.16.46.112' (ECDSA) to the list of known hosts.
root@172.16.46.112's password: 
docker.service                                                                 100% 1716     1.7KB/s   00:00    
[root@docker01 ~]# 
[root@docker01 ~]# 
[root@docker01 ~]# scp /usr/lib/systemd/system/docker.service root@172.16.46.113:/usr/lib/systemd/system/docker.service
The authenticity of host '172.16.46.113 (172.16.46.113)' can't be established.
ECDSA key fingerprint is 27:2d:ca:ff:27:6d:02:9d:7e:c1:aa:25:90:a6:15:8b.
Are you sure you want to continue connecting (yes/no)? yes   
Warning: Permanently added '172.16.46.113' (ECDSA) to the list of known hosts.
root@172.16.46.113's password: 
docker.service                                                                 100% 1716     1.7KB/s   00:00    
[root@docker01 ~]# 
#修改完配置后重启docker
[root@docker02 ~]# systemctl daemon-reload
[root@docker02 ~]# systemctl restart docker
....
....

最后浏览网页界面,3台不同主机的docker已经添加到了一起

mac Docker没有任何反应 docker macvlan不通_网络_02

在任意一个节点创建一个网络

[root@docker03 ~]# docker network create -d overlay myovernet
e9d8d6890c4545c12956e78324b550cd77b699b51833521ba2c9ca94c36da39f
[root@docker03 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
5319a64fec1d        bridge              bridge              local
4f64be31d339        host                host                local
e9d8d6890c45        myovernet           overlay             global
73778fbffd07        none                null                local

这时候每一个节点都会有这个网卡,并且范围是global

查看这个网卡的信息

默认的网段是10.0.0.0/24;如果与主机冲突,我们是可以在创建网卡的时候自定义网段

mac Docker没有任何反应 docker macvlan不通_mac Docker没有任何反应_03


mac Docker没有任何反应 docker macvlan不通_linux_04

有了这个网卡以后,去建立容器这个时候跨主机的容器之间就可以ping;
docker基础网络的时候也知道,自定义的网卡是自带域名解析的,所以直接ping名字

[root@docker01 ~]# docker run -itd --name busybox01 --network ovnet busybox:latest
[root@docker02 ~]# docker run -itd --name busybox02 --network ovnet busybox:latest
[root@docker03 ~]# docker run -itd --name busybox03 --network ovnet busybox:latest

ping测试

[root@docker01 ~]# docker exec -it busybox01 ping busybox02
PING busybox02 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=0.916 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.535 ms
64 bytes from 10.0.0.3: seq=2 ttl=64 time=0.542 ms
64 bytes from 10.0.0.3: seq=3 ttl=64 time=0.490 ms
^C
--- busybox02 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.490/0.620/0.916 ms
[root@docker01 ~]# docker exec -it busybox01 ping busybox03
PING busybox03 (10.0.0.4): 56 data bytes
64 bytes from 10.0.0.4: seq=0 ttl=64 time=0.465 ms
64 bytes from 10.0.0.4: seq=1 ttl=64 time=1.027 ms
64 bytes from 10.0.0.4: seq=2 ttl=64 time=1.074 ms
^C
--- busybox03 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.465/0.855/1.074 ms

解决方案二:docker跨主机之二Macvlan

此方案仅作为参考,慎用!!!

macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配 置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。macvlan 本质上是一种网卡虚拟化技术

Macvlan工作原理:

  • Macvlan是Linux内核支持的网络接口。要求的Linux内部版本是v3.9–3.19和4.0+;
  • 通过为物理网卡创建Macvlan子接口,允许一块物理网卡拥有多个独立的MAC地址和IP地址。虚拟出来的子接口将直接暴露在相邻物理网络中。从外部看来,就像是把网线隔开多股,分别接受了不同的主机上一样;
  • 物理网卡收到包后,会根据收到包的目的MAC地址判断这个包需要交给其中虚拟网卡

使用Macvlan需要注意以下几点:

  • 容器直接连接物理网络,由物理网络负责分配IP地址,可能的结果是物理网络IP地址被耗尽,另一个后果是网络性能问题,物理网络中接入的主机变多,广播包占比快速升高而引起的网络性能下降问题;
  • 宿主机上的物理网卡(ens33)需要工作在 混乱模式 下;
  • 前面说到,工作在混乱模式下的物理网卡,其MAC地址会失效,所以,此模式中运行的容器并不能与外网进行通信,但是不会影响宿主机与外网通信;
  • 从长远来看bridge网络与overlay网络是更好的选择,原因就是虚拟网络应该与物理网络隔离而不是共享。

·

Macvlan本身不创建网络,本质上首先使宿主机物理网卡工作在‘混杂模式’,这样物理网卡的MAC地址将会失效,所有二层网络中的流量物理网卡都能收到。接下来就是在这张物理网卡上创建虚拟网卡,并为虚拟网卡指定MAC地址,实现一卡多用,在物理网络看来,每张虚拟网卡都是一个单独的接口 .

macvlan的单网络通信

前提准备:
 #关闭防火墙和selinux
 #重载daemon && 重启docker
 #docker01可以ping通docker02

mac Docker没有任何反应 docker macvlan不通_mac Docker没有任何反应_05

打开网卡的混杂模式
#开启混杂模式
ip link set ens33 promisc on
#查看ens33混杂网卡
ip link show ens33

开启路由转发

echo "net.ipv4.ip_forward = 1" > /etc/sysctl.conf 
 sysctl -p
docker01创建macvlan 网络
docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o parent=ens33 mac_net1

PS: -o parent=绑定在哪张网卡之上

基于macvlan运行一个容器
docker run -itd --name bbox1 --ip 172.22.16.10 --network mac_net1 busybox
docker02创建网络,与docker01一米一样
docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o parent=ens33 mac_net1
docker02运行一个容器
docker run -itd --name bbox2 --network mac_net1 --ip 172.22.16.20 busybox

验证单网络跨主机

[root@docker01 ~]# docker exec -it bbox1 ping 172.22.16.20
PING 172.22.16.20 (172.22.16.20): 56 data bytes
64 bytes from 172.22.16.20: seq=0 ttl=64 time=1.162 ms
64 bytes from 172.22.16.20: seq=1 ttl=64 time=1.171 ms
^C

此时,正如上面说的这样

只能单网络之间互相通信,不能和自己网关ping,不能和宿主机ping

但是不会影响和宿主机与外网互通

[root@docker01 ~]# ping baidu.com
PING baidu.com (39.156.69.79) 56(84) bytes of data.
64 bytes from 39.156.69.79 (39.156.69.79): icmp_seq=1 ttl=49 time=8.14 ms
64 bytes from 39.156.69.79 (39.156.69.79): icmp_seq=2 ttl=49 time=9.91 ms
^C

实现多网络跨主机之间的网络互通

mac Docker没有任何反应 docker macvlan不通_网络_06

这个时候,需要使用到macvlan来虚拟出来的虚拟网卡

来保证只能多网络相同的网络才可以通信

macvlan需要解决的问题:基于真实的ens33网卡,生产新的虚拟网卡。

~]# modinfo 8021q

//如果内核模块没有开启,运行下边的命令导入一下

~]# modprobe 8021q

基于ens33创建虚拟网卡

修改物理网卡ens33配置文件

PS:BOOTPROTO指定的类型都无所谓,只要的一个固定的ip就可以,可以有static,可以是manual,还可以是none,但是注意ip不要冲突

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nXfZaKRG-1628215985402)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1596249935220.png)]

docker02修改ens33物理网卡

mac Docker没有任何反应 docker macvlan不通_linux_07

基于ens33创建虚拟网卡
cd /etc/sysconfig/network-scripts/
ls
vim ifcfg-ens33 
cp ifcfg-ens33 ifcfg-ens33.10
vi ifcfg-ens33.10 
cp ifcfg-ens33.10 ifcfg-ens33.20
vim ifcfg-ens33.20
systemctl restart networkork

mac Docker没有任何反应 docker macvlan不通_网络_08

mac Docker没有任何反应 docker macvlan不通_mac Docker没有任何反应_09

docker02也要去创建虚拟网卡

mac Docker没有任何反应 docker macvlan不通_网络_10

mac Docker没有任何反应 docker macvlan不通_docker_11

启动ens33.10和ens33.20

ifup ifcfg-ens33.10
ifup ifcfg-ens33.20
[root@docker02 network-scripts]# ip a | grep ens33
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 192.168.2.112/24 brd 192.168.2.255 scope global ens33
9: ens33.10@ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    inet 192.168.12.10/24 brd 192.168.12.255 scope global ens33.10
10: ens33.20@ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    inet 192.168.22.10/24 brd 192.168.22.255 scope global ens33.20
基于虚拟网卡创建macvlan网络

同单网络跨主机,docker01和docker02都创建macvlan网络

[root@docker02 ~]# docker network create -d macvlan  --subnet 172.12.26.0/24 --gateway 172.12.26.1 -o parent=ens33.10 mac_net01
8440437a4a804df1ab878de725835015d4a966442e04138763b7458ff422ca7c
[root@docker02 ~]# 
[root@docker02 ~]# docker network create -d macvlan  --subnet 172.12.36.0/24 --gateway 172.12.36.1 -o parent=ens33.20 mac_net02
58458c1c899da4e291b80f46bc6d07deaee836ce9db1b6617bc5e4b1f017d898
[root@docker02 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
50bdd8e3aa78        bridge              bridge              local
a62f15abc7cf        host                host                local
66b73948aa9b        mac_net             macvlan             local
8440437a4a80        mac_net01           macvlan             local
58458c1c899d        mac_net02           macvlan             local
ae356e9ff53e        none                null                local
基于macvlan网络创建容器

docker01创建容器

[root@docker01 ~]# docker run -itd --name dc01 --network mac_net01 --ip 172.12.26.10 busybox
bcbf22d5a9e44882d02452100b92e966cf1df48a9a1febdc5a5f0338c4f57af0
[root@docker01 ~]# 
[root@docker01 ~]# 
[root@docker01 ~]# docker run -itd --name dc02 --network mac_net02 --ip 172.12.36.10 busybox
65c5da8b4a500821c4bcdca4d75555d9a2df1ad6983f229a783b633a88758a3c

docker02创建容器

[root@docker02 ~]# docker run -itd --name t1 --network mac_net01 --ip 172.12.26.11 busybox
f34cb4857f746ddd40f67a3b93610253c566257fdbd8d2ea8558f5bb9a872320
[root@docker02 ~]# docker run -itd --name t2 --network mac_net02 --ip 172.12.36.11 busybox
822187b2231eae576dd7e20d90962f56d9508e82755002d001bd09c7d8f36302

容器互通验证

[root@docker01 ~]# docker exec -it dc01 ping 172.12.26.11
PING 172.12.26.11 (172.12.26.11): 56 data bytes
64 bytes from 172.12.26.11: seq=0 ttl=64 time=1.050 ms
64 bytes from 172.12.26.11: seq=1 ttl=64 time=0.196 ms
^C
--- 172.12.26.11 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.196/0.623/1.050 ms
[root@docker01 ~]# docker exec -it dc02 ping 172.12.36.11
PING 172.12.36.11 (172.12.36.11): 56 data bytes
64 bytes from 172.12.36.11: seq=0 ttl=64 time=0.940 ms
64 bytes from 172.12.36.11: seq=1 ttl=64 time=1.155 ms
^C

因为我们知道macvlan网络是ping不通宿主机的;但是不影响宿主机与外网ping通

mac Docker没有任何反应 docker macvlan不通_IP_12

PS:因为我这里是使用桥接的方式做的,所以在ping t2的时候直接就会ping通,如果你使用的VMware虚拟机摒并且网络使用的Nat8网络,需要改成桥接才可以ping通,再起修改一个静态的桥接ip地址,就可以ping外网了。

mac Docker没有任何反应 docker macvlan不通_linux_13