一、前言Docker网络
1、单 Docker Host 容器通信网络方案
none、host、bridge 和 joined 容器
2、跨主机容器间通信网络方案
A、Docker 原生 Network 的 overlay 和 macvlan
B、第三方方案常用的有 flannel、weave 和 calico
N方案如何与 Docker 集成?
利用: libnetwork 以及 CNM
2.1、libnetwork & CNM
libnetwork 是 Docker 容器网络库
Container Network Model (CNM)是libnetwork的核心,对容器网络抽象化,由以下三类组件组成:
Sandbox
Sandbox 是容器的网络栈,包含容器的 interface、路由表和 DNS 设置
Linux Network Namespace 是 Sandbox 的标准实现
Sandbox 可以包含来自不同 Network 的 Endpoint
Endpoint
Endpoint 作用是将 Sandbox 接入 Network
Endpoint 典型实现是 veth pair
1个 Endpoint 只能属于一个网络,且只能属于一个 Sandbox
Network
Network 包含一组 Endpoint
同1个 Network 的 Endpoint 可直接通信
Network 的实现可以是 Linux Bridge、VLAN 等
CNM 示例:
如上图所示:
2个容器,1个容器1个 Sandbox,每个 Sandbox 都有1个 Endpoint 连接到 Network 1,第2个 Sandbox 还有1个 Endpoint 是接入到了 Network 2
libnetwork CNM 定义了 Docker Container的网络模型,按照该模型开发出的 driver 能与 docker daemon 协同工作,实现Container Network
Docker 原生的 driver 包括 none、bridge、overlay 和 macvlan
第三方 driver 包括 flannel、weave、calico 等
二、Docker Overlay Network 环境
Docker 提供了 overlay driver,可创建基于 VxLAN 的 overlay 网络
VxLAN 将二层数据封装到 UDP 进行传输,VxLAN 提供与 VLAN 相同的以太网二层服务,并且拥有更强的扩展性和灵活性
什么是overlay网络
overlay网络用于连接不同机器上的docker容器,允许不同机器上的容器相互通信,同时支持对消息进行加密,当我们初始化一个swarm或是加入到一个swarm中时,在docker主机上会出现两种网络:
第一种、称为ingress的overlay网络
用于传递集群服务的控制或是数据消息,若在创建swarm服务时没有指定连接用户自定义的overlay网络,将会加入到默认的ingress网络
第二种、名为docker_gwbridge桥接网络
docker_gwbridge桥接网络会连接swarm中所有独立的docker系统进程
可以使用docker network create创建自定义的overlay网络,容器以及服务可以加入多个网络,只有同一网络中的容器可以相互交换信息,可以将单一容器或是swarm服务连接到overlay网络中,但是两者在overlay网络中的行为会有所不同,接下来会描述两者在overlay网络中的共同行为以及不同行为
注意事项:
如果想要连接到overlay网络,请确保连接前下列端口没有服务,并且服务器防火墙要允许下列端口通过:
TCP端口2377,用于集群管理信息的交流
TCP、UDP端口7946用于集群中节点的交流
UDP端口4789用于overlay网络中数据报的发送与接收
1、搭配key-value 数据库
Docerk overlay 网络需要1个 key-value 数据库来保存网络状态信息,包括 Network、Endpoint、IP 等
Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件,此处使用 Consul
2、环境描述
使用docker-machine 创建的实验环境
- 跨主机的2台Docker 主机
Docker 主机 host02(192.168.233.144)和 host03(192.168.233.145)上实践各种跨主机网络方案
B、部署组件
主机 docker-centos (192.168.233.143) 上部署支持的组件,如: Consul
简单方式--容器方式运行 Consul
Consul可以用来实现分布式系统的服务发现与配置,它是HashiCorp公司推出的一款实用开源工具,支持Linux等平台。Consul是分布式的、高可用的、可横向扩展的。
Consul具备的特性:
服务发现: Consul提供了通过DNS或者HTTP接口的方式来注册服务和发现服务。一些外部的服务通过Consul很容易的找到它所依赖的服务。
健康检测: Consul的Client提供了健康检查的机制,可以通过用来避免流量被转发到有故障的服务上。
Key/Value存储: 应用程序可以根据自己的需要使用Consul提供的Key/Value存储。Consul提供了简单易用的HTTP接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。
多数据中心: Consul支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。
执行指令:
docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap
docker run -d \
--restart="always" \
-p="8500:8500" \
-hostname="consul" \
--name="consul" \
progrium/consul -server -bootstrap
访问 Consul:
http://192.168.233.143:8500
C、修改 docker daemon 配置文件
host02 和 host03 配置文件
cat /etc/systemd/system/docker.service.d/10-machine.conf
实际内容:Docker version 19.03.11
vi /etc/systemd/system/docker.service.d/10-machine.conf
追加
--cluster-store=consul://192.168.233.143:8500 --cluster-advertise=ens33:2376
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --storage-driver overlay2 --tlsverify --tlscacert /etc/docker/ca.pem --tlscert /etc/docker/server.pem --tlskey /etc/docker/server-key.pem --label provider=generic --cluster-store=consul://192.168.233.143:8500 --cluster-advertise=ens33:2376
配置解析:
--cluster-store 指定 consul 的地址
--cluster-advertise 告知 consul 自己的连接地址
D、重启 docker daemon
systemctl status docker.service
systemctl daemon-reload
systemctl restart docker.service
systemctl status docker.service
E、观察结果
host02 和 host03 将自动注册到 Consul 数据库中
三、创建 overlay 网络
1、在 host02 服务器上创建 overlay 网络 overlay_net01
docker network create -d overlay overlay_net01
-d overlay 指定 driver 为 overlay
2、host03上查看当前网络
docker network ls
原理解释:
host03 上也能看到 overlay_net01,因为创建 overlay_net01 时 host02 将 overlay 网络信息存入了 consul,host03 从 consul 读取到了新网络的数据。之后 overlay_net01 的任何变化都会同步到 host02 和 host3
3、查看 overlay_net01 的详细信息
docker network inspect overlay_net01
docker network inspect overlay_net01
[
{
"Name": "overlay_net01",
"Id": "9ebb22fd5d745f1c8715032c4e76053603c31045accbddf1308d2444b89c259a",
"Created": "2020-06-16T16:53:00.071749316+08:00",
"Scope": "global",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
IPAM 是指 IP Address Management,docker 自动为 overlay_net01 分配的 IP 空间为 10.0.0.0/24
四、在 overlay 中运行容器
1、在host02上,运行1个 busybox 容器并连接到 overlay_net01
docker run -itd --name busybox-01 --network overlay_net01 busybox
2、查看容器网络配置
docker exec busybox-01 ip r
busybox-01 有两个网络接口 eth0 和 eth1
eth0 IP 为 10.0.0.2,连接的是 overlay 网络 overlay_net01
eth1 IP 172.17.0.2,容器的默认路由是走 eth1,eth1 是哪儿来的呢?
其实,docker 会创建一个 bridge 网络 “docker_gwbridge”,为所有连接到 overlay 网络的容器提供访问外网的能力
3、查看 docker_gwbridge 详情信息
docker network inspect docker_gwbridge
docker network inspect docker_gwbridge
[
{
"Name": "docker_gwbridge",
"Id": "192f1d193f83f81c836842b0a339e5097e04aaf3341c2f7909d913335ac194dc",
"Created": "2020-06-16T17:23:20.698017508+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"42fbbcdeacd351701163986bc920f5e70af72f8d72d9d4d36817d8120c3a90f5": {
"Name": "gateway_297bdad64327",
"EndpointID": "adf1f97c040f78792e0ea94db272ddfccc276e5ec77e6f891a1d639a423d8997",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.enable_icc": "false",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.name": "docker_gwbridge"
},
"Labels": {}
}
]
IP 地址范围是 172.18.0.0/16,当前连接的容器就是 busybox-01 (172.18.0.2)
172.18.0.0/16网络的网关就是网桥 docker_gwbridge 的 IP 172.18.0.1
ifconfig docker_gwbridge
4、验证与外网的连通性
A、访问外网
容器 busybox-01 就可通过 docker_gwbridge 访问外网
docker exec busybox-01 ping -c 3 www.baidu.com
B、外网访问容器
如果外网要访问容器,可通过主机端口映射,比如:
docker run -p 80:80 -d --net overlay_net01 --name web1 httpd
五、overlay 实现跨主机通信--连通性
1、在 host03 中运行容器 busybox-02
docker run -itd --name busybox-02 --network overlay_net01 busybox
docker exec busybox-02 ip r
【问题记录】创建容器时,报:docker: Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on 144.144.144.144:53: read udp 192.168.233.149:41512->144.144.144.144:53: i/o timeout.
【解决方法】vi /etc/docker/daemon.json
{
"registry-mirrors":["https://49c47s26.mirror.aliyuncs.com"]
}
systemctl restart docker
2、host03上的busybox-02与host02上的busybox-01网络
busybox-02 IP 为 10.0.0.4,可以直接 ping busybox-01
docker exec busybox-02 ping -c 3 busybox-01
docker exec busybox-02 ping -c 3 10.0.0.2
overlay 网络中的容器可以直接通信,同时 docker 也实现了 DNS 服务
3、overlay 网络的具体实现
docker 会为每个 overlay 网络创建一个独立的 network namespace,其中会有一个 Linux bridge br0,endpoint 还是由 veth pair 实现,一端连接到容器中(即 eth0),另一端连接到 namespace 的 br0 上
br0 除了连接所有的 endpoint,还会连接一个 vxlan 设备,用于与其他 host 建立 vxlan tunnel。容器之间的数据就是通过这个 tunnel 通信的
4、查看 overlay 网络的 namespace
在 host02 和 host03 上执行 ip netns(请确保在此之前执行过 ln -s /var/run/docker/netns /var/run/netns),可以看到两个 host 上有一个相同的 namespace “1-9ebb22fd5d”
ln -s /var/run/docker/netns /var/run/netns
ip netns
[root@host02 ~]# ip netns
ae08955cc1c2 (id: 1)
1-9ebb22fd5d (id: 0)
[root@host03 ~]# ip netns
e5d25e449779 (id: 1)
1-9ebb22fd5d (id: 0)
5、查看 namespace 中的 br0 上的设备
这就是 overlay_net01 的 namespace
ip netns exec 1-9ebb22fd5d brctl show
可见 namespace 中的 br0 上的设备vxlan0
【问题记录】[root@host02 ~]# ip netns exec 1-9ebb22fd5d brctl show
exec of "brctl" failed: No such file or directory
【解决方法】先安装
yum install -y bridge-utils
6、查看 vxlan0 设备的具体配置信息
ip netns exec 1-9ebb22fd5d ip -d l show vxlan0
可见 overlay 使用的 VNI(VxLAN ID)为 256
vxlan0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default
link/ether 66:48:73:e2:77:52 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 1
vxlan id 256 srcport 0 0 dstport 4789 proxy l2miss l3miss ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx
bridge_slave state forwarding priority 32 cost 100 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8001 port_no 0x1 designated_port 32769 designated_cost 0 designated_bridge 8000.66:48:73:e2:77:52 designated_root 8000.66:48:73:e2:77:52 hold_timer 0.00 message_age_timer 0.00 forward_delay_timer 0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
六、overlay 的网络隔离特性
不同的 overlay 网络是相互隔离的
1、创建第二个 overlay 网络 overlay_net02 并运行容器 busybox-03
docker network create -d overlay overlay_net02
docker run -itd --name busybox-03 --network overlay_net02 busybox
docker exec -it busybox-03 ip r
busybox-03 分配到的 IP 是 10.0.1.2,尝试 ping busybox-01(10.0.0.2)
docker exec -it busybox-03 ping -c 3 10.0.0.2
可见:overlay_net02 中的 busybox-03 ping overlay_net01 中的 busybox-01 失败,可见不同 overlay 网络之间是隔离的。即便是通过 docker_gwbridge 也不能通信
2、实现 busybox-03 与 busybox-01 通信
将 busybox-03 也连接到 overlay_net01
docker network connect overlay_net01 busybox-03
尝试再次 ping busybox-03
docker exec -it busybox-03 ping -c 3 busybox-01
3、指定overlay 网络 IP 空间
overlay IPAM
docker 默认为 overlay 网络分配 24 位掩码的子网(10.0.X.0/24),所有主机共享这个 subnet,容器启动时会顺序从此空间分配 IP
--subnet 指定 IP 空间
docker network ls
docker network create -d overlay --subnet 10.10.1.0/24 overlay_net03
4、查看 overlay_net03 详情
docker network inspect overlay_net03
[root@host02 ~]# docker network inspect overlay_net03
[
{
"Name": "overlay_net03",
"Id": "beb14c4386f9f947754531c5ee53c054cbcc9a6b8f63a6d954f27db824ebf7c1",
"Created": "2020-06-21T02:31:05.632006303+08:00",
"Scope": "global",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.10.1.0/24"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
详情请见,微信公众号