一、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中容器网络模型十分简洁,可以让上层使用网络的应用容器最大程度上不去关心底层实现。网络模型的结构如下所示:
(1)模型中的三种元素
1)Sandbox(沙盒):代表一个容器(容器的网络命名空间)
2)Endpint:代表网络上可以挂在容器的网络接口,会分配IP地址
3)Network:可以连通多个接入点的一个子网
(2)网络模型支持的驱动的类型
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…]