欢迎您, 来到 宁时修博客.^_^

Docker系列10--网络管理(下)

2018/11/19 林木立 Docker 1041
Docker容器技术

一、Docker高级网络管理

    当 Docker 启动时,会自动在主机上创建一个  docker0  虚拟网桥,实际上是Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。

    同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给  docker0  接口。比如  172.17.0.1  ,掩码为255.255.0.0  。此后启动的容器内的网口也会自动分配一个同一网段( 172.17.0.0/16  )的地址。

    当创建一个 Docker 容器的时候,同时会创建了一对  veth pair  接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即  eth0  ;另一端在本地并被挂载到  docker0  网桥,名称以  veth  开头。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。


二、容器访问控制

    容器的访问控制,主要通过 Linux 上的  iptables  防火墙来进行管理和实现。


    

    容器访问外部网络

    容器要想访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开。

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

    0 为关闭,1 为打开。

    手动打开命令:

sysctl -w net.ipv4.ip_forward=1

    或者将 net.ipv4.ip_forward=1 写入 /etc/sysctl.conf文件。

    如果在启动 Docker 服务的时候设定  --ip-forward=true  , Docker 就会自动设定系统的  net.ipv4.ip_forward=1。



    容器之间访问

    容器之间相互访问,需要两方面的支持:

    1)容器的网络拓扑是否已经互联。默认情况下,所有容器都会被连接到docker0  网桥上。

    2)本地系统的防火墙软件 iptables  是否允许通过。



    访问所有端口

    当启动 Docker 服务时候,默认会添加一条转发策略到 iptables 的 FORWARD 链上。策略为通过( ACCEPT  )还是禁止( DROP  ),取决于配置 --icc=true (缺省值)还是  --icc=false  。如果手动指定  --iptables=false  则不会添加  iptables  规则。

    默认情况下,不同容器之间是允许网络互通的。如果为了安全考虑,可以在/etc/docker/daemon.json  文件中配置  --icc=false  来禁止它。

}
  "icc" : false
}


    

    访问指定端口

    通过  --icc=false  关闭网络访问后,还可以通过  --link CONTAINER_NAME:ALIAS  选项来访问容器的开放端口。

    --link CONTAINER_NAME:ALIAS  中的  CONTAINER_NAME  目前必须是Docker 分配的名字,或使用  --name  参数指定的名字。否则主机名不会被识别。ALIAS 是这个连接的别名。


    启动容器( docker run  )时使用  --link CONTAINER_NAME:ALIAS  选项。Docker 会在  iptables  中为 两个容器分别添加一条  ACCEPT  规则,允许相互访问开放的端口(取决于  Dockerfile  中的  EXPOSE  指令)。



三、端口映射

    映射容器端口到宿主主机。

    默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。


    

    容器访问外部实现

    容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址。这是使用iptables  的源地址伪装操作实现的。

    iptables的NAT规则:

$ iptables -t nat -nL
.........
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           
..........

    上述规则将所有源地址在  172.17.0.0/16  网段,目标地址为其他网段(外部网络)的流量动态伪装为从系统网卡发出。MASQUERADE 跟传统 SNAT的好处是它能动态从网卡获取地址。



    外部访问容器实现

    容器允许外部访问,可以在  docker run  时候通过  -p  或  -P  参数来启用。不管用那种办法,其实也是在本地的  iptables  的 nat 表中添加相应的规则。

    使用  -P  时的NAT规则:

$ docker run -d -P training/webapp python app.py
cb72fa6378eea599adf00216ab690ede28df80e57cb34ea0b0eb030ab4fe2f00

$ iptables -t nat -L -n
..........       
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32769 to:172.17.0.3:5000


    使用 -p 时的NAT规则:

$ docker run -d -p 8088:5000 training/webapp python app.py
51a6990bc2100f56f7eaaaabcb75da1ba7b1caeba2de014869744cc59246a5ed

$ iptables -t nat -L -n
...........
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8088 to:172.17.0.4:5000


    这里的规则映射了  0.0.0.0  ,意味着将接受主机来自所有接口的流量。用户可以通过 -p IP:host_port:container_port  或  -p IP::port  来指定允许访问容器的主机上的 IP、接口等,以制定更严格的规则。


    如果希望永久绑定到某个固定的 IP 地址,可以在 Docker 配置文件/etc/docker/daemon.json  中添加如下内容。

{
  "ip" : "ip地址"
}




四、配置docker0网桥

    Docker 服务默认会创建一个  docker0  网桥(其上有一个  docker0  内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

    Docker 默认指定了  docker0  接口的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。

    --bip=CIDR  IP 地址加掩码格式,例如 192.168.1.5/24

    --mtu=BYTES  覆盖默认的 Docker mtu 配置


    也可以在配置文件/etc/docker/daemon.json中配置 DOCKER_OPTS,然后重启Docker服务。



    Docker 网桥是 Linux 网桥,用户可以使用  brctl show  来查看网桥和端口连接信息。

    brctl命令通过 yum install -y bridge-utils下载。

$ brctl show
bridge name	bridge id		STP enabled	interfaces
br-401127e63686		8000.0242d069107e	no		
docker0		8000.0242e084168f	no		veth363c4a9
							veth478d0a1
							vethc3d6797

    每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0 端口。使用本地主机上  docker0  接口的 IP 作为所有容器的默认网关。



五、自定义网桥

    除了默认的  docker0  网桥,用户也可以指定网桥来连接各个容器。

    在启动 Docker 服务的时候,使用  -b BRIDGE  或 --bridge=BRIDGE  来指定使用的网桥。

    如果服务已经运行,那需要先停止Docker服务,并删除旧的网桥。

systemctl stop docker
ip link set dev docker0 down
brctl delbr docker0


    创建新网桥  bridge0:

brctl addbr bridge0
ip addr add 192.168.1.1/24 dev bridge0
ip link set dev bridge0 up
ip add show bridge0


    配置文件  /etc/docker/daemon.json  中添加如下内容,将Docker 默认桥接到创建的网桥上。

{
  "bridge": "bridge0"
}

    启动Docker服务。

    新建一个容器,看它是否已经桥接到了  bridge0  上。

    用  brctl show  命令查看桥接的信息。

    在容器中可以使用  ip addr  和  ip route  命令来查看 IP 地址配置和路由信息。



六、容器里编辑网络配置文件

    Docker 1.2.0 开始支持在运行中的容器里编辑  /etc/hosts  ,  /etc/hostname和  /etc/resolv.conf  文件。

    但是这些修改是临时的,只在运行的容器中保留,容器终止或重启后并不会被保存下来,也不会被  docker commit  提交。




点赞
说说你的看法

所有评论: (0)