Docker网络
目录
内容概述
1.Docker网络
-1.1 网络基础
-1.2 Docker网络模式
2.用Docker部署discuz
内容详细
1.Docker网络
1.1 网络基础
Docker使用到的与linux网络有关的技术分别是:网络名称空间、Veth、Iptables、网桥、路由等
网络名称空间
1、为了支持网络协议栈的多个实例,Linux在网络协议栈中引入了网络名称空间(NetworkNamespace),这些独立的协议栈被隔离到不同的命名空间中。处于不同的命名空间的网络协议栈是完全隔离的,彼此之间无法进行网络通信,就好像两个“平行宇宙”。通过这种对网络资源的隔离,就能在一个宿主机上虚拟多个不同的网络环境,而Docker正是利用这种网络名称空间的特性,实现了不同容器之间的网络隔离。在Linux的网络命名空间内可以有自己独立的Iptables来转发、NAT及IP包过滤等功能。
2、Linux的网络协议栈是十分复杂的,为了支持独立的协议栈,相关的这些全局变量都必须修改为协议栈私有。最好的办法就是让这些全局变量成为一个NetNamespace变量的成员,然后为了协议栈的函数调用加入一个Namespace参数。这就是Linux网络名称空间的核心。所以的网络设备都只能属于一个网络名称空间。当然,通常的物理网络设备只能关联到root这个命名空间中。虚拟网络设备则可以被创建并关联到一个给定的命名空间中,而且可以在这些名称空间之间移动。
# 创建一个命名空间
ip netns add test01
ip netns add test02
ip netns list
test02
test01
Veth设备
引入Veth设备对是为了在不同的网络名称空间之间进行通信,利用它可以直接将两个网络名称空间链接起来。由于要连接的两个网络命名空间,所以Veth设备是成对出现的,很像一对以太网卡,并且中间有一根直连的网线。既然是一对网卡,那么我们将其中一端称为另一端的peer。在Veth设备的一端发送数据时,它会将数据直接发送到另一端,并触发另一端的接收操作。
Veth设备操作
1.创建两个命名空间
# 创建test01命名空间
[root@Centos7 ~]# ip netns add test01
# 创建test02命名空间
[root@Centos7 ~]# ip netns add test02
# 查看命令空间
[root@Centos7 ~]# ip netns list
test02
test01
2.创建Veth设备对
[root@Centos7 ~]# ip link add veth01 type veth peer name veth02
#查看
[root@Centos7 ~]# ip link show
4: veth02@veth01: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether a2:af:63:df:f2:d9 brd ff:ff:ff:ff:ff:ff
5: veth01@veth02: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 7a:d6:8b:90:f1:ce brd ff:ff:ff:ff:ff:ff
# 生成了两个Veth设备,互为对方的peer
3.绑定命名空间
[root@Centos7 ~]# ip link set veth01 netns test01
[root@Centos7 ~]# ip link set veth02 netns test02
[root@Centos7 ~]# ip link show | grep veth
# 已经查看不到veth01和veth02,当我们进入test01命名空间之后,就可以查看到veth01
[root@Centos7 ~]# ip netns exec test01 bash
[root@Centos7 ~]# 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
5: veth01@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 7a:d6:8b:90:f1:ce brd ff:ff:ff:ff:ff:ff link-netnsid 1
[root@Centos7 ~]#exit
exit
[root@Centos7 ~]# ip netns exec test02 bash
[root@Centos7 ~]# 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: veth02@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether a2:af:63:df:f2:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
4.为Veth分配IP
[root@Centos7 ~]# ip netns exec test01 ip addr add 172.16.0.111/20 dev veth01
[root@Centos7 ~]# ip netns exec test01 ip link set dev veth01 up
[root@Centos7 ~]# ip netns exec test02 ip addr add 172.16.0.112/20 dev veth02
[root@Centos7 ~]# ip netns exec test02 ip link set dev veth02 up
#查看
[root@Centos7 ~]# ip netns exec test01 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
5: veth01@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 7a:d6:8b:90:f1:ce brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 172.16.0.111/20 scope global veth01
valid_lft forever preferred_lft forever
inet6 fe80::78d6:8bff:fe90:f1ce/64 scope link
valid_lft forever preferred_lft forever
[root@Centos7 ~]# ip netns exec test02 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: veth02@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether a2:af:63:df:f2:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.0.112/20 scope global veth02
valid_lft forever preferred_lft forever
inet6 fe80::a0af:63ff:fedf:f2d9/64 scope link
valid_lft forever preferred_lft forever
[root@Centos7 ~]# ip netns exec test01 ethtool -S veth01
NIC statistics:
peer_ifindex: 4
[root@Centos7 ~]# ip netns exec test02 ethtool -S veth02
NIC statistics:
peer_ifindex: 5
5.测试网络是否畅通
[root@Centos7 ~]# ip netns exec test01 bash
[root@Centos7 ~]# ping 172.16.0.112
PING 172.16.0.112 (172.16.0.112) 56(84) bytes of data.
64 bytes from 172.16.0.112: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 172.16.0.112: icmp_seq=2 ttl=64 time=0.021 ms
[root@Centos7 ~]# exit
exit
[root@Centos7 ~]# ip netns exec test02 bash
[root@Centos7 ~]# ping 172.16.0.111
PING 172.16.0.111 (172.16.0.111) 56(84) bytes of data.
64 bytes from 172.16.0.111: icmp_seq=1 ttl=64 time=0.014 ms
64 bytes from 172.16.0.111: icmp_seq=2 ttl=64 time=0.022 ms
网桥
Linux可以支持多个不同的网络,它们之间能够相互通信,就需要一个网桥。网桥是二层的虚拟网络设备,它是把若干个网络接口“连接”起来,从而报文能够互相转发。网桥能够解析收发的报文,读取目标MAC地址的信息,和自己记录的MAC表结合,来决定报文的转发目标网口。
网桥设备br0绑定了eth0、eth1。对于网络协议的上层来说,只看得到br0。因为桥接是在数据链路层实现的,上层不需要关心桥接的细节,于是协议上层需要发送的报文被送到br0,网桥设备的处理代码判断报文该被转发到eth0还是eth1,或者两者皆转发。反过来,从eth0或从eth1接收到的报文被提交给网桥的处理代码,在这里会判断报文应该被转发、丢弃还是提交到协议枝上层。而有时eth1也可能会作为报文的源地址或目的地址直接参与报文的发送与接收,从而绕过网桥。
iptables
我们知道,Linux络协议非常高效,同时比较复杂如果我们希望在数据的处理过程中对关心的数据进行一些操作该怎么做呢?Linux提供了一套机制来为用户实现自定义的数据包处理过程。
在Linux网络协议棋中有一组回调函数挂接点,通过这些挂接点挂接的钩子函数可以在Linux网络棋处理数据包的过程中对数据包进行些操作,例如过滤、修改、丢弃等整个挂接点技术叫作Netfilterlptables
Netfilter负责在内核中执行各种挂接的规则,运行在内核模式中:而lptables是在用户模式下运行的进程,负责协助维护内核中Netfilter的各种规则表通过者的配合来实现整个Linux网络协议战中灵活的数据包处理机制。
总结
Docker网络模型 | 配置 | 说明 |
---|---|---|
host模式 | –network=host | 容器和宿主机共享Networknamespace,网络性能最高 |
containe模式 | –network=container:容器ID | 容器和另外一个容器共享Networknamespace。kubernetes中的pod就是多个容器共享一个Networknamespace。 |
none模式 | –network=none | 容器有独立的Networknamespace,但并没有对其进行任何网络设置,如分配vethpair和网桥连接,配置IP等 |
bridge模式 | –network=bridge | 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。(默认为该模式) |
1.2 Docker网络模式(重点)
HOST模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的NetworkNamespace,而是和宿主机共用一个NetworkNamespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是dockerhost上已经使用的端口就不能再用了,网络的隔离性不好。
# 和宿主机公用网卡,使用宿主机的IP和端口,但是文件系统与进程还是与宿主机隔离的
Containe模式
这个模式指定新创建的容器和已经存在的一个容器共享一个NetworkNamespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
# 容器之间共享网卡,端口和IP,其他方面依然是隔离的
none模式
使用none模式,Docker容器拥有自己的NetworkNamespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
Bridge
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡vethpair设备,Docker将vethpair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctlshow命令查看。
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用dockerrun-p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables-tnat-vnL查看。
# 当需要运行的容器变多时,需要的Veth设备也会变得十分的多,对部署造成很大的麻烦。而使用网桥就可以有效的避免这一点。
Docker网桥相关命令
#格式
docker network [cmd]
1.查看网桥
docker network ls
2.创建网桥
docker network create [网桥名称]
3.查看网桥信息
docker network inspect [网桥的名称|ID]
4.添加一个容器网络到网桥中
docker network connect [网络名称] [容器名称]
5.断开容器与这个网桥的连接
docker network disconnect [网络名称] [容器名称]
6.删除一个网桥
docker network rm [网桥名称]
7.清除所有网桥(清除了默认的三个网桥之外的和正在使用的)
docker network prune
2.用Docker部署discuz
在期中架构期间我们已经手动搭建过discuz了,手动搭建的效率还是太低了,这次我们将lnmp架构部署在Docker容器中。
1.创建网桥
docker network create discuz
2.创建数据库
docker run -d --name mysql --network discuz -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=discuz mysql:5.7
3.下载nginx和php镜像
docker pull alvinos/php:wordpress-v2
docker pull alvinos/nginx:wordpress-v2
4.修改nginx的配置文件
server {
listen 80;
listen [::]:80;
server_name localhost;
root /usr/share/nginx/html;
location / {
index index.php index.html index.htm;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
部署语句
docker run -d --name mysql --network discuz -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=discuz mysql:5.7
docker run -d --name php --network discuz -v /root/discuz/upload:/usr/share/nginx/html/ alvinos/php:wordpress-v2
docker run -d --name nginx --network discuz -v /root/discuz/upload:/usr/share/nginx/html/ -v /root/discuz/default.conf:/etc/nginx/conf.d/default.conf -p 8090:80 alvinos/nginx:wordpress-v2