Docker 网络管理--五种网络模式


一:了解宿主机网络和容器网络状态关联(bridge网络模式)。


每次新建容器后,宿主机多了一个虚拟网卡,和容器的网卡组合成一个网卡,比如:186: vetha9dbe9c@if185,
而在容器内的网卡名为(185: eth0@if186),可以看出和宿主机的网卡之间的关联,
容器会自动获取一个172.17.0.0/16网段的随机地址,默认从172.17.0.2开始,第二次容器为172.17.0.3,以此类推


#创建容器前宿主机网络配置
[root@localhost7B ~]# ip a
....
省略部分
....
6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:f1:d7:04:96 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:f1ff:fed7:496/64 scope link
valid_lft forever preferred_lft forever


root@localhost7B ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242f1d70496 no
virbr0 8000.525400ecdab8 yes virbr0-nic



#创建容器后的宿主机网络配置
[root@localhost7B ~]# docker run -it -d --name centosA centos:7
fa32a5ac5c983da61f6079d68a2cec22ebc811172228cf7d52801f9ec5b4358e
[root@localhost7B ~]# docker run -it -d --name centosB centos:7
a7b0f8fd0ae0a7d1b27d8d22128405b85fdcf4d9c193b2f70c1aca65b3e7aeca


#宿主机网络
[root@localhost7B ~]# ip a
....
省略部分
....
186: vetha9dbe9c@if185: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether fe:e1:c0:dd:18:3b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::fce1:c0ff:fedd:183b/64 scope link
valid_lft forever preferred_lft forever
188: vethfa558dc@if187: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether be:1e:9e:f2:3c:13 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::bc1e:9eff:fef2:3c13/64 scope link
valid_lft forever preferred_lft forever


#新建容器后桥接状态
[root@localhost7B ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242f1d70496 no vetha9dbe9c
vethfa558dc
virbr0 8000.525400ecdab8 yes virbr0-nic

 

#容器的ip地址
[root@localhost7B ~]# docker exec -it centosA bash
[root@fa32a5ac5c98 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
185: eth0@if186: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

 

宿主机网络结构图,本例中使用的是bridge模式,没有创建host模式的网络,查看后续案例。

 

Docker 的网络支持5种网络模式:
  1.bridge(默认)
  2.none
  3.host
  4.container
  5.network-name

  docker run --network <mode>

一、bridge模式,--net=bridge(默认)

本模式是docker的默认模式,即不指定任何模式就是bridge模式,也是使用比较多的模式,
此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信
可以和外部网络之间进行通信,通过宿主机的物理网卡利用SNAT访问外网,使用DNAT可以入容器被外部主机访问,所以此模式也称为NAT模式

    
bridge网络模式特点
    -宿主机的需要启动ip_forward功能
    -网络资源隔离:不同宿主机的容器无法直接通信,各自使用独立风络
    -无需手动配置:容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
    -可访问外网:利用宿主机的物理网卡,SNAT连接外网
    -外部主机无法直接访问容器:可以通过配置DNAT接受外网的访问
    -低性能较低:因为可通过NAT,网络转换带来更的损耗
    -端口管理繁琐:每个容器必须手动指定唯一的端口,容器产生端口冲容    
    -bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,对宿主机端口的管理会是一个比较大的问题。
    -由于容器与外界通信是基于三层上iptables NAT,性能和效率上的损耗是可以预见的。


从上面的网络模型可以看出,容器从原理上是可以与宿主机乃至外界的其他机器通信的。同一宿主机上,容器之间都是连接掉docker0这个网桥上的,
它可以作为虚拟交换机使容器可以相互通信。然而,由于宿主机的IP地址与容器veth pair的 IP地址均不在同一个网段,故仅仅依靠veth pair和namespace的技术,
还不足以使宿主机以外的网络主动发现容器的存在。为了使外界可以方位容器中的进程,docker采用了端口绑定的方式,也就是通过iptables的NAT,
将宿主机上的端口端口流量转发到容器内的端口上。
举一个简单的例子,使用下面的命令创建容器,并将宿主机的3306端口绑定到容器的3306端口:
#docker run -d -p 3306:3306  --name mysqlA  -e  MYSQL_ROOT_PASSWORD=123456  mysql:5.7.29
在宿主机上,可以通过iptables -t nat -L -n,查到一条DNAT规则:
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306



例: [root@localhost7B
~]# docker network inspect bridge [ { "Name": "bridge", "Id": "dadcee624d9f39c54f392b3ab65b3c4946c547237c9f296c3560b8b1a04f2066", "Created": "2022-10-14T14:45:56.711288575+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] [root@localhost7B ~]# cat /proc/sys/net/ipv4/ip_forward 1 [root@localhost7B ~]#docker run -d -p 3306:3306 --name mysqlA -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.29 [root@localhost7B ~]# iptables -vnL -t nat Chain PREROUTING (policy ACCEPT 36 packets, 3618 bytes) pkts bytes target prot opt in out source destination 47 2520 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 36 packets, 3618 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 17 packets, 1172 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 17 packets, 1172 bytes) pkts bytes target prot opt in out source destination 0 0 MASQUERADE all -- * !br-775d6ddec6bb 172.27.0.0/16 0.0.0.0/0 395 25304 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 2 279 RETURN all -- * * 192.168.122.0/24 224.0.0.0/24 0 0 RETURN all -- * * 192.168.122.0/24 255.255.255.255 0 0 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 0 0 MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 0 0 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24 0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:3306 Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- br-775d6ddec6bb * 0.0.0.0/0 0.0.0.0/0 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.2:3306

 

二、host模式,--net=host

启动的容器如果指定host模式,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,
因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,
不过容器内除网络以外的其它资源,如:文件系统、系统进程等仍然和宿主机保持隔离
此模式由于直接使用宿主机的网络无需转换,网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务

Host网络模式特点:
    -使用参数 –network host 指定
    -共享宿主机网络
    -网络性能无损耗
    -网络故障排除相对简单
    -各容器网络无隔离
    -网络资源无法分别统计
    -端口管理困难:容易产生端口冲突
    -不支持端口映射
  一个宿主机只能有一个host网络模式实例,不能创建多个.

[root@localhost7C ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.100.0.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::42:cdff:fe40:f877  prefixlen 64  scopeid 0x20<link>
        ether 02:42:cd:40:f8:77  txqueuelen 0  (Ethernet)
        RX packets 10266  bytes 414244 (404.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14941  bytes 25980712 (24.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.80.120  netmask 255.255.255.0  broadcast 192.168.80.255
        inet6 fe80::7cd:a65c:16d4:ff57  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a2:14:02  txqueuelen 1000  (Ethernet)
        RX packets 974428  bytes 1020747076 (973.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 106441  bytes 8097431 (7.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


[root@localhost7C ~]# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.80.2    0.0.0.0         UG    100    0        0 eth0
10.100.0.0      0.0.0.0         255.255.255.0   U     0      0        0 docker0

#创建host模式的容器
[root@localhost7C ~]# docker run  -it  -d  --network host --name web1  centos-base:v1
[root@localhost7C ~]# docker exec  -it web1   bash
[root@localhost7C /]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.100.0.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::42:cdff:fe40:f877  prefixlen 64  scopeid 0x20<link>
        ether 02:42:cd:40:f8:77  txqueuelen 0  (Ethernet)
        RX packets 10274  bytes 414788 (405.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14941  bytes 25980712 (24.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.80.120  netmask 255.255.255.0  broadcast 192.168.80.255
        inet6 fe80::7cd:a65c:16d4:ff57  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a2:14:02  txqueuelen 1000  (Ethernet)
        RX packets 975337  bytes 1020857467 (973.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 107003  bytes 8178707 (7.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


#host模式下端口映射无法实现
[root@localhost7C ~]# docker run  -it  -d  --name  nginxB --network host  -p:80:80  docker.io/nginx bash
#对比前面host模式的容器和bridge模式的端口映射
[root@localhost7C ~]# docker run  -it  -d  --name  nginxA    -p:81:80  docker.io/nginx bash
267d2070667565190f93ea0c20bd6a188a59d9f1be1ee81bd876c23c5d03df37
[root@localhost7C ~]# docker port nginxB
[root@localhost7C ~]# docker port nginxA
80/tcp -> 0.0.0.0:81

 

三、none模式,--net=none

[root@localhost7C ~]# docker run  -it  -d  --name  centosA  --network  none  centos-base:v1  bash
a38c77cc23f5293d1fb8dcc22161063777469ef8128ae6574722ba0f5b348b75
[root@localhost7C ~]# 
[root@localhost7C ~]# 
[root@localhost7C ~]# docker exec  -it centosA bash
[root@a38c77cc23f5 /]# 
[root@a38c77cc23f5 /]# 
[root@a38c77cc23f5 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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

 

 四、容器模式(即container模式,join模式),--net=container:NAME_or_ID

 

使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网,新创建的容器不会创建自己的网卡也不会配置自己的IP,
而是和一个已经存在的被指定的容器东西IP和端口范围,因此这个容器的端口不能和被指定的端口冲突,
除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡社保通信


Container模式特点
    -使用参数 –-network container:名称或ID 指定
    -与宿主机网络空间隔离
    -容器间共享网络空间
    -适合频繁的容器间的网络通信
    -直接使用对方的网络,较少使用
    -主机名相同
   -通过link通信

[root@localhost7C ~]# docker run  -it  -d  --name  centosA   centos-base:v1  bash
6449387eaa0596538017cfbc6b3dde4aaf4dd8f840f7f00b08c8586e83f94938
 
[root@localhost7C ~]# docker exec  -it centosA bash
[root@6449387eaa05 /]# netstat  -anltp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name  
  
[root@6449387eaa05 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0a:64:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.100.0.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:aff:fe64:2/64 scope link 
       valid_lft forever preferred_lft forever

#在另一个终端执行下面操作
[root@localhost7C ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6449387eaa05 centos-base:v1 "bash" About a minute ago Up About a minute centosA


[root@localhost7C ~]# docker run -it -d --name centosB --network container:centosA centos-base:v1 bash
66c4b35af222b6158b40023081fa5d66cf3ebda69f10c62ffc4884ee2a00d608


[root@localhost7C ~]# docker exec -it centosB bash


#和第一个容器共享相同的网络,IP相同。
[root@6449387eaa05 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.100.0.2 netmask 255.255.255.0 broadcast 0.0.0.0
inet6 fe80::42:aff:fe64:2 prefixlen 64 scopeid 0x20<link>
ether 02:42:0a:64:00:02 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0


[root@6449387eaa05 /]# curl www.zjol.com.cn


#第一台主机容器测试网络。
[root@6449387eaa05 /]# netstat -anltp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 10.100.0.2:47840 203.107.36.9:80 TIME_WAIT -
tcp 0 0 10.100.0.2:47838 203.107.36.9:80 TIME_WAIT -

 

 五、用户自定义网络

 

在用户定义网络模式下,开发者可以使用任何docker支持的第三方网络driver来定制容器的网络。并且,docker 1.9以上的版本默认自带了bridge和overlay两种类型的自定义网络driver。
可以用于集成calico、weave、openvswitch等第三方厂商的网络实现。 除了docker自带的bridge driver,其他的几种driver都可以实现容器的跨主机通信。
而基于bdrige driver的网络,docker会自动为其创建iptables规则,保证与其他网络之间、与docker0之间的网络隔离。 

例:使用下面的命令创建一个基于bridge driver的自定义网络:
[root@localhost7C ~]# docker  network create -d bridge --subnet 172.27.0.0/16 --gateway 172.27.0.1 zzhz
b3a5712a5391eff8db290b25893e88a496432d54c63df050efb05c44ccbf938f
[root@localhost7C ~]# 
[root@localhost7C ~]# 
[root@localhost7C ~]# docker network ls 
NETWORK ID          NAME                DRIVER              SCOPE
796c38ad861b        bridge              bridge              local
00e08763c06a        host                host                local
0bf2813ea139        none                null                local
b3a5712a5391        zzhz                bridge              local

[root@localhost7C ~]# ip a

6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:cd:40:f8:77 brd ff:ff:ff:ff:ff:ff
    inet 10.100.0.1/24 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:cdff:fe40:f877/64 scope link 
       valid_lft forever preferred_lft forever
21: br-b3a5712a5391: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:ac:d8:d7:4a brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.1/16 scope global br-b3a5712a5391
       valid_lft forever preferred_lft forever
[root@localhost7C ~]# brctl  show
bridge name                bridge id        STP enabled    interfaces
br-b3a5712a5391        8000.0242acd8d74a    no        
docker0                8000.0242cd40f877    no        
virbr0                8000.525400fbc09b    yes        virbr0-nic


[root@localhost7C ~]# route  -n
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.80.2    0.0.0.0         UG    100    0        0 eth0
10.100.0.0      0.0.0.0         255.255.255.0   U     0      0        0 docker0
172.27.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-b3a5712a5391

[root@localhost7C ~]# docker run  -it  -d  --name centosA  
centos-base             centos-base:v1          docker.io/nginx         docker.io/nginx:latest  
[root@localhost7C ~]# docker run  -it  -d  --name centosA --network zzhz   centos-base:v1 
833c8730e36d7e391a27c53ed44e5d62502f3ab10753dd21f5f7857c471dcd30
[root@localhost7C ~]# docker exec  -it  centosA bash
[root@833c8730e36d /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.27.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe1b:2/64 scope link 
       valid_lft forever preferred_lft forever

#则docker会自动生成如下的iptables规则,保证不同网络上的容器无法互相通信。
[root@localhost7C ~]# iptables -vnL  -t nat
....
......
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  br-b3a5712a5391 *       0.0.0.0/0            0.0.0.0/0           
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0   

 

posted @ 2022-10-20 15:21  yuanbangchen  阅读(819)  评论(0编辑  收藏  举报