docker的跨主机网络
前言
这篇文件分两种方式介绍docker跨主机通信,overlay和macvlan,macvlan的方式给大家做个参考,生产环境下不推荐大家使用这种方式 🐴 。。。。
解决方案一:overlay的解决方案
默认的自定义网络的类型就是bridge
,但是无法在单宿主机网络里面的可以通过docker network connect
的命令互通;但是跨主机的时候bridge就明显不可用的;可以使用overlay
和macvlan
实现
为支持容器跨主机通信,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加映射端口
安装完成后浏览器访问,发现只有一台节点
修改其他的节点的配置文件,,使得每一台都通过本机的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已经添加到了一起
在任意一个节点创建一个网络
[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
;如果与主机冲突,我们是可以在创建网卡的时候自定义网段
有了这个网卡以后,去建立容器这个时候跨主机的容器之间就可以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
打开网卡的混杂模式
#开启混杂模式
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
实现多网络跨主机之间的网络互通
这个时候,需要使用到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物理网卡
基于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
docker02也要去创建虚拟网卡
启动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通
PS:因为我这里是使用桥接的方式做的,所以在ping t2的时候直接就会ping通,如果你使用的VMware虚拟机摒并且网络使用的Nat8网络,需要改成桥接才可以ping通,再起修改一个静态的桥接ip地址,就可以ping外网了。