Docker网络

Posted shi_zi_183

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker网络相关的知识,希望对你有一定的参考价值。

Docker网络

Libnetwork

Libnetwork提出了新的容器网络模型(Container Network Model简称CNM),定义了标准的API用于为容器配置网络,其底层可以适配各种网络驱动。CNM有三个重要的概念:

  • 沙盒。沙盒是一个隔离的网络运行环境,保存了容器网络栈的配置,包括了对网络接口、路由表和DNS配置的管理。在Linux平台上,沙盒是用Linux Network Namespace实现的,在其他平台上可能是不同的概念,如FreeBSD Jail。一个沙盒可以包括来自多个网络的多个Endpoint(端点)。
  • Endpoint。Endpoint将沙盒加入一个网络,Endpoint的实现可以是一对veth pair或者OVS内部端口,当前的Libnetwork使用的是veth pair。一个Endpoint只能隶属于一个沙盒及一个网络。通过给沙盒增加多个Endpoint可以将一个沙盒加入多个网络。
  • 网络。网络包括一组能互相通信的Endpoint。网络的实现可以是Linux bridge、vlan等。

从CNM的概念角度讲,Libnetwork的出现使得Docker具备了跨主机多子网的能力,同一个子网内的不同容器可以运行在不同的主机上。比如,同属于192.168.0.0/24子网ip地址分别为192.168.0.1和192.168.0.2的容器可以位于不同的主机上且可以直接通信,而持有IP192.168.1.1的容器即使与IP为192.168.0.1的容器处于同一主机也不能互通。
到Docker1.8发布,Libnetwork已经实现了五种驱动(driver):

  • bridge:Docker默认的容器网络驱动。Container通过一对veth pair连接到docker0网桥上,由Docker为容器动态分配IP及配置路由、防火墙规则等。
  • host:容器与主机共享同一Network Namespace,共享同一套网络协议栈、路由表及iptables规则等。容器与主机看到的是相同的网络视图。
  • null:容器内网络配置为空,需要用户手动为容器配置网络接口及路由等。
  • remote:Docker网络插件的实现。Remote driver使得Libnetwork可以通过HTTP RESTful API对接第三方的网络方案,类似SocketPlane的SDN方案只要实现了约定的HTTP URL处理函数及底层的网络接口配置方法,就可以替换Docker原生的网络实现。
  • overlay:Docker原生的跨主机多子网网络方案。主要通过使用Linux bridge和vxlan隧道实现,底层通过类似于etcd或consul的KV存储系统实现多机的信息同步。

基本网络配置

Docker网络初探

Linux平台下,Docker容器网络资源通过内核的Network Namespace机制实现隔离,不同的Network Namespace有各自的网络设备、协议栈、路由表、防火墙规则等,反之,同一Network Namespace下的进程共享同一网络视图。通过对Network Namespace的灵活操纵,Docker提供了五种容器网络模式。
1)none:不为容器配置任何网络功能。
在该模式下,需要以 --net=none参数启动容器:

docker run --net=none -ti centos ip addr show


可以看到Docker容器仅有一个lo环回接口,用户使用–net-none启动容器之后,仍然可以手动为容器配置网络。
2)container:与另一个运行中的容器共享Network Namespace,共享相同的网络视图。
举个例子,首先以默认网络配置(bridge模式)启动一个容器,设置hostname为dockerNet,dns为8.8.4.4。

docker run -h dockerNet --dns 8.8.4.4 -tid centos bash
docker exec -it 77481c019ed7 bash
ip addr
cat /etc/resolv.conf



然后以–net=container:77481c019ed7方式启动另一个容器

docker run --net=container:77481c019ed7 -ti centos bash


可以看到,使用–net=container:77481c019ed7 参数启动的容器,其ip地址、DNS、hostname都继承了容器77481c019ed7 。实质上两个容器是共享同一个Network Namespace的,自然网络配置也是完全相同的。
3)host:与主机共享Root Network Namespace,容器有完整的权限可以操纵主机的协议栈、路由表和防火墙等,所以被认为是不安全的。
相应的,host模式启动时需要指定–net=host参数。

docker run -it --net=host centos bash


host模式下,容器可以操纵主机的网络配置,这是危险的,除非万不得已,应该尽可能避免使用host模式。
4)bridge:Docker设计的NAT网络模型。
Docker daemon启动时会在主机创建一个Linux网桥(默认为docker0,可通过-b参数手动指定)。容器启动时,Docker会创建一对veth pair(虚拟网络接口)设备,veth设备的特点是成对存在,从一端进入的数据会同时出现在另一端。Docker会将一端挂载到docker0网桥上,另一端放入容器的Network Namespace内,从而实现容器与主机通信的目的。
在桥接模式下,Docker容器与Internet的通信,以及不同容器之间的通信,都是通过iptables规则控制的。
总之,Docker网络的初始化动作包括:创建docker0网桥、为docker0网桥新建子网路由、创建相应的iptables规则等。
举例来说,初次启动Docker daemon后,用户可以观察到主机的网络接口、网桥、路由等信息发生了如下变化


Bridge模式是Docker默认的容器运行模式,以bridge模式启动的容器,默认会以172.17.42.1/16子网内分配IP

docker run -it --net=bridg centos ip addr show

5)overlay:Docker原生的跨主机多子网模型
overlay网络模型比较复杂,底层需要类似consul或etcd的KV存储系统进行消息同步,核心是通过Linux网桥与vxlan隧道实现跨主机划分子网。
每创建一个网络,Docker会在主机上创建一个单独的沙盒,沙盒的实现实质上是一个Network Namespace。在沙盒中,Docker会创建名为br0的网桥,并在网桥上增加一个vxlan接口,每个网络占用一个vxlan ID,当前Docker创建vxlan隧道的ID范围为256~1000,因而最多可以创建745个网络。当添加一个容器到某个网络上时,Docker会创建一对veth网卡设备,一端连接到此网络相关沙盒内的br0网桥上,另一端放入容器的沙盒内,并设置br0的IP地址作为容器内路由默认的网关地址,从而实现容器加入网络的目的。

跨主机网络部署

系统环境

hostnamehostip
node1192.168.2.120
node2192.168.2.121

安装Consul

以下操作都是在node1中进行的,Consul只需运行在一个节点即可
获取Consul压缩包

wget https://releases.hashicorp.com/consul/1.9.11/consul_1.9.11_linux_386.zip

解压压缩包

unzip consul_1.9.11_linux_386.zip

移植扫描目录并给予可执行权限

mv consul /usr/bin/ && chmod a+x /usr/bin/consul

启动

nohup consul agent -server -bootstrap -ui -data-dir /data/docker/consul -bind=192.168.2.120 &> /var/log/consul.log &

测试
访问192.168.2.120:8500查看ui界面

节点配置Docker守护进程连接Consul

两台机器上都要修改
node1

vi /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd  -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store consul://192.168.2.120:8500 --cluster-advertise 192.168.2.120:2375

systemctl daemon-reload
systemctl restart docker

node2
同上操作一样
修改一处

ExecStart=/usr/bin/dockerd  -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store consul://192.168.2.120:8500 --cluster-advertise 192.168.2.121:2375

注意 --cluster-advertise后ip为本机局域网ip

配置成功

创建overlay网络

docker network ls

docker network create -d overlay multi_host

node1

node2

使用overlay网络启动容器

分别在两台机器上使用overlay网络启动一个容器

docker run -it --net=multi_host centos




Consul集群配置

之前Consul只有一个节点,这有一些问题

  • 单节点压力过大,故障后整个集群会当掉,可用性不高
  • 网络拓扑环境更改后,所有节点都需要修改Docker守护进程配置。
    等等。
    我们可以通过Consul修改。
    将集群修改为初始态(停掉consul,docker),我们重新开始。

启动consul

node1

nohup consul agent -server -bootstrap -data-dir /data/docker/consul -bind=192.168.2.120 &> /var/log/consul.log &

可以看到这里相比之前删去了client参数,这是因为client参数只能设置一个值,我们之前设置了192.168.2.120可以方便的通过192.168.2.120查看UI页面,但是localhost访问会被禁止,这是我们不想要的。在localhost和UI页面之间我选择了前者,去掉之后,client会使用默认值127.0.0.1。这样也就可以将ui参数去掉,不再查看页面了。

node2

nohup consul agent -server -bootstrap -data-dir /data/docker/consul -bind=192.168.2.121 -join=192.168.2.120 &> /var/log/consul.log &

这里多出了join参数,是用来将node2和node1进行连接。这样不论在node1或node2上注册的服务都会共享。

修改Docker守护进程配置

ExecStart=/usr/bin/dockerd  -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store consul://localhost:8500 --cluster-advertise 192.168.2.121:2375

之后测试都一样,可以对照上面做。

以上是关于Docker网络的主要内容,如果未能解决你的问题,请参考以下文章

docker 网络

Docker网络

docker桥接模式

云原生网络架构

Docker NAT iptables实现 及网络配置

Docker flannel网络