Docker网络管理之docker跨主机通信
博文大纲:
一、前言
二、Docker的原生网络
三、自定义bridge网络
四、Overlay网络
五、Macvlan网络
六、使外网可以访问容器的方法创新互联建站专注于企业成都营销网站建设、网站重做改版、阜新网站定制设计、自适应品牌网站建设、html5、商城网站建设、集团公司官网建设、外贸网站制作、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为阜新等各大城市提供网站开发制作服务。
一、前言
由于docker技术的火爆,导致现在越来越多的企业都在使用docker这种虚拟化技术。企业中使用docker这种虚拟化技术,其目的就是为了让docker中的容器对外提供服务。因此,我们必须深入了解一下docker的网络知识,以满足更高的网络需求。
二、Docker的原生网络
当你安装Docker时,它会自动创建三个网络。如下:
[root@localhost ~]# docker network ls
//查看docker的默认网络
NETWORK ID NAME DRIVER SCOPE
a38bd52b4cec bridge bridge local
624b3ba70637 host host local
62f80646f707 none null local
Docker内置这三个网络,运行容器时,你可以使用该“--network”选项来指定容器应连接到哪些网络。如果没有指定则默认使用bridge模式。
比如:
host模式:使用 --net=host 指定;
none模式:使用 --net=none 指定;
bridge模式:使用 --net=bridge 指定(默认设置);
下面详细介绍一下这几种网络模式:
虽然docker模式提供三种网络模式,但其实是有四种网络模式的!
1.host模式
如果启动容器时使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
使用场景:
由于网络配置与docker宿主机完全一样,性能较好,但是不便之处就是灵活性不高,容易和宿主机出现端口冲突的问题。最好是单个容器时使用,一般情况下不建议使用。
创建使用host网络模式的容器示例:
[root@localhost ~]# docker run -it --name host --network host busybox:latest
//使用busybox镜像创建一个名为host的容器,网络采用host模式
/ # ip a
//进入容器后可以看出容器中的网络与docker主机的网络一模一样
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:66:72:13 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.1/24 brd 192.168.1.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::9f3:b94e:5f5d:8070/64 scope link
valid_lft forever preferred_lft forever
3: virbr0: mtu 1500 qdisc noqueue qlen 1000
link/ether 52:54:00:e1:82:15 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: mtu 1500 qdisc pfifo_fast master virbr0 qlen 1000
link/ether 52:54:00:e1:82:15 brd ff:ff:ff:ff:ff:ff
5: docker0: mtu 1500 qdisc noqueue
link/ether 02:42:3c:06:f8:1d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
2.none模式
在none模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器只有一个回环地址,不能与外界通信,称为被隔离的网络。
使用场景:
none模式被称为隔离的网络,隔离便意味着安全,不能与外部通信,同样外部也不可以访问到使用none模式的容器,使用这种网络模式的容器可以运行于关于安全方面的验证码、校验码等服务。一般用于对安全性要求较高的场景中!
创建使用none网络模式的容器示例:
[root@localhost ~]# docker run -it --name none --network none busybox:latest
//使用busybox镜像创建一个名为none的容器,网络采用none模式
/ # ip a //可以看到容器中只有一个lo网卡
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3.bridge模式
bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网卡上。当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。如一般Docker会使用172.17.0.0/16这个网段,并将172.17.0.1/16分配给docker0网桥。
[root@localhost ~]# ifconfig docker0
docker0: flags=4099 mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:3c:06:f8:1d txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@localhost ~]# brctl show //查看桥接网络
bridge name bridge id STP enabled interfaces
docker0 8000.02423c06f81d no
//如果没有创建桥接模式的容器,默认是空的。
创建使用bridge网络模式的容器示例:
[root@localhost ~]# docker run -itd --name bridge busybox:latest /bin/sh
//创建一个名为bridge的容器,如果没有指定网络模式,默认便是bridge模式
[root@localhost ~]# docker exec -it bridge /bin/sh
//进入bridge容器中
/ # ip a
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if9: mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
//可以看出eth0@if9这块虚拟网卡上的地址与docker宿主机的docker0网络属于同一网段
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02423c06f81d no veth811d20c
//可以看到桥接模式的接口下出现了一个新的接口,当创建一个容器便会出现一个接口
//这个接口便是容器在docker宿主机创建一个虚拟网卡,用于容器与docker通信
[root@localhost ~]# ifconfig veth811d20c //查看这个虚拟网卡是否存在
veth811d20c: flags=4163 mtu 1500
inet6 fe80::c035:95ff:febf:978b prefixlen 64 scopeid 0x20
ether c2:35:95:bf:97:8b txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
当使用bridge网络模式,docker的工作步骤大致为:
(1)在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备;
(2)Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth811d20c这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看(上述实例已经验证);
(3)从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关;
4.container(共享网络协议栈)模式
这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
创建使用container网络模式的容器示例:
[root@localhost ~]# docker run -it --name container --network container:a172b832b531 busybox:latest
//a172b832b531是bridge容器的ID号
/ # ip a
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
8: eth0@if9: mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
//可以看出container容器的IP地址与bridge容器的IP地址一模一样
关于这四种网络模式推荐使用默认的bridge网络模式!
三、自定义bridge网络
细心一点可以发现,创建的容器默认情况IP地址为172.17.0.0/16网段,那么我们可不可以自定义一个网段供容器使用呢?答案肯定是可以的,方法如下:
[root@localhost ~]# docker network create -d bridge my_net
//创建一个桥接网络,名称为my_net,如果没有指定网段,默认是172.18.0.0/16,按docker0的网段自动递增
[root@localhost ~]# docker network ls //查看docker支持的网络类型
NETWORK ID NAME DRIVER SCOPE
9fba9dc3d2b6 bridge bridge local
624b3ba70637 host host local
74544573aa67 my_net bridge local
62f80646f707 none null local
//可以看出,刚才创建的my_net已经出现在列表中
[root@localhost ~]# docker run -itd --name test1 --network my_net busybox:latest /bin/sh
[root@localhost ~]# docker run -itd --name test2 --network my_net busybox:latest /bin/sh
//使用刚才创建的网络模式创建两个容器
[root@localhost ~]# docker exec -it test1 /bin/sh
//进入test1
/ # ip a
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
11: eth0@if12: mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
//查看其IP地址,发现确实是172.18.0.0/16网段的
/ # ping test2 //测试通过容器名称ping test2容器
PING test2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.079 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.175 ms
[root@localhost ~]# ifconfig br-74544573aa67
//这张虚拟网卡就是我们创建my_net网络时产生的
br-74544573aa67: flags=4163 mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
inet6 fe80::42:50ff:fec2:7657 prefixlen 64 scopeid 0x20
ether 02:42:50:c2:76:57 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
//通过IP地址网段就可看出
自定义网络的优点:
- 可以通过容器的名称进行通信;
- 自定了ContainerDNSserver功能;
以上方法按照默认的方式创建一个桥接模式的网络,可以发现网段地址并不是我们自定义的。
接下来我们通过指定具体网段的方式创建网卡。方法如下:
[root@localhost ~]# docker network create -d bridge --subnet 200.0.0.0/24 --gateway 200.0.0.1 my_net2
//自定义网络模式的地址时,必须要明确指定其IP网段及网关信息
[root@localhost ~]# ifconfig br-0ca6770b4a10
//这张虚拟网卡便是我们创建my_net2网络时产生的
br-0ca6770b4a10: flags=4099 mtu 1500
inet 200.0.0.1 netmask 255.255.255.0 broadcast 200.0.0.255
ether 02:42:05:ba:8b:fc txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
//可以看出其IP地址就是我们指定的IP地址
[root@localhost ~]# docker run -itd --name test3 --network my_net2 --ip 200.0.0.100 busybox:latest
[root@localhost ~]# docker run -itd --name test4 --network my_net2 --ip 200.0.0.200 busybox:latest
//基于刚才创建的网络创建出两个容器并指定其固定的IP地址
[root@localhost ~]# docker exec -it test3 /bin/sh
//进入test3容器
/ # ip a
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
16: eth0@if17: mtu 1500 qdisc noqueue
link/ether 02:42:c8:00:00:64 brd ff:ff:ff:ff:ff:ff
inet 200.0.0.100/24 brd 200.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
//发现其IP地址确实我们刚才指定的IP地址
/ # ping test4 //测试发现确实是可以和test4通信的
PING test4 (200.0.0.200): 56 data bytes
64 bytes from 200.0.0.200: seq=0 ttl=64 time=0.156 ms
64 bytes from 200.0.0.200: seq=1 ttl=64 time=0.178 ms
/ # ping test1
ping: bad address 'test1'
//发现无法与第一次创建的网络进行通信
使用相同的网络创建的容器是可以相互通信的,但是发现无法与其他容器进行通信,这主要是因为iptables规则的原因,创建docker网络时,iptables规则就会随着自动添加的。
举例说:尝试把iptables规则清空,是可以实现我们想要的效果的。但是这种命令的作用不亚于“rm -rf /*”,显然在现实环境中是不可以使用的!
那么就需要使用下面的方法来实现了,方法如下:
[root@localhost ~]# docker network connect my_net2 test1
//这条命令就是在test1容器中添加一块虚拟网卡(my_net2分配的)
[root@localhost ~]# docker exec -it test1 /bin/sh
/ # ip a
1: lo: mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
11: eth0@if12: mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
20: eth2@if21: mtu 1500 qdisc noqueue
link/ether 02:42:c8:00:00:02 brd ff:ff:ff:ff:ff:ff
inet 200.0.0.2/24 brd 200.0.0.255 scope global eth2
valid_lft forever preferred_lft forever
//可以查询到确实多了一块虚拟网卡,网段确实和my_net2属于同一网段
/ # ping test3
PING test3 (200.0.0.100): 56 data bytes
64 bytes from 200.0.0.100: seq=0 ttl=64 time=0.171 ms
64 bytes from 200.0.0.100: seq=1 ttl=64 time=0.237 ms
^C
--- test3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.171/0.204/0.237 ms
/ # ping test4
PING test4 (200.0.0.200): 56 data bytes
64 bytes from 200.0.0.200: seq=0 ttl=64 time=0.097 ms
^C
--- test4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.097/0.097 ms
//测试与test3、test4通信,通信正常
注意:此时test2容器并不可以与test3、test4进行通信!如果需要其通信,还需给test2添加虚拟my_net2网卡地址(使用案例中的命令即可)!
注意:
- 容器之间可以使用容器名进行通信,但前提必须是使用自定义网络,比如案例中创建的my_net、my_net2;
- 如果在创建自定义网络时,指定了该网络的网段,那么使用此时的容器也可以指定容器的IP地址,若没有指定该网络的网段,则不可指定容器的IP地址;
四、Overlay网络
使用overlay网络需事先部署好consul服务!
consul:是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
通过一个小案例来验证consul服务的特性!
1.案例环境
2.准备工作
(1)关闭防火墙与SELinux(实验环境);
(2)更改主机名,避免发生冲突;
3.案例实施
(1)Docker1
[root@Docker1 ~]# docker pull progrium/consul
//下载consul镜像
[root@Docker1 ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap
//-d:后台运行;
//-p:将容器中的8500端口映射到宿主机的8500端口;
//-h:表示consul容器的主机名;
//--name:表示运行的容器名;
//--restart=always:随docker服务的启动而启动;
//-server -bootstrap:添加这两个选项,则表示在群集环境中可以使其以master的身份出现;
[root@Docker1 ~]# netstat -anpt | grep 8500
tcp6 0 0 :::8500 :::* LISTEN 2442/docker-proxy
//确定其8500端口正在监听
(2)Docker2
[root@Docker2 ~]# vim /usr/lib/systemd/system/docker.service
//编写Docker的主配置文件
13 ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.1.1:8500 --cluster-advertise=ens33:2376
//在第13行上原本的基础添加以上内容,各个配置项含义如下:
# /var/run/docker.sock:Docker的一个套接字;
# “ -H tcp://0.0.0.0:2376 ” :使用本机的tcp2376端口;
# “ --cluster-store=consul://192.168.1.1:8500”:指定运行着consul服务的docker服务器IP及端口;
# “ --cluster-advertise=ens33:2376”:从本机的ens33网卡通过2376端口搜集网络信息,存储在consul上
[root@Docker2 ~]# systemctl daemon-reload
[root@Docker2 ~]# systemctl restart docker //重新启动docker服务
(3)Docker3
Docker3与Docker2的操作就是一模一样的,所以这里就不多做解释了!
[root@Docker3 ~]# vim /usr/lib/systemd/system/docker.service
13 ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.1.1:8500 --cluster-advertise=ens33:2376
[root@Docker3 ~]# systemctl daemon-reload
[root@Docker3 ~]# systemctl restart docker
(4)使用浏览器访问consul服务的web页面
如图:
(5)将Docker1服务器也加入到consul群集
[root@Docker1 ~]# vim /usr/lib/systemd/system/docker.service
13 ExecStart=/usr/bin/dockerd -H unix:////var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.1.1:8500 --cluster-advertise=ens33:2376
[root@Docker1 ~]# systemctl daemon-reload
[root@Docker1 ~]# systemctl restart docker
//解释上面都已经解释的很清楚,这里就不做解释了
再次访问consul的web页面,如图:
如果在此过程中,访问web页面如果出现“500”的错误页面,将运行consul服务的容器删除重新创新即可!
(6)创建一个 overlay网络
[root@Docker1 ~]# docker network create -d overlay my_olay
//创建一个名为my_olay的voerlay网络
//以上操作不管在那台docker主机上操作都可以
[root@Docker1 ~]# docker network create -d overlay --subnet 200.0.0.0/24 --gateway 200.0.0.1 lv_olay
//也可以在创建overlay网卡时,指定其IP网段及网关
[root@Docker1 ~]# docker network ls //查看docker所支持的网络
而且在另外两台docker服务器上也可看到,自行验证!
在docker 1上创建的网络,可以看到其SPOCE(范围)定义的是global(全局),那么这就意味着加入consul这个服务群集的其他docker服务器也可以看到这张网卡!
如果在创建网卡时,没有指定其网段,则默认是10.0.0.0网段,由于是自定义网络,所以满足自定义网络的特征(比如支持容器之间的通信)!
(7)在不同的docker服务器各自创建一个容器,验证是否可以通信!
[root@Docker1 ~]# docker run -itd --name t1 --network lv_olay --ip 200.0.0.10 busybox:latest
//在docker1服务器上创建一个名为t1的容器并指定其IP地址
[root@Docker2 ~]# docker run -itd --name t2 --network lv_olay --ip 200.0.0.20 busybox:latest
//在docker2上创建一个容器并指定IP地址
[root@Docker3 ~]# docker run -itd --name t3 --network lv_olay --ip 200.0.0.30 busybox:latest
//在docker3上创建一个容器并指定IP地址
[root@Docker1 ~]# docker exec -it t1 /bin/sh
//随便在一台docker服务器上进入其创建的容器中,进行测试
如图:
五、Macvlan网络
Macvlan是linux kernel比较新的特性,可以通过以下方法判断当前系统是否支持:
[root@localhost ~]# modprobe macvlan
[root@localhost ~]# lsmod | grep macvlan
macvlan 19239 0
如果是第一个命令报错,或者第二个命令没有返回信息,则说明当前系统不支持macvlan,需要升级内核。
[root@docker01 ~]# modprobe 8021q //加载内核模块
[root@docker01 ~]# modinfo 8021q //如果有信息返回则表示开启8021q模块,如果没有使用上条命令
这两组命令所支持的效果一样!
以上命令主要验证Linux内核是否支持macvlan功能!
macvlan允许在主机的一个网络接口上配置多个虚拟的网络接口,这些网络接口有自己独立的mac地址,也可以配置IP地址进行通信。macvlan下的虚拟机或者容器网络和主机在同一网段中,共享一个广播域。macvlan和bridge比较相似,但因为它省去了bridge的存在,所以在配置和调试时比较简单,而且效率较高。除此之外,macvlan自身也完美支持VLAN。
如果希望容器或者虚拟机放在主机相同的网络中,享受已经存在网络栈的各种优势,可以考虑macvlan。
macvlan和overlay网络不同,overlay的作用范围是global;而macvlan的作用范围是local。global类型的网络其作用于一组docker daemon集群,local类型的网络只作用于单一主机。
每台主机创建的macvlan网络是独立的,A机器行创建的macvlan网络并不影响B机器上的网络。
两台主机在网卡配置混杂模式、两台主机上macvlan存在overlap、两个macvlan网络没有分配过同样的IP,以上三个条件满足后,同样可以实现跨主机通信!
1.环境准备
如图:
2.准备工作
(1)关闭Linux防火墙和SELinux;
(2)修改主机名;
3.案例实施
关于macvlan单网络通信这里就不介绍了,直接介绍macvlan多网络通信!方法如下:
(1)开启网卡混杂模式
[root@dockerA ~]# ip link set ens33 promisc on //开启网卡的混杂模式
[root@dockerA ~]# ip link show ens33 //查询网卡已经支持PROMISC
2: ens33: mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:66:72:13 brd ff:ff:ff:ff:ff:ff
[root@dockerA ~]# modprobe 8021q /加载8021q内核模块
[root@dockerA ~]# modinfo 8021q //有返回信息则表示支持8021q内核模块
(2)创建虚拟网卡
由于一个网卡最好创建出一个macvlan网卡,所以需创建虚拟网卡以满足要求!
[root@dockerA ~]# cd /etc/sysconfig/network-scripts/
[root@dockerA network-scripts]# sed -i 's/static/manual/g' ifcfg-ens33
[root@dockerA network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.10
[root@dockerA network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.20
[root@dockerA network-scripts]# vim ifcfg-ens33.10
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.1
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
VLAN=yes
//保证和原本的物理网卡不在同一网段,并且打开vlan的支持模式
[root@dockerA network-scripts]# vim ifcfg-ens33.20
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.1
NETMASK=255.255.255.0
GATEWAY=192.168.20.254
VLAN=yes
[root@dockerA network-scripts]# ifup ifcfg-ens33.10
[root@dockerA network-scripts]# ifup ifcfg-ens33.20
[root@dockerA network-scripts]# ifconfig ens33.10
ens33.10: flags=4163 mtu 1500
inet 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::20c:29ff:fe66:7213 prefixlen 64 scopeid 0x20
ether 00:0c:29:66:72:13 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29 bytes 4052 (3.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@dockerA network-scripts]# ifconfig ens33.20
ens33.20: flags=4163 mtu 1500
inet 192.168.20.1 netmask 255.255.255.0 broadcast 192.168.20.255
inet6 fe80::20c:29ff:fe66:7213 prefixlen 64 scopeid 0x20
ether 00:0c:29:66:72:13 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 28 bytes 3987 (3.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
//确保虚拟网卡已经生效
dockerB主机上的操作与dockerA主机上的操作一致(注意IP不一样)!要保证两台docker主机的虚拟网卡可以通信!
[root@dockerB network-scripts]# ifconfig ens33.10
ens33.10: flags=4163 mtu 1500
inet 192.168.10.2 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::20c:29ff:feb7:1bbd prefixlen 64 scopeid 0x20
ether 00:0c:29:b7:1b:bd txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29 bytes 4100 (4.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@dockerB network-scripts]# ifconfig ens33.20
ens33.20: flags=4163 mtu 1500
inet 192.168.20.2 netmask 255.255.255.0 broadcast 192.168.20.255
inet6 fe80::20c:29ff:feb7:1bbd prefixlen 64 scopeid 0x20
ether 00:0c:29:b7:1b:bd txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29 bytes 4100 (4.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
(3)创建macvlan网卡
[root@dockerA ~]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33.10 mac_net10
[root@dockerA ~]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1 -o parent=ens33.20 mac_net20
//创建虚拟网卡并针对其网段、网关
//-d:指令网卡驱动类型,-o parent:绑定在那张网卡上
[root@dockerA ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
0a74599fef51 bridge bridge local
624b3ba70637 host host local
cb81dde7685d mac_net10 macvlan local
983927dbcae8 mac_net20 macvlan local
62f80646f707 none null local
dockerB主机上的创建虚拟网卡时,命令一模一样,指定的网段、名称必须一样,因为要保证其通过虚拟网卡可以通信!
[root@dockerB ~]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33.10 mac_net10
[root@dockerB ~]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1 -o parent=ens33.20 mac_net20
(4)基于创建的macvlan网卡创建容器,验证是否可以通信!
dockerA主机创建容器:
[root@dockerA ~]# docker run -itd --name box10 --network mac_net10 --ip 172.16.10.10 busybox
[root@dockerA ~]# docker run -itd --name box20 --network mac_net20 --ip 172.16.20.10 busybox
dockerB主机创建容器:
[root@dockerB ~]# docker run -itd --name box11 --network mac_net10 --ip 172.16.10.20 busybox
[root@dockerB ~]# docker run -itd --name box21 --network mac_net20 --ip 172.16.20.20 busybox
进入容器进行验证:
[root@dockerA ~]# docker exec -it box10 /bin/sh
/ # ping 172.16.10.20
PING 172.16.10.20 (172.16.10.20): 56 data bytes
64 bytes from 172.16.10.20: seq=0 ttl=64 time=0.653 ms
64 bytes from 172.16.10.20: seq=1 ttl=64 time=0.966 ms
[root@dockerA ~]# docker exec -it box20 /bin/sh/ # ping 172.16.20.20
PING 172.16.20.20 (172.16.20.20): 56 data bytes
64 bytes from 172.16.20.20: seq=0 ttl=64 time=0.734 ms
64 bytes from 172.16.20.20: seq=1 ttl=64 time=0.718 ms
注意:实验环境验证时,应使用虚拟机桥接模式;并且,测试时,只能ping通另一条docker host容器的ip,因为创建的虚拟macvlan的范围是local!
六、使外网可以访问容器的方法
(1)手动指定映射端口
[root@localhost ~]# docker run -itd --name web1 -p 90:80 nginx
//将一个容器的nginx服务映射到宿主机的90端口
(2)随机映射端口
[root@localhost ~]# docker run -itd --name web2 -p 80 nginx
//如果-p之后只有一个端口,则是容器中的端口(宿主机会随机映射一个端口)从32768端口开始
(3)将容器中的端口全部映射到宿主机上
[root@localhost ~]# docker run -itd --name web4 -P nginx
//注意:大写的P
//从宿主机随机映射端口到容器,容器内所有暴露的端口,都会一一映射
以上操作,个人验证没有问题,这里就不截图示范了!
—————————本文到此结束,感谢观看—————————
新闻标题:Docker网络管理之docker跨主机通信
网址分享:http://pwwzsj.com/article/ipcige.html