Docker的网络
Docker网络通讯
Docker通讯是通过Docker0(Bridge)网桥和DNAT转换实现的
Docker使用Linux桥接,再宿主机虚拟一个Docker0网桥,Docker每启动一个容器会根据Docker网桥的网段分配给容器一个IP地址,Docker0网桥是每个容器的默认网关。因为在同一个宿主机都接入同一个网桥,这样容器之间就能够通过容器的IP直接通信、
Docker网桥是宿主机虚拟出来的,并不是真是存在的网络设备,外界是无法直接通过IP地址访问到容器的。如果容器需要外界能够访问到,可以通过DNAT转换映射容器端口到宿主机端口。在docker run时使用-p参数来启用
Docker容器修改常用命令
参数 | 描述 |
---|---|
–dns | 指定容器的DNS |
–net | 指定容器的网络通讯方式(bridge、none、container、host) |
-b,–bridge= | 指定Docker使用的网桥设备,默认Docker会自动创建和使用docker0网桥设备 |
–bip | 指定Docker0和IP和掩码,使用标准的CIDR形式。 |
网络类型
当安装启用Docker时,会自动创建三个网络。bridge、none、host。可以通过docker network ls
进行查看
当使用docke run不指定–network=时 ,默认使用的时bridge模式。
Docker网络模式 | 配置 | 说明 |
---|---|---|
host模式 | –net=host | 容器和宿主机共享Network namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。 |
container模式 | –net=container:NAME_or_ID | 容器和另外一个容器共享Network namespace。创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围 |
bridge模式 | –net=bridge | (默认为该模式)此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。 |
none模式 | –net=none | 该模式关闭了容器的网络功能。 |
host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
bridge模式
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
自定义网络通讯
建议使用自定义的网桥来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Overlay或Macvlan网络。你还可以创建一个网络插件或远程网络进行完整的自定义和控制。
你可以根据需要创建任意数量的网络,并且可以在任何给定时间将容器连接到这些网络中的零个或多个网络。此外,您可以连接并断开网络中的运行容器,而无需重新启动容器。当容器连接到多个网络时,其外部连接通过第一个非内部网络以词法顺序提供。
创建一个自定义网桥(bridge)
docker network create --driver bridge --subnet 172.168.0.0/16 --gateway 172.168.0.1 mynet
docker network ls
docker network inspect mynet
启动两个容器测试,使用mynet网桥模式
docker run -d -P --name tomcat-mynet-01 --net mynet tomcat
docker run -d -P --name tomcat-mynet-02 --net mynet tomcat
docker ps -a
查看到mynet网桥中已经有了tomcat-mynet-01、tomcat-mynet-02
[root@localhost ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "b18b00e1dac45499529b9507af77415da26bfc85c64d70095a613f4847d8f7fd",
"Created": "2021-05-06T19:11:46.752935498+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.168.0.0/16",
"Gateway": "172.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"058622f0affb79c687d1b2180397638285e3f817d3eb597e7111a9a7a4d21002": {
"Name": "tomcat-mynet-02",
"EndpointID": "07e9319b9ceffb777492998d64d41de73d3f5385afbe727c784295a1571f83b5",
"MacAddress": "02:42:ac:a8:00:03",
"IPv4Address": "172.168.0.3/16",
"IPv6Address": ""
},
"38f5a1dca56e2b895235938a108faf84b5400ec3bbef1e7c391d11411366e252": {
"Name": "tomcat-mynet-01",
"EndpointID": "f2c64838c35cff6227f8213e6dbabe3c8171ff5f6adebaedf8d50403e54f7f20",
"MacAddress": "02:42:ac:a8:00:02",
"IPv4Address": "172.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
接下来进行ping测试
自定义网络docker都已经帮我们维护好了对应的关系
所以我们平时可以这样使用网络,不是用–link效果一样,多有东西实时维护好,直接域名ping通
Docker0和自定义网络肯定不同,使用自定义网络的好处就是网络隔离:
比如公司项目部署的业务都非常多,假设我们有一个商城,我们会有订单业务(操作不同数据),会有订单业务购物车(操作不同缓存)。如果在一个网络下,有的恶意代码就不能防止了,所欲我们在部署的时候网络隔离,创建两个桥接网卡,比如订单业务放在order-net网络下,其他业务放在其他网络下。
Macvlan
Macvlan是一个新的尝试,是真正的网络虚拟化技术的转折点。Linux实现非常轻量级,因为与传统的Linux Bridge隔离相比,它们只是简单地与一个Linux以太网接口或子接口相关联,以实现网络之间的分离和与物理网络的连接。
Macvlan提供了许多独特的功能,并有充足的空间进一步创新与各种模式。这些方法的两个高级优点是绕过Linux网桥的正面性能以及移动部件少的简单性。删除传统上驻留在Docker主机NIC和容器接口之间的网桥留下了一个非常简单的设置,包括容器接口,直接连接到Docker主机接口。由于在这些情况下没有端口映射,因此可以轻松访问外部服务。
overlay网络
overlay网络用于连接不同机器的docker容器,允许不同机器上的容器互相通信,同事支持对消息进行加密,当我们初始化一个swarm或是加入到一个swarm中时,在docker主机上回出席那两种网络:
- ingress的overlay网络,用于传递集群服务的控制或是数据消息,若在创建swarm服务时没有指定连接用户自定义的overlay网络,将会加入到默认的ingress网络
- docker——gwbridge桥接网络会桥接swarm中所有的docker系统进程
可以使用docker network create创建自定义的overlay网络,容器以及服务可以加入到多个网络,只有统一网络的容器才可以互相交换信息,可以将单一容器或是swarm服务连接到overlay网络中,但是两者在overlay网络中的行为会有所不同
network namespace
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络
使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样
# 创建虚拟网络空间
ip netns add r1
# 进入虚拟网络空间
ip netns exec ns1 bash
# 添加一对 veth 设备
ip link add veth1.1 type veth peer name veth1.2
# 将其中一块网卡放入至 ns1 网络名称空间之中
ip link set veth1.1 netns r1
# 更改网络名称
ip link set veth1.1 name eth0
# 启动网卡
ip link set eth0 up
# 设置网卡名称
ip addr add 10.0.0.11/24 dev eth0
# 启动回环网卡
ip link set lo up
### 使用 Linux 桥接器进行主机间的通讯
使用Linux桥接器进行主机间的通信
```bash
cd /etc/sysconfig/network-scripts/
cp ifcfg-eth0 ifcfg-br0
vi ifcfg-eth0
DEVICE=eth0
HWADDR=00:0C:29:06:A2:35
TYPE=Ethernet
UUID=34b706cc-aa46-4be3-91fc-d1f48c301f23
ONBOOT=yes
BRIDGE=br0
NM_CONTROLLED=yes
BOOTPROTO=static
vi ifcfg-br0
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.216.131
NETMASK=255.255.255.0
GATEWAY=192.168.216.2
DN1=8.8.8.8
yum install -y git
git clone https://github.com/jpetazzo/pipework
cp pipework/pipework /usr/local/bin/
docker run -itd --net=none --name=ff centos-6-x86 bash
pipework br0 fl 192.168.216.135/24