docker中网络的使用

一、docker网络

1、docker网络原理

         Docker本地网络创建是利用了linux系统上的网络命名空间和虚拟网络设备,在本地主机和容器你分别创建一个虚拟接口,并让他们彼此连通。

2、docker网络创建过程

(1)创建一对虚拟接口,分别放到本地主机和新容器的命名空间中

(2)本地主机的一段连接到默认的docker0桥上,并修改为以veth开头的名字,容器一端的放到容器中并修改名称为eth0

(3)从网桥可用地址段中获取一个空闲地址分配给容器的eth0,并配置默认的网关为docker0网卡的内部接口docker0的IP地址。

# 创建一个不带网络的容器
]# docker run --name n1 --net=none -it -d busybox 
]# docker exec -it n1 ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B) 
# 在本地查找容器的进程ip,并为容器创建网络命名空间
]# docker inspect -f '{{.State.Pid}}' n1
7381
]# pid=7381
]# mkdir -p /var/run/netns
]# ln -s /proc/$pid/ns/net /var/run/netns/$pid
# 检查桥接网卡的信息
]# ip addr show docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:97:3e:f3:ad brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.1/16 brd 10.0.255.255 scope global docker0
       valid_lft forever preferred_lft forever
# 创建一对“veth pair”接口A和接口B绑定A接口到网桥docker0并启用
]# ip link add A type veth peer name B
]# brctl addif docker0 A
]# ip link set A up
# 将接口B放到容器的网络命名空间,命名为eth0启用并配置IP地址
]# ip link set B netns $pid
]# ip netns exec $pid ip link set dev B name eth0
]# ip netns exec $pid ip link set eth0 up
]# ip netns exec $pid ip addr add 10.0.0.100/16 dev eth0
]# ip netns exec $pid ip route add default via 10.0.0.1
# 查看容器内的网络
]# docker exec -it n1 ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 32:B3:BF:24:BD:81  
          inet addr:10.0.0.100  Bcast:0.0.0.0  Mask:255.255.0.0

3、创建容器时指定容器网络配置

   在使用”docker run”命令创建容器的过程中,可以通过”--net”参数来指定容器的网络配置:

(1)--net-bridge:默认值,在docker网桥docker0为容器创建新的网络栈

(2)--net-none:创建容器时,不创建网络,之后,用户可以自行进行配置。

(3)--net-container:NAME_or_ID:将新建容器的进程放到一个已存在的网络容器栈中

(4)--net=host:让创建的容器使用本地主机的网络

(5)--net=user_defined_network:使用用户自定义网络

# 创建容器时使用本地网络
]# docker run --name n2 --net=host -it -d  busybox
]# docker exec -it n2 ifconfig ens33
ens33     Link encap:Ethernet  HWaddr 00:0C:29:1D:3E:4D  
          inet addr:192.168.16.160  Bcast:192.168.16.255  Mask:255.255.255.0

4、创建容器时的更多网络配置

(1)以下选项只有在docker服务启动时指定

         -b BRIDGE或—bridge=BRIDGE:指定容器挂载的网桥

         --bip=CIDR:指定docker0的掩码

         -H SOCKET或—host=SOCKET:docker服务端接收命令的通道

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

         --ip-forward=true|false:启用net.ipv4.ip_forward,打开转发功能

         --iptables=true|false:禁止docker添加iptables规则

网络的一些相关配置也可以配置在配置文件/etc/docker/daemon.json中,配置如下

{
  "bip": "192.168.1.5/24",
  "fixed-cidr": "192.168.1.5/25",
  "fixed-cidr-v6": "2001:db8::/64",
  "mtu": 1500,
  "default-gateway": "10.20.1.1",
  "default-gateway-v6": "2001:db8:abcd::89",
  "dns": ["10.20.1.2","10.20.1.3"]
}

(2)dns的配置也可在创建容器及启动容器时配置

         1)--dns=IPADDRESS:使用指定的dns服务器

         2)--dns-search=DOMAIN:指定dns搜索域

         容器中的DNS和主机名配置都是通过宿主机的三个系统配置文件/etc/resolv.conf,/etc/hostname,/etc/hosts来维护,在启动容器时,这三个文件都会被挂在到容器中的对应位置,/etc/resolv.conf中的内容回和宿主机该文件内容保持一致,而/etc/hosts文件中默认只记录了容器自身的一些地址和名称。Docker1.2开始可以直接编辑这三个文件,但修改只是临时的。

(3)在启动容器时可以使用的选项:

         -h HOSTNAME(--hostname=HOSTNAME):配置容器的主机名

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

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

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

二、容器访问控制

1、容器访问外部网络的实现

         容器访问外部网络时需要打开宿主机的网络转发功能。在没有打开时,需要打开,否则容器无法访问外部网络。

# 查看网络转发功能是否打开,值等于0时表示没有打开
]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
# 打开网络转发功能
]# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

         容器访问外部网络时则会进行源地址转化(在创建容器时,默认会在iptables中添加规则),以实现容器访问外部网络。

# IPTABLES的转发规则
]# iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 449 packets, 33898 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    5   345 MASQUERADE  all  --  *      !docker0  10.0.0.0/16          0.0.0.0/0  

2、容器之间的互相访问

         容器之间的访问需要容器之间的网络拓扑连通的情况下本地系统的iptables允许访问时,各容器之间才能互相访问。

3、外部网络访问容器的实现

         让外部网络访问容器,在启动容器时通过”-P”或者”-p”参数将容器内的端口映射到宿主机上,再通过宿主机的IP加端口去访问;其实也是对访问的外部的IP地址进行了目的地址转化。

]# docker run --name web1 -p 80:80 -d busybox /bin/httpd -f
]# iptables -t nat -vnL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    5   345 MASQUERADE  all  --  *      !docker0  10.0.0.0/16          0.0.0.0/0           
    0     0 MASQUERADE  tcp  --  *      *       10.0.0.2             10.0.0.2             tcp dpt:80

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:10.0.0.2:80

三、docker网络应用

1、使用自定义的网桥

         创建容器时在不指定网络的情况下默认通过docker0网桥来桥接的,如果不想使用docker0网桥桥接也可通过自己创建的网桥来桥接。

# 创建一个网桥
]# docker network create --driver bridge test-net
b66df5a40b4984ccb41efcb389c8772ae5e1abe5b2be8a48461b38298d6823e1
# 查看创建的网桥的配置信息
]# docker inspect network test-net
[
    {
        "Name": "test-net",
        "Id": "b66df5a40b4984ccb41efcb389c8772ae5e1abe5b2be8a48461b38298d6823e1",
        "Created": "2018-12-18T22:41:42.30515433-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
……
# 创建一个容器指定网络为test-net
]# docker run -it --name t1 --network test-net busybox /bin/sh
/ # ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0

2、使用OpenvSwitch网桥

         Docker默认使用的是linux自带的网桥,同时,docker也可以使用openvswitch实现网络功能

(1)安装openvswitch

# 安装openvswitch
]# yum install openvswitch
# 添加网桥
]# ovs-vsctl add-br br0
]# ovs-vsctl show
04ab1358-e6d4-4712-a89e-e49d175362f3
    Bridge "br0"
        Port "br0"
            Interface "br0"
                type: internal
ovs_version: "2.0.0"

(2)配置容器连接到openvswitch网桥

# 创建不带网络功能的容器
]# docker run -it -exec -d --name o1 --net=none busybox 
743a5cc99fc20b00cf719aee81ea18f3ae5583124e586a2f8d7c9d14e44659d6
# 下载openvswitch提供的辅助脚本,并赋予执行权限(脚本地址为https://github.com/openvswitch/ovs/blob/master/utilities/ovs-docker)
]# chmod a+x ovs-docker
# 为容器添加网卡,并挂在到br0上
]# ./ovs-docker add-port br0 eht0 o1 --ipaddress=192.168.0.2/16
]# docker exec -it o1 ifconfig
eht0      Link encap:Ethernet  HWaddr 3E:E4:8F:74:7B:38  
          inet addr:192.168.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
# 为网桥br0添加IP地址
]# ifconfig br0 192.168.0.1/16

3、实现两个容器之间点到点的连接

         有时需要两个容器之间可以直接连接通信,不需要通过主机网桥进行桥接,此时可以创建一对peer接口,分别放到两个容器接口中,配置成点到点链路即可。

# 创建两个没有网络的容器
]# docker run -it --name p1 -d --net=none busybox
0d8d5dcdf28cfeddc97a9c13a8d3609f18aad9527927007a5cb00447b96e3117
]# docker run -it --name p2 -d --net=none busybox
a035e11b33a45dffa3ebd922ea24777c51713412fe7816cfd0d0aacb65e5bc94
# 找到进程号,创建网络名称空间的的追踪文件
]# docker inspect -f {{.State.Pid}} 0d8d5dcdf28c
12823
]# docker inspect -f {{.State.Pid}} a035e11b33a4
12897
]# mkdir /var/run/netns
]# ln -s /proc/12823/ns/net /var/run/netns/12823
]# ln -s /proc/12897/ns/net /var/run/netns/12897
# 创建一对peer接口C和D
]# ip link add C type veth peer name D
# 为两个接口分别添加IP地址及路由信息
]# ip link set C netns 12823
]# ip netns exec 12823 ip addr add 1.1.1.1/32 dev C
]# ip netns exec 12823 ip link set C up
]# ip netns exec 12823 ip route add 1.1.1.2/32 dev C
]# ip link set D netns 12897
]# ip netns exec 12897 ip addr add 1.1.1.2/32 dev D
]# ip netns exec 12897 ip link set D up
]# ip netns exec 12897 ip route add 1.1.1.1/32 dev D

四、docker网络命令的使用

1、插件化网络

         Docker从1.7.0版本开始把网络和存储的功能实现都已插化形式剥离出来,允许用户通过指令来选择不同的后端实现;剥离出来的独立容器的网络项目叫做libnetwork。

2、容器的网络模型

         Libnetwork中容器网络模型(CNM)十分简洁,可以让上层使用网络的应用容器最大程度上不去关心底层实现。网络模型的结构如下所示:

(1)模型中的三种元素

         1)Sandbox(沙盒):代表一个容器(容器的网络命名空间)

         2)Endpint:代表网络上可以挂在容器的网络接口,会分配IP地址

         3)Network:可以连通多个接入点的一个子网

(2)网络模型CNM支持的驱动的类型

         1)Null:不提供网络服务,容器启动后无网络接入

         2)Bridge:Docker传统上默认用linux网桥和iptables实现的单机网络

         3)Overlay:用vxlan隧道实现的跨主机容器网络

         4)Remote:扩展类型,预留给其他外部实现的方案

3、docker网络相关命令

(1)常用的网络命令

         使用”docker network  --help”查看有如下的网络命令:

]# docker network --help
Usage:    docker network COMMAND
Manage networks
Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks    
(2)创建网络

         命令:docker network create [OPTIONS] NETWORK

         支持的选项(可通过docker network create –help查看):    

                   --aux-address:辅助IP地址    

                   --driver string(-d):网络驱动类型    

                   --gateway:网关地址    

                   --internal:禁止外部对创建网络的访问         

                   --ip-range:分配IP地址范围

                   --ipam-driver:IP地址管理的插件类型

                   --ipam-opt:ip地址管理插件的选项           

                   --label:为网络添加元标签信息       

                   --opt:网络驱动支持的选项 

                  --subnet:网络地址段

(3)删除网络

         命令:docker network rm NETWORK [NETWORK…]

         删除指定的网络时,只有当网络上不存在接入点时才能删除成功。

(4)接入容器

         接入容器是将容器连接到一个已存在的网络上

         命令:docker network connect [OPTIONS] NETWORK CONTAINER

         主要选项(可”docker network connect –help”命令查看):

                   --alias strings:为容器添加一个别名,此别名仅在所添加网络上可见       

                   --ip string:指定IP地址           

                   --ip6 string:指定ipv6地址          

                   --link list:添加连接到另外一个容器           

                   --link-local-ip strings:为容器添加一个连接地址

(5)删除容器网络

         将一个连接到网络上的容器从网络上删除

         命令:docker network disconnect [OPTIONS] NETWORK CONTAINER

(6)查看网络信息

         命令:docker network inspect [OPTIONS] NETWORK [NETWORK…]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章