Docker网络管理及容器互联实战指南

Docker网络管理及容器互联指南,涵盖bridge、host、overlay、macvlan、none五种模式及跨主机通信配置。

原文标题:Docker网络管理及容器互联

原文作者:牧羊人的方向

冷月清谈:

本文详细介绍了Docker的五种网络模式:bridge、host、overlay、macvlan和none,并通过实际案例演示了如何配置和使用这些模式,以及如何实现同一主机和跨主机容器间的通信。

bridge模式是Docker默认的网络模式,为每个容器分配独立的网络命名空间和IP,并通过docker0虚拟网桥连接到主机网络。host模式则让容器与主机共享网络命名空间,直接使用主机的IP和端口。overlay模式用于跨主机的容器通信,通过虚拟网络将多个Docker主机连接在一起。macvlan模式为容器分配MAC地址,使其像物理设备一样出现在网络中。none模式下容器只有回环网络,需要手动配置网络。

文章通过具体的操作步骤和命令演示了如何创建和配置不同网络模式的容器,并测试了容器间的连通性。例如,在overlay模式下,文章演示了如何使用consul服务发现实现跨主机容器通信;在macvlan模式下,文章演示了如何配置网卡的混杂模式以及如何为容器分配IP地址。

此外,文章还介绍了如何连接同一主机内的多个容器,以及如何实现跨主机的容器通信。对于同一主机内的容器通信,文章演示了如何创建新的Docker网络并将多个容器连接到该网络中。对于跨主机的容器通信,文章提到了可以使用overlay和macvlan模式来实现。

怜星夜思:

1、文章提到了macvlan模式的性能优异,那在实际生产环境中,相比其他模式,它有哪些具体的性能优势,又有哪些局限性呢?
2、overlay网络的实现依赖于服务发现,文章中使用了consul,那除了consul之外,还有哪些常用的服务发现工具可以用于Docker overlay网络?它们各自有什么特点?
3、文章中提到的五种网络模式,在实际应用中该如何选择?有没有一些通用的选择策略或建议?

原文内容

Docker网络有bridge、host、overlay、macvlan和none五种模式,本文对这几种网络模式进行验证并测试容器间的互联通信。

1、Docker网络管理

Docker有5种网络模式,在创建容器的时候指--net参数设定网络模式:

  • bridge桥接模式:默认模式,通常用于独立部署的容器之间的通信

  • host主机模式:对于独立部署容器,移除容器和Docker主机间的网络隔离,直接使用主机的网络

  • overlay模式:将多个Docker守护进程连接在一起,并使集群之间能够相互通信,也可以用于集群环境和独立部署容器之间的通信或者两个独立容器之间不同守护进程之间的通信

  • macvlan模式:为容器分配MAC地址,在网络上显示物理设备。Docker守护进程通过MAC地址将流量路由到容器中

  • none模式:Docker容器不会设置网络环境,容器内部只能使用loopback网络设备

在安装完docker以后,宿主机上会创建三个网络,分别是bridge网络,host网络,none网络,可以使用docker network ls命令查看:

[root@tango-01 ~]# docker network ls
NETWORK
ID NAME DRIVER SCOPE
beae4c09945e bridge bridge local
7bbafde1931d host host local
56440e57a748 none null local
1.1 Bridge桥接模式

Bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。

  1. 当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。

  2. 为容器分配IP,Docker会选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的 IP 使用。如一般Docker会使用 172.17.0.0/16这个网段,并将 172.17.42.1/16分配给 docker0 网桥

Bridge桥接模式的实现原理主要如下:

  1. Docker Daemon利用veth pair技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0和veth1。Veth pair技术的特性可以保证无论哪一个veth接收到网络报文,都会将报文传输给另一方

  2. Docker Daemon将veth0附加到Docker Daemon创建的docker0网桥上,保证宿主机的网络报文可以发往veth0

  3. Docker Daemon将veth1添加到Docker Container所属的namespace下,并被改名为eth0

如此一来,保证宿主机的网络报文如果发往veth0,则立即会被eth0接收,实现宿主机到Docker Container网络的联通性;同时保证Docker Container单独使用eth0,实现容器网络环境的隔离性。

1)列出当前主机网桥

[root@tango-01 ~]# brctl show
bridge
name bridge id STP enabled interfaces
docker0 8000.0242857c0ccd no
virbr0 8000.52540010a078 yes virbr0-nic

2)查看当前 docker0 ip

[root@tango-01 ~]# ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:85:7c:0c:cd 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

在容器运行时,每个容器都会分配一个特定的虚拟机口并桥接到docker0。每个容器都会配置同docker0 ip相同网段的专用ip地址,docker0的IP地址被用于所有容器的默认网关。

3)运行一个容器

[root@tango-01 ~]# docker run -it -d ubuntu:latest /bin/bash
ba6fc34e3c5404410fab232890a8f259408f87adca417ed4a5200fb144c5bea0
[root@tango-01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba6fc34e3c54 ubuntu:latest "/bin/bash" 14 seconds ago Up 12 seconds keen_euclid
[root@tango-01 ~]# brctl show
bridge
name bridge id STP enabled interfaces
docker0 8000.0242857c0ccd no veth9292ea4
virbr0 8000.52540010a078 yes virbr0-nic

以上, docker0扮演着ba6fc34e3c54这个容器的虚拟接口veth9292ea4 interface桥接的角色

1.2 Host主机模式

如果使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。Host方式由于无需额外进行NAT转换,效率上会有提升,但是Docker容器网络环境的隔离会被弱化。

1)创建一个容器指定net为host

[root@tango-01 ~]# docker run --rm -d --network host --name my_nginx nginx:latest
73c935d570b0d42997845351bcff0a5834b9316df5f7386f09c68d2ab2ae87f6
[root@tango-01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73c935d570b0 nginx:latest "/docker-entrypoint." 23 seconds ago Up 22 seconds my_nginx

2)检查network interface

[root@tango-01 ~]# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:6c:5d:b1 brd ff:ff:ff:ff:ff:ff
inet 192.168.112.10/24 brd 192.168.112.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::db02:8b2d:162f:fae8/64 scope link
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
link/ether 52:54:00:10:a0:78 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: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
link/ether 52:54:00:10:a0:78 brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:85:7c:0c:cd 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
inet6 fe80::42:85ff:fe7c:ccd/64 scope link
valid_lft forever preferred_lft forever
1.3 Overlay模式

Overlay网络模式是在多个Docker主机中实现分布式网络,这种网络是在主机网络之上,允许跨容器之间的交互。Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。这样不但能够充分利用成熟的IP路由协议进程数据分发;而且在Overlay技术中采用扩展的隔离标识位数,能够突破VLAN的4000数量限制支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案。

如图所示,容器使用overlay network实现两个跨主机通信的时候,overlay虚拟出一个网络veth1如ip地址为172.17.0.101。在overlay网络模式里面,有一个类似于服务网关的地址,然后把这个包转发到物理服务器eth33这个地址,最终通过路由和交换,到达另一个服务器的ip地址。

案例:Overlay网络实现跨主机通信

要实现overlay网络,需要有一个服务发现,比如consul。如下图所示,Consul会定义一个ip地址池,比如10.0.2.0/24,容器的ip地址会从中获取。获取IP以后,容器会通过ens33来进行通信,这样就实现跨主机的通信。

1)环境准备

Hostname 系统 IP
tango-centos01 Centos_x86_64 192.168.112.101
tango-centos02 Centos_x86_64 192.168.112.102

2)系统配置

[root@tango-centos01 ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@tango-centos02 ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@tango-centos01 ~]# docker -v
Docker version 19.03.13, build 4484c46d9d
[root@tango-centos02 ~]# docker -v
Docker version 19.03.13, build 4484c46d9d

3)修改docker配置并重启

在docker daemon的配置文件/lib/systemd/system/docker.service添加cluster-store和cluster-advertise:cluster-store为consul 的地址、cluster-advertise为consul自己连接的地址

[root@tango-centos01 ~]# vi /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --cluster-store=consul://192.168.112.101:8500 --cluster-advertise=ens33:2376 --insecure-registry=0.0.0.0/0

[root@tango-centos01 ~]# vi /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --cluster-store=consul://192.168.112.101:8500 --cluster-advertise=ens33:2376 --insecure-registry=0.0.0.0/0

修改完后,需要重启docker

[root@tango-centos01 ~]# systemctl daemon-reload
[root@tango-centos01 ~]# systemctl restart docker
[root@tango-centos01 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2020-10-14 09:22:23 CST; 32s ago
Docs: https://docs.docker.com
Main PID: 1533 (dockerd)
Memory: 37.7M
CGroup: /system.slice/docker.service
└─1533 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --cluster-store=consul://192.168.112.101:8500 --cluster-advertise=ens33:2376 --insecure-registry=0.0.0.0/0

[root@tango-centos02 ~]# systemctl daemon-reload
[root@tango-centos02 ~]# systemctl restart docker
[root@tango-centos02 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2020-10-14 09:24:01 CST; 5s ago
Docs: https://docs.docker.com
Main PID: 1332 (dockerd)
Memory: 43.3M
CGroup: /system.slice/docker.service
└─1332 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --cluster-store=consul://192.168.112.102:8500 --cluster-advertise=ens33:2376 --insecure-registry=0.0.0.0/0

4)在tango-centos01主机上创建一个consul

[root@tango-centos01 ~]# docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server bootstrap
[root@tango-centos01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04e635fbc613 progrium/consul "/bin/start -server …" 36 seconds ago Up 9 seconds 53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8301-8302/udp, 0.0.0.0:8500->8500/tcp consul

创建完后通过浏览器访问192.168.112.101:8500,可以看到这两台会自动注册上来,这样的话这两个主机之间就会进行通信。

5)在tango-centos01主机上创建一个overlay网络

[root@tango-centos01 ~]# docker network create -d overlay --subnet=10.0.2.1/24 ov_net1
2a60c89e7b700133e2c4f3af25965aef32a32734eaac53bf1512ef9b7ba3b9bb
[root@tango-centos01 ~]# docker network ls
NETWORK
ID NAME DRIVER SCOPE
bbb3e163e60c bridge bridge local
839aec547da7 host host local
bc52bc1ec263 none null local
2a60c89e7b70 ov_net1 overlay global

第二台主机会自动进行通步,是因为信息存到consul中会自动同步信息

[root@tango-centos02 ~]# docker network ls
NETWORK
ID NAME DRIVER SCOPE
f7f52367c834 bridge bridge local
0ab8d42e5106 host host local
11c97f656489 none null local
2a60c89e7b70 ov_net1 overlay global

6)创建一个使用overlay网络的容器

[root@tango-centos01 ~]# docker run -itd --name bbox1 --network ov_net1 busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
df8698476c65: Pull complete
Digest: sha256:7c223a633b51ef785537d73fbe549655089bdaa8a1cd25acf2de02bd0cdc3364
Status: Downloaded newer image for busybox:latest
36ee2a4181f443a7f7abb61afff75eb1d07e89838c0ac766b25e8946e0fd993d [root@tango-centos01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36ee2a4181f4 busybox "sh" 17 seconds ago Up 15 seconds bbox1

登陆进去查看ip地址是否是10.0.2.0的网段

[root@tango-centos01 ~]# docker exec -it bbox1 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:0A:00:02:02
inet addr:10.0.2.2 Bcast:10.0.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1128 (1.1 KiB) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

它也具备一个nat网络模式,可以访问互联网

/ # ping www.baidu.com
PING
www.baidu.com (14.215.177.39): 56 data bytes
64 bytes from 14.215.177.39: seq=0 ttl=127 time=37.144 ms
64 bytes from 14.215.177.39: seq=1 ttl=127 time=65.292 ms
64 bytes from 14.215.177.39: seq=2 ttl=127 time=93.848 ms
^C
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 37.144/65.428/93.848 ms

7)在tango-centos02上面同样创建一个overlay网路的容器。

[root@tango-centos02 ~]# docker run -itd --name bbox2 --network ov_net1 busybox
beac016541311fdb06cf2c89360bf7202f615e8e65ab974f299093cd35f99c37
[root@tango-centos02 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
beac01654131 busybox "sh" 10 seconds ago Up 7 seconds bbox2
[root@tango-centos02 ~]# docker exec -it bbox2 sh

查看ip地址

/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:0A:00:02:03
inet addr:10.0.2.3 Bcast:10.0.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1128 (1.1 KiB) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

8)查看tango-centos01和tango-centos02的容器网络是否可以互通

/ # ping 10.0.2.2
PING
10.0.2.2 (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: seq=0 ttl=64 time=0.687 ms
64 bytes from 10.0.2.2: seq=1 ttl=64 time=0.415 ms
64 bytes from 10.0.2.2: seq=2 ttl=64 time=0.360 ms
^C
--- 10.0.2.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.360/0.487/0.687 ms

/ # ping bbox1
PING
bbox1 (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: seq=0 ttl=64 time=0.459 ms
64 bytes from 10.0.2.2: seq=1 ttl=64 time=0.397 ms
64 bytes from 10.0.2.2: seq=2 ttl=64 time=0.363 ms
^C
--- bbox1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.363/0.406/0.459 ms

到此,两台主机间的容器可以直接连通,通过overlay network网络模式实现容器跨主机间的通信。

1.4 Macvlan模式

有些应用需要直接连接到物理网络,这个时候可以使用macvlan为每个容器的 虚拟网络接口分配MAC地址。Macvlan 的优点是性能优异,因为无须端口映射或者额外桥接,可以直接通过主机接口(或者子接口)访问容器接口。但是,Macvlan 的缺点是需要将主机网卡(NIC)设置为混杂模式(Promiscuous Mode),这在大部分公有云平台上是不允许的。

如上图描述了Docker macvlan使用场景,假设物理网络上配置了两个VLAN:VLAN 100(10.0.2.0/24)和 VLAN 200(192.168.112.0/24)。我们希望创建一个新的容器接入VLAN 100,可以按照以下步骤进行配置:

1)创建一个名为 macvlan100 的 Macvlan 网络,该网络会连接到 VLAN 100

docker network create -d macvlan \
--subnet=10.0.2.0/24 \
--ip-range=10.0.2.0/25 \
--gateway=10.0.2.1 \
-o parent=eth0.100 \
macvlan100

该命令会创建 macvlan100 的网络以及 eth0.100子接口

2)创建容器部署到该网络中

docker container run -d --name Container1 --network macvlan100

这样就创建了基于macvlan网络模式的容器

案例:相同macvlan网络之间的容器通信

如图以相同macvlan网络之间的容器跨主机通信为例,主要流程如下:

  1. 主机host1和host2分别创建macvlan网络,并创建子网段

  2. 容器内的eth0是由macvlan所在物理接口ens33创建的一个逻辑网口

  3. 当host1向host2发送数据包时,容器内的子网网卡会向它的网关发送一个mac地址请求

  4. 虚拟网关接受请求后会先查询本地的路由表查找发送目标,如果找不到它会转交给ens33来发ARP送广播,来获取目标IP地址是多少

  5. host2收到ARP广播后它会查找本地是否存在目标IP地址,通过IP来获取指定IP的mac地址

  6. 获取mac地址后它会转发给宿主机host2的ens33网卡,然后通过宿主机网卡发送给host1的外网网卡,然后再转给容器内网卡

  • 具体配置过程如下:

1)设置支持promisc

使用 tango-centos01和 tango-centos02上单独的网卡 ens33创建 macvlan。为保证多个 MAC地址的网络包都可以从 ens33通过,我们需要打开网卡的混杂模式(promisc)

[root@tango-centos01 ~]# ip link show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:92:e8:12 brd ff:ff:ff:ff:ff:ff
[root@tango-centos01 ~]# ip link set ens33 promisc on
[root@tango-centos01 ~]# ip link show ens33
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:92:e8:12 brd ff:ff:ff:ff:ff:ff
[root@tango-centos02 ~]# ip link show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:37:f9:17 brd ff:ff:ff:ff:ff:ff
[root@tango-centos02 ~]# ip link set ens33 promisc on
[root@tango-centos02 ~]# ip link show ens33
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:37:f9:17 brd ff:ff:ff:ff:ff:ff

2)创建macvlan网络MAC1

[root@tango-centos01 ~]# docker network create -d macvlan --subnet=10.0.2.0/24 --gateway=10.0.2.1 -o parent=ens33 MAC1
00b0a3987b677332b27a46bd612b45f923e4495b5d8ef4946d138377e7de8136
[root@tango-centos02 ~]# docker network create -d macvlan --subnet=10.0.2.0/24 --gateway=10.0.2.1 -o parent=ens33 MAC1
cbe5e638f842e656cc7b964395b5d8efa15a7511f6672b28fdfc6d711a25ffd6
-d指定 driver 为 macvlan、-o parent 指定使用的网络 interface、指定子网和gateway

注:与其他网络不同,docker 不会为 macvlan 创建网关,这里的网关应该是真实存在的,否则容器无法路由。

3)在 tango-centos01中运行容器 bbox1 并连接到MAC1

[root@tango-centos01 ~]# docker run -itd --name bbox1 --ip=10.0.2.10 --network MAC1 busybox
54fc97a5f3f4bc89b00f3602315161d6ab1bb19e67cf4564fdce944d23d4e27d
[root@tango-centos01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54fc97a5f3f4 busybox "sh" 11 seconds ago Up 9 seconds bbox1

由于tango-centos01中的MAC1与tango-centos02中的MAC2本质上是独立的,为了避免自动分配造成IP冲突,我们最好通过 --ip 指定bbox1地址为10.0.2.10

4)在 tango-centos02中运行容器 bbox2,指定IP为10.0.2.11

[root@tango-centos02 ~]# docker run -itd --name bbox2 --ip=10.0.2.11 --network MAC1 busybox
26e37e629b0cd9a492a672a246de1004402570dfe994ad522cb58dad29ed3bb7

5)验证bbox1和bbox2的连通性

[root@tango-centos02 ~]# docker exec -it bbox2 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:0A:00:02:0B
inet addr:10.0.2.11 Bcast:10.0.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:900 (900.0 B) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

/ # ping 10.0.2.10
PING 10.0.2.10 (10.0.2.10): 56 data bytes
64 bytes from 10.0.2.10: seq=0 ttl=64 time=0.606 ms
64 bytes from 10.0.2.10: seq=1 ttl=64 time=0.288 ms
64 bytes from 10.0.2.10: seq=2 ttl=64 time=0.281 ms
^C
--- 10.0.2.10 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.281/0.391/0.606 ms
/ #
/ # ping bbox1
^C
/ #

注:bbox2能够ping到bbox1的I地址,但是无法解析”bbox1”的主机名。docker没有为macvlan 提供DNS服务,这点与overlay网络是不同的。

1.5 None模式

这个模式和前几个不同,在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器容器只有lo回环网络,没有网卡、IP、路由等信息,需要我们自己为Docker容器添加网卡、配置IP等。

[root@tango-01 ~]# docker run -it --network=none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/
2、Docker容器互联
2.1 同一主机内的容器通信

Docker允许将同一个主机内多个容器连接在一起,共享连接信息。Docker连接会创建一个父子关系,其中父容器可以看到子容器的信息。

1)先创建一个新的 Docker网络net-test01

[root@tango-01 ~]# docker network create -d bridge net-test01
b95c87bb1d270e2df82d4397840e3a5fbf72a99c6a78cbdb8ed04a3a643467db
[root@tango-01 ~]# docker network ls
NETWORK
ID NAME DRIVER SCOPE
56130a7ca84a bridge bridge local
7bbafde1931d host host local
b95c87bb1d27 net-test01 bridge local
56440e57a748 none null local

2)运行一个容器并连接到新建的 net-test01网络

[root@tango-01 ~]# docker run -itd --name test1 --network net-test01 ubuntu /bin/bash
058dbea3d7ba94d15f32b0d453362d4f24db32849a39f7eadecdb229c91173ac
[root@tango-01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
058dbea3d7ba ubuntu "/bin/bash" 2 minutes ago Up 2 minutes test1

打开新的终端,再运行一个容器并加入到net-test01网络:

[root@tango-01 ~]# docker run -itd --name test2 --network net-test01 ubuntu /bin/bash
22c64450cb027ee3575e170eac2fda7632a84ed515149c21bc4d33af4fad783c
[root@tango-01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
22c64450cb02 ubuntu "/bin/bash" About a minute ago Up About a minute test2
058dbea3d7ba ubuntu "/bin/bash" 2 minutes ago Up 2 minutes test1

3)下面通过ping来证明test1容器和test2容器建立了互联关系

如果test1、test2容器内中无ping命令,则在容器内执行以下命令安装 ping:

apt-get update
apt install iputils-ping

在 test1 容器输入以下命令:

[root@tango-01 ~]# docker exec -it test1 /bin/bash
root@058dbea3d7ba:/# apt-get update
root@058dbea3d7ba:/# apt install iputils-ping
root@22c64450cb02:/# ping test2
PING
test2 (172.18.0.3) 56(84) bytes of data.
64 bytes from 22c64450cb02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from 22c64450cb02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.030 ms
64 bytes from 22c64450cb02 (172.18.0.3): icmp_seq=3 ttl=64 time=0.033 ms
^C
--- test2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.029/0.030/0.033/0.001 ms
root@22c64450cb02:/#

同理在test2容器也会成功连接到test1

2.2 跨主机的容器通信

跨主机间的容器通信可以通过Overlay和Macvlan模式实现,参考内容:

  • Overlay网络实现跨主机通信

  • 相同macvlan网络之间的容器通信

参考资料:

  1. https://docs.docker.com/network/

  2. http://www.dockone.io/article/2717

  3. https://www.cnblogs.com/bakari/p/10893589.html

我记得还有ZooKeeper,也是一个常用的服务发现工具,它提供了一种类似于文件系统的层级结构来存储数据,并且具有高可用性和容错性。

补充一点,macvlan模式下,每个容器都有独立的MAC地址,这使得它可以更好地与现有的网络基础设施集成,例如可以直接使用交换机和路由器进行流量管理,而不需要依赖Docker自身的网络管理机制。

局限性的话,我觉得最大的问题是需要将主机网卡设置为混杂模式,这在很多云平台上是不允许的,而且也存在一定的安全风险。另外,macvlan的配置相对复杂,需要对网络底层有一定的了解。

关于macvlan的性能优势,我理解主要在于它绕过了Docker的虚拟网络层,直接与物理网络交互,减少了网络地址转换(NAT)的开销,从而降低了延迟并提高了吞吐量。这对于对网络性能要求很高的应用,比如实时游戏或高频交易系统,非常有益。

针对“文章中提到的五种网络模式,在实际应用中该如何选择?有没有一些通用的选择策略或建议?”这个问题,我觉得可以从几个方面考虑:如果容器需要直接访问外部网络,并且对性能要求较高,可以考虑host或macvlan模式;如果需要跨主机通信,则可以选择overlay模式;如果只是同一主机内的容器通信,则bridge模式就足够了;none模式则适用于需要自定义网络配置的场景。

我补充一下,关于“文章中提到的五种网络模式,在实际应用中该如何选择?有没有一些通用的选择策略或建议?”,选择网络模式还要考虑部署环境的限制。比如,在一些公有云平台上,可能不支持macvlan模式;在一些资源受限的环境中,可能需要选择更轻量级的网络模式,比如bridge模式。

可以考虑一下Eureka,它是Netflix开源的一个服务发现组件,主要用于微服务架构中,支持跨平台部署,并且提供了可视化的管理界面。

对于“文章中提到的五种网络模式,在实际应用中该如何选择?有没有一些通用的选择策略或建议?”我的看法是,选择网络模式时,安全也是一个重要的考虑因素。host模式安全性最低,因为它与主机共享网络命名空间;macvlan模式需要混杂模式,也存在一定的安全风险;bridge和overlay模式相对安全一些,因为它们提供了网络隔离;none模式则取决于具体的网络配置。

服务发现工具的话,etcd也是一个不错的选择,它是一个分布式键值存储系统,可以用于存储和同步配置信息,并且与Kubernetes集成得很好。