docker 网络

1. 启动配置参数

1.1 网络启动过程

    Docker服务启动时会首先在主机上自动创建一个 dockerO虚拟网桥,实际上是一个Linux 网桥。

    同时, Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0接口。

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

1.2 参数

-b BRIDGE or --bridge=BRIDGE: 指定容器挂载的网桥;

--bip=CIDR: 定制docker0 的掩码;

-H SOCKET... or --host=SOCKET...; Docker 服务端接收命令的通道;

--icc=true I false : 是否支持容器之间进行通信;

--ip-forward=true I false: 启用net.ipv4.ip _forward, 即打开转发功能;

--iptables=true I false : 禁止Docker 添加 iptables 规则;

--mtu=BYTES: 容器网络中的 MTU

      命令选项既可以在启动服务时指定, 也可以 Docker 容器启动(使用 docker [ container] run 命令)时候指定。在 Docker 服务启动的时候指定则会成为默认值, 后续执行该命 令时可以覆盖设置的默认值

--dns=IP_ADDRESS: 使用指定的 DNS 服务器;

--dns-opt= " ":指定 DNS 选项;

--dns-search=DOMAIN: 指定DNS搜索域

    在 docker [con七ainer] run 命令执行时使用, 因为它针对容器的配置:

-h HOSTNAME or --hostname=HOSTNAME:配置容器主机名

-ip=" ": 指定容器内接口的ip地址;

--link=CPNTAINER_NAME:ALIAS: 添加到另外一个容器的连接;

--net=bridge | none | con七ainer:NAME_or_ID | host | user_defined_network: 配置容器的桥接模式;

--network-alias: 容器在网络中的别名;

-p SPEC or --publish=SPEC: 映射容器端口到宿主主机

 -P or --publish-all=true | false: 映射容器所有端口到宿主主机。

    net的支持模式

--net=bridge: 默认配置.为容器创建独立的网络命名空间,分配网卡、IP 地址等网络配置, 并通过veth接口对将容器挂载到一个虚拟网桥(默认为 docker0) 上;

--net=none: 为容器创建独立的网络命名空间,但不进行网络配置,即容器内没有创建网卡,IP地址等;

 --net=container:NAME—or_ID: 新创建的容器共享指定的已存在容器的网络命名空间, 两个容器内的网络配置共享, 但其他资源(如进程空间、 文件系统等)还是相互隔离的;

--net=host:不为容器创建独立的网络命名空间, 容器内看到的网络配置(网卡信息路由表 Iptables 规则等)均与主机上的保持一致 注意其他资源还是与主机隔离的;

--net=user_defined_network: 用户自行用network相关命令创建一个网络,同一个网络内的容器彼此可见,可以采用更多类型的网络插件

2. 配置容器DNS和主机名

    Docker 服务启动后会默认启用一个内嵌的DNS服务,来自动解析同一个网络中的容器主机名和地址,如果无法解析,则通过容器内的DNS相关配置进行解析,用户可以通过命令选项自定义容器的主机名和DNS配置

    2.1 配置文件 

    容器中主机名和DNS配置信息通过三个系统配置文件来管理

/etc/resolv.conf
/etc/hostname
/etc/hosts

    启动容器,在配置中使用monut命令可以看到这三个文件挂载信息;

[root@kubernetes ~]# docker run -it --rm ubuntu
root@2334d56d6268:/# mount

    启动容器时,会从宿主机上复制/etc/resolv.conf

root@2334d56d6268:/# cat /etc/resolv.conf

    /etc/hosts文件中默认只记录了容器自身的地址和名称

root@2334d56d6268:/# cat /etc/hosts 
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	2334d56d6268

    /etc/hostname文件则记录了容器的主机名

root@2334d56d6268:/# cat /etc/hostname 
2334d56d6268

2.2 容器内修改配置

    容器运行时,可以在运行中的容器里直接编辑/etc/hosts,/etc/hostname和/etc/resolve.conf文件,这些修改都是临时的,只是在运行的容器中保留,容器终止或重启后并不会被保存下来,也不会被docker commit 提交。

2.3 通过参数指定

    想自定义容器的配置,可以在创建或启动容器时利用参数指定,注意不与-net=host一起使用,会破坏宿主机上的配置信息:

指定主机名 -h HOSTNAME 或者 --hostname=HOSTNAME: 设定容器的主机名容器主机名会被写到容器内的/etc/hostname和/etc/hosts 但这个主机名只有容器内中能看到,在容器外部则看不到,既不会在docker ps 中显示,也不会在其他容器的/etc/hosts中看到;

--link=CONTAINER_NAME:ALIAS:记录其他容器主机名.在创建容器的时候,添加一个所连接容器的主机名到容器内/etc/hosts 文件中 这样,新建容器可以直接使用主机名与所连接容器通信;

 --dns=IP_ADDRESS:指定DNS服务器。添加DNS服务器到容器的/etc/resolv.conf 中,容器会用指定的服务器来解析所有不在/etc/hosts中的主机名;

--dns-option list:指定 DNS 相关的选项;

--dns-search=DOMAIN :指定DNS搜索域。设定容器的搜索域,当设定搜索域为.example.com时,在搜索一个名为host的主机时,DNS不仅搜索host,还会搜索host.example .com

3. 容器访问控制

3.1 容器访问外部网络

    容器默认情况下可以访问到宿主 机本地网络 如果容器要想通过宿主机访问到外部网络,则需要宿主机进行辅助转发。

    检查转发是否打开:

[root@kubernetes ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

若为0,说明没有开启转发,则需要手动打开

sysctl -w net.ipv4.ip_forward=1

Docker 服务启动时会默认开启--ip-forward=true,自动配置宿主机系统的转发规则。

3.2 容器之间访问

网络拓扑是否已经连通。默认情况下,所有容器都会连接到docker0网桥上,这意味着默认情况下拓扑是互通的;

本地系统的防火墙软件 iptables 是否允许访问通过 这取决于防火墙的默认规则许(大部分情况)还是禁止

(1)访问所有端口

    启动docker服务时候,默认会添加一条"允许"转发策略到iptables的FORWARD 链上,通过配置--icc=true|false(默认为true) 参数可以控制默认的策略

    docker 配置文件中配置DOCKER_OPTS= --ice=false来默认禁止容器之间的相互访问。

    启动docker时手动指定--iptables=false参数,则不会修改宿主机系统上的iptables规则。

(2)访问指定端口

        在通过-ice=false禁止容器间相互访问后,仍可以通过--link=CONTAINER_NAME:ALIAS选项来允许指定容器的开放端口。

    启动docker服务时,

          启动docker时,可以同时使用ice=false --iptables=true参数来配置容器间禁止访问,并允许docker自动修改系统中的iptables规则。测试系统中的iptables规则可能是类似如下规则,禁止转发流量

iptables -nL

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

--link=CONTAINER_NAME:ALIAS 中的 CONTAINER_NAME 目前必须是 Docker 自动分配的容器名,或使用--name 参数指定的名字. 不能为容器-h 参数配置的主机名

4. 映射容器端口到宿主主机的实现

4.1 容器访问外部实现

    容器内部的网络地址为 172.17.0.2 ,本地网络地址为 10.0 2.2 。容器要能访问外部网络,源地址不能为 172.17.0.2 ,需要进行源地址映射( Source NAT, SNAT ),修改为本地系统 IP 地址 10.0.2.2

    映射是通过 iptables 的源地址伪装操作实现的。查看主机 nat 表上 POSTROUTING 链的 规则 。该链负责网包要离开主机前,改写其源地址:

iptables -t nat -nvL POSTROUTING

规则将所有源地址在 172 .1 .0.0/16 网段,且不是从 dock rO 接口发出的流量 即从容器中 来的流量),动态伪装为从系统网卡发出 MASQUERADE 行动与传统 SNAT 行动相比,好处是能动态地从网卡获取地址

4.2 外部访问容器

    容器允许外部访问,可以在docker [container] run时候通过-p 或 -P参数来启用。

    在本地添加iptables的nat表中添加相应规则    

规则映射地址为0.0.0.0,意味着将接受主机来自所有网络接口上的流量。用户可以通过-p IP:host_port:container_port 或-p IP:port 来指定绑定的外部网络接口,以指定更严格的访问规则

如果希望映射绑定到某个固定的宿主机IP地址,可以在Docker配置文件中指定DOCKER_OPTS="--ip=IP_ADDRESS",之后重启Docker服务即可生效

5. 配置容器网桥

    Docker 会默认创建一个docker0的Linux网桥(其上有一个docker0 内部接口),在内核层连通了其他的物理或虚拟网卡,将所有容器和本地主机都放在同一个物理网络。用户使用docker创建多个自定义网络时可能出现多个容器网桥。

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

--bip=CIDR: IP地址加掩码格式

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

    在配置文件中配置DOCKER_OPTS,重启服务docker网桥是Linux网桥,可以通过brctl show来查看网桥和端口信息

[root@kubernetes ~]# brctl show 
bridge name	bridge id		STP enabled	interfaces
docker0		8000.024226291d89	no		vetha462a72
 yum install bridge-utils

apt-get install bridge-utils

    创建容器时,docker从可用的地址段选择空闲的ip地址分配给容器的eth0端口,使本地主机上的docker0接口的IP 作为容器的默认网关

[root@kubernetes /usr/local/nginx]# docker run -it --rm centos bash
[root@e188e00fe279 /]# ip addr show eth0
560: eth0@if561:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@e188e00fe279 /]# ip route
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3 

6. 自定义网桥

    除了默认的docker0网桥,还可以指定其他网桥来连接各个容器,在启动docker服务时,可使用-b BRIDGE或--bridge=BRIDGE指定网桥

    先停止服务,删除旧网桥

systemctl stop docker

ip link set dev docker0 down

brctl delbr docker0

创建网桥

brctl addbr bridge0

ip addr add 192.168.5.1/24 dev bridge0

ip link set dev bridge0 up

查看确认网桥启动

ip addr show bridge0

配置服务,默认桥接到创建的网桥上:

echo 'DOCKER_OPTS"="-b=bridge0"' >> /etc/default/docker

systemctl start docker

    启动一个容器,查看是否桥接到bridge0上。

    可使用brctl show查看桥接的信息。在容器中可以使用ip addr和ip route命令查看ip地址配置和路由信息

 

你可能感兴趣的:(docker,网络)