4-Docker网络模型
Docker网络模型
Docker默认是使用网桥进行交互的,Docker完成以上网络配置的过程大致是这样的:
1. 在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
2. Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。
# 查看系统网桥信息
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b172ec42 no
- 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
1、Docker四种网络模型
Docker使用Linux的NameSpaces技术来进行资源隔离,如PID NameSpaces隔离进程,Mount NameSpaces隔离文件系统,同时Network NameSpaces提供了一份独立的网络环境,包括网卡、路由、iptables规则都与其他Network NameSpace隔离。同时提供了四种网络模式。
-
none模式,使用--net=none指定。
-
bridge模式,使用--net=bridge指定,默认即为bridge设置。
-
container模式,使用--net=container:NAME_or_ID指定
-
host模式,使用--net=host指定
1.1、none模式
Docker容器使用none模式启动时容器拥有自己的Network Space,不为Docker容器进行任何网络设置,容器没有网卡、IP、路由信息。
1.2、bridge模式
docker网络隔离基于Network Space,在物理机上创建docker容器时会为每一个docker容器分配网络命名空间,并且把容器IP桥接到物理机的虚拟网桥上。此模式是通过网桥进行交互,会去生成一个子网络,子网络的每个子网络中的ip都是一个单独的网络,一个自己的IP段。
当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。如一般Docker会使用172.17.0.0/16这个网段,并将172.17.42.1/16分配给docker0网桥(在主机上使用ifconfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)。单机环境下的网络拓扑如下,主机地址为10.10.101.105/24。

1.3、container模式
这个模式在创建容器时指定和一个已经存在的容器共享一个Network NameSpaces,但是两个容器还有自己独立的文件系统、主机名等。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
1.4、host模式
和container模式不同,host模式共享的是宿主机的Network NameSpaces,此模式创建的容器没有自己独立的网络命名空间,并且共享物理机的所有端口与IP。
2、通过ip netns创建虚拟网卡对
前面了解过Docker的网络实现是在主机上创建一对虚拟网卡veth pair设备,可以通过ip netns 命令用来管理 network namespace中的虚拟网卡对。
# 查看网络名称空间列表
[root@localhost ~]# ip netns help
Usage: ip netns list
ip netns add NAME
ip netns set NAME NETNSID
ip [-all] netns delete [NAME]
ip netns identify [PID]
ip netns pids NAME
ip [-all] netns exec [NAME] cmd ...
ip netns monitor
ip netns list-id
# 添加两个网络名称空间
[root@localhost ~]# ip netns add ns1
[root@localhost ~]# ip netns add ns2
[root@localhost ~]#
[root@localhost ~]# ip netns list
ns2
ns1
# 创建网卡对
[root@localhost ~]# ip link add name veth1.1 type veth peer name veth1.2
# name:指定网卡名称
# type:指定网卡类型
# peer name:指定另外一半网卡名称
[root@localhost ~]# ip link show
# 查看网卡对,下面可以看到veth1.1和veth1.2这对网卡
......
4: veth1.2@veth1.1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether e6:bb:5f:08:40:73 brd ff:ff:ff:ff:ff:ff
5: veth1.1@veth1.2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 62:63:07:98:2c:cf brd ff:ff:ff:ff:ff:ff
# 将veth1.1留在宿主机上,将veth1.2移到前面创建的名称空间ns1上,模拟在不同设备上成对出现
[root@localhost ~]# ip link set dev veth1.2 netns ns1 # 将veth1.2绑定到ns1名称空间中
[root@localhost ~]# ip link show
......
# 可以看到宿主机上只有veth1.1网卡了,另外一半就在ns名称空间了
5: veth1.1@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 62:63:07:98:2c:cf brd ff:ff:ff:ff:ff:ff link-netnsid 0
# 查看ns1名称空间的网卡
[root@localhost ~]# ip netns exec ns1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: veth1.2@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether e6:bb:5f:08:40:73 brd ff:ff:ff:ff:ff:ff link-netnsid 0
# 给宿主机上的这一半网卡veth1.1配置IP并启动
[root@localhost ~]# ip addr add 10.1.0.1/24 dev veth1.1
[root@localhost ~]# ip link set veth1.1 up
# 给名称空间上的另一半网卡veth1.2配置IP并启动
[root@localhost ~]# ip netns exec ns1 ip addr add 10.1.0.2/24 dev veth1.2
[root@localhost ~]# ip netns exec ns1 ip link set veth1.2 up
# 在名称空间间ping在宿主机上这一半的网卡验证
[root@localhost ~]# ip netns exec ns1 ping 10.1.0.1
PING 10.1.0.1 (10.1.0.1) 56(84) bytes of data.
64 bytes from 10.1.0.1: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 10.1.0.1: icmp_seq=2 ttl=64 time=0.028 ms
64 bytes from 10.1.0.1: icmp_seq=3 ttl=64 time=0.026 ms
3、创建四种网络类型容器
3.1、创建none类型网络的容器
[root@localhost ~]# docker run --name t1 -it --network none --rm busybox:latest
/ # 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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
3.2、创建bridge类型网络的容器
[root@localhost ~]# docker run --name t1 -it --network bridge --rm busybox:latest
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 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:516 (516.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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
# 创建时配置主机名
[root@localhost ~]# docker run --name t1 -it --network bridge -h larry.test.com --rm busybox:latest
/ # hostname
larry.test.com
# 创建时配置dns服务器地址
[root@localhost ~]# docker run --name t1 -it --network bridge --dns 114.114.114.114 --rm busybox:latest
/ # cat /etc/resolv.conf
search localdomain
nameserver 114.114.114.114
创建container类型网络的容器
# 1、创建第一个bridge类型容器
[root@localhost ~]# docker run --name busybox1 -it --rm busybox:latest / # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 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:516 (516.0 B) TX bytes:0 (0.0 B)
# 2、创建第二个container类型的容器
[root@localhost ~]# docker run --name busybox2 --network container:busybox1 -it --rm busybox:latest
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 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:656 (656.0 B) TX bytes:0 (0.0 B)
上面的例子可以看到两个容器的ip地址是一样的,说明使用了相同的网路名称空间,单其他名称空间还是独立的,比如主机名、硬盘等。
3.4、创建host类型网络的容器
[root@localhost ~]# docker run --name t1 --network host -it --rm busybox
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:7B:F3:10:88
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:7bff:fef3:1088/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:656 (656.0 B)
enp0s3 Link encap:Ethernet HWaddr 08:00:27:46:31:55
inet addr:10.0.16.90 Bcast:10.0.17.255 Mask:255.255.254.0
inet6 addr: fe80::a00:27ff:fe46:3155/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8651 errors:0 dropped:2 overruns:0 frame:0
TX packets:1621 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:890929 (870.0 KiB) TX bytes:302211 (295.1 KiB)
上面可以看到生成的ip和宿主机的ip相同。
4、自定义Docker默认网络属性信息
docker默认使用172.17.x.x作为容器的虚拟ip地址,这个地址可以修改。
自定义docker0桥的网络属性信息:/etc/docker/daemon.json文件
{
"bip": "192.168.1.5/24",
"fixed-cidr": "10.20.0.0/16",
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "10.20.1.1",
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}
核心选项为bip,即bridge ip之意,用于指定docker0桥自身的IP地址;其它选项可通过此地址计算得出。
自定义Docker监听端口
dockerd守护进程的C/S,其默认仅监听Unix SOcket格式的地址,/var/run/docker.sock;如果使用TCP套接字。
修改/etc/docker/daemon.json,添加:
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
也可向dockerd直接传递“-H|--host”选项;
可以通过-H远程连接其他docker服务
# docker -H 10.0.16.91:2375 image ls
6、自定义网桥
docker可以自定义网桥
[root@localhost ~]# docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" mybr07e5ee2128e3f20789db14245928bfc76decfec01cdcb2634868217cef6e71331[root@localhost ~]# docker network lsNETWORK ID NAME DRIVER SCOPEb38755c57d8c bridge bridge local136e91e4c434 host host local7e5ee2128e3f mybr0 bridge localb9e4dcb6ea19 none null local[root@localhost ~]# ip a......3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:7b:f3:10:88 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:7bff:fef3:1088/64 scope link valid_lft forever preferred_lft forever14: br-7e5ee2128e3f: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:23:d1:64:89 brd ff:ff:ff:ff:ff:ff inet 172.26.0.1/16 brd 172.26.255.255 scope global br-7e5ee2128e3f valid_lft forever preferred_lft forever

浙公网安备 33010602011771号