21、《每天5分钟玩转Docker容器技术》学习--Flannel Network

------------------------------------重要说明------------------------------------

本文内容都是参考Cloudman系列进行学习,是个人学习过程记录,与原版不同!

原版请参考cloudman《每天5分钟玩转Docker容器技术》Cloudman博客如下:

http://blog.51cto.com/cloudman

------------------------------------重要说明------------------------------------

flannel 是 CoreOS 开发的容器网络解决方案。flannel 为每个 host 分配一个 subnet,容器从此 subnet 中分配 IP,这些 IP 可以在 host 间路由,容器间无需 NAT 和 port mapping 就可以跨主机通信。

每个 subnet 都是从一个更大的 IP 池中划分的,flannel 会在每个主机上运行一个叫 flanneld 的 agent,其职责就是从池子中分配 subnet。为了在各个主机间共享信息,flannel 用 etcd(与 consul 类似的 key-value 分布式数据库)存放网络配置、已分配的 subnet、host 的 IP 等信息。

数据包如何在主机间转发是由 backend 实现的。flannel 提供了多种 backend,最常用的有 vxlan 和 host-gw,我们将在本章讨论这两种 backend。其他 backend 请参考 https://github.com/coreos/flannel。

图片.png 

etcd 部署在 192.168.56.129【docker01】docker02 和 docker03 上运行 flanneld,首先安装配置 etcd。

a) 安装配置 etcd

在 192.168.56.129 上运行如下脚本: 

ETCD_VER=v2.3.7

DOWNLOAD_URL=https://github.com/coreos/etcd/releases/download

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz

mkdir -p /tmp/test-etcd && tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/test-etcd --strip-components=1

cp /tmp/test-etcd/etcd* /usr/local/bin/

图片.png

该脚本从 github 上下载 etcd 的可执行文件并保存到 /usr/local/bin/,启动 etcd 并打开 2379 监听端口。

etcd -listen-client-urls http://192.168.56.129:2379 -advertise-client-urls http://192.168.56.129:2379

图片.png

图片.png 

该终端不要结束,新开一个终端

测试 etcd 是否可用:

图片.png 

图片.png 

可以正常在 etcd 中存取数据了。

当前网络结构

 

b) 安装配置 flannel 

flannel 没有现成的执行文件可用,必须自己 build,最可靠的方法是在 Docker 容器中 build。不过用于做 build 的 docker 镜像托管在 gcr.io,国内可能无法直接访问,为方便大家,我把它 mirror 到了 docker hub,构建步骤如下:

1.下载并重命名 image

docker pull cloudman6/kube-cross:v1.6.2-2

docker tag cloudman6/kube-cross:v1.6.2-2 gcr.io/google_containers/kube-cross:v1.6.2-2

图片.png

2.下载 flannel 源码

git clone https://github.com/coreos/flannel.git

图片.png

图片.png

3.开始构建

cd flannel

图片.png 

make dist/flanneld-amd64

图片.png
 

4.将 flanneld 执行文件拷贝到 host1 和 host2

scp dist/flanneld-amd64 192.168.56.130:/usr/local/bin/flanneld

scp dist/flanneld-amd64 192.168.56.128:/usr/local/bin/flanneld

图片.png 

c) 将 flannel 网络的配置信息保存到 etcd

先将配置信息写到文件 flannel-config.json 中:

cat >>flannel-config.json<<EOF

{

  "Network": "10.2.0.0/16",

  "SubnetLen": 24,

  "Backend": {

    "Type": "vxlan"

  }

}

EOF

图片.png 

Network 定义该网络的 IP 池为 10.2.0.0/16。

SubnetLen 指定每个主机分配到的 subnet 大小为 24 位,即10.2.X.0/24。

Backend 为通信类型。 vxlan,即主机间通过 vxlan 通信,后面我们还会讨论host-gw。

将配置存入 etcd

etcdctl --endpoints=192.168.56.129:2379 set /docker-test/network/config < flannel-config.json

/docker-test/network/config 是此 etcd 数据的 key,其 value 为 flannel-config.json 的内容。

key 可以任意指定,这个 key 后面会作为 flanneld 的一个启动参数。执行 etcdctl get 确保设置成功。

图片.png

d) 启动 flannel

在 docker02 和 docker03 上执行如下命令,NOTE:Don’t close current terminal!

flanneld -etcd-endpoints=http://192.168.56.129:2379 -iface=ens33 -etcd-prefix=/docker-test/network

-etcd-endpoints 指定 etcd url。

-iface 指定主机间数据传输使用的 interface。

-etcd-prefix 指定 etcd 存放 flannel 网络配置信息的 key。

图片.png 

图片.png 

图片.png

① enp0s8 被选作与外部主机通信的 interface。

② 识别 flannel 网络池 10.2.0.0/16。

③ 分配的 subnet 为 10.2.40.0/24。

flanneld 启动后,docker02 docker03 内部网络会发生一些变化:

1.一个新的 interface flannel.1 被创建,而且配置上 subnet 的第一个 IP 10.2.3.0。

图片.png

图片.png 

2.docker02 docker03 添加了一条路由:目的地址为 flannel 网络 10.2.0.0/16 的数据包都由 flannel.1 转发

图片.png

图片.png 

当前环境网络拓扑如下:

图片.png
 

e) 配置 Docker 连接 flannel

cat /run/flannel/subnet.env 中 FLANNEL_SUBNET 和FLANNEL_MTU 

docker02

图片.png 

docker03

图片.png
 

编辑 docker02  docker03的 Docker 配置文件 /etc/systemd/system/docker.service.d/10-machine.conf,设置 --bip 和 --mtu

docker02

图片.png
 

docker03

图片.png 

重启 Docker daemon

systemctl daemon-reload

systemctl restart docker.service

Docker --bip配置到 Linux bridge docker0 上,并添加 10.2.xx.0/24 的路由。

docker02

图片.png 

docker03

图片.png
 

当前环境网络拓扑如图所示

图片.png
 

可见:flannel 没有创建新的 docker 网络,而是直接使用默认的 bridge 网络。同一主机的容器通过 docker0 连接,跨主机流量通过 flannel.1 转发。

f) 将容器连接到 flannel 网络

在 docker02 中运行容器 bbox1

图片.png
 

在 docker03 中运行容器 bbox2

图片.png
 

图片.png
 

图片.png 

Docker02 和 docker03 的 IP 分别为 10.2.3.2 和 10.2.98.2。

当前网络拓扑

图片.png
 

g) flannel 网络连通性

测试 bbox1 和 bbxo2 的连通性

图片.png
 

bbox1 能够 ping 到位于不同 subnet 的 bbox2通过 traceroute 分析一下 bbox1 到 bbox2 的路径。

图片.png

1.bbox1 与 bbox2 不是一个 subnet数据包发送给默认网关 10.2.98.1 docker0。

2.根据 docker02的路由表下图数据包会发给 flannel.1。

3.flannel.1 将数据包封装成 VxLAN通过 ens33 发送给 docker03

4.Docker03 收到包解封装发现数据包目的地址为 10.2.3.2根据路由表下图将数据包发送给 flannel.1并通过 docker0 到达 bbox2。

图片.png

另外flannel 是没有 DNS 服务的容器无法通过 hostname 通信。

图片.png 

h) flannel 网络隔离

flannel 为每个主机分配了独立的 subnet但 flannel.1 将这些 subnet 连接起来了相互之间可以路由。本质上flannel 将各主机上相互独立的 docker0 容器网络组成了一个互通的大网络实现了容器跨主机通信。flannel 没有提供隔离。

i) flannel 与外网连通性

因为 flannel 网络利用的是默认的 bridge 网络所以容器与外网的连通方式与 bridge 网络一样即

1.容器通过 docker0 NAT 访问外网

2.通过主机端口映射外网可以访问容器

j) 如何使用 flannel host-gw backend

flannel 支持多种 backend,前面我们讨论的是 vxlan,host-gw 是 flannel 的另一个 backend,本节会将前面的 vxlan backend 切换成 host-gw。

与 vxlan 不同,host-gw 不会封装数据包,而是在主机的路由表中创建到其他主机 subnet 的路由条目,从而实现容器跨主机通信。要使用 host-gw 首先修改 flannel 的配置 flannel-config.json:

先将配置信息写到文件 flannel-config.json 中:

cat >>flannel-config.json<<EOF

{

  "Network": "10.2.0.0/16",

  "SubnetLen": 24,

  "Backend": {

    "Type": "host-gw"

  }

}

EOF

图片.png

Type 用 host-gw 替换原先的 vxlan。更新 etcd 数据库:

etcdctl --endpoints=192.168.56.129:2379 set /docker-test/network/config < flannel-config.json

Ctrl+C 掉之前 docker02 和 docker03 的 flanneld 进程并重启。

flanneld -etcd-endpoints=http://192.168.56.129:2379 -iface=enp0s8 -etcd-prefix=/docker-test/network

docker02

图片.png 

查看 docker02 的路由表,增加了一条到 10.2.98.0/24 的路由,网关为 docker03 的 IP 192.168.56.128

图片.png

docker03

图片.png
 

查看 docker03 的路由表,增加了一条到 10.2.3.0/24 的路由,网关为 docker02 的 IP 192.168.56.130

图片.png

从 /run/flannel/subnet.env 可以看到 host-gw 使用的 MTU 为 1500

图片.png


 

这与 vxlan MTU=1450 不同,所以应该修改 docker 启动参数 --mtu=1500并重启 docker daemon。

下面对 host-gw 和 vxlan 这两种 backend 做个简单比较。

1. host-gw 把每个主机都配置成网关,主机知道其他主机的 subnet 和转发地址。vxlan 则在主机间建立隧道,不同主机的容器都在一个大的网段内(比如 10.2.0.0/16)。

2. 虽然 vxlan 与 host-gw 使用不同的机制建立主机之间连接,但对于容器则无需任何改变,bbox1 仍然可以与 bbox2 通信。

3. 由于 vxlan 需要对数据进行额外打包和拆包,性能会稍逊于 host-gw。

------------------------------------重要说明------------------------------------

本文内容都是参考Cloudman系列进行学习,是个人学习过程记录,与原版不同!

原版请参考cloudman《每天5分钟玩转Docker容器技术》Cloudman博客如下:

http://blog.51cto.com/cloudman

------------------------------------重要说明------------------------------------

书籍:

1.《每天5分钟玩转Kubernetes》
https://item.jd.com/26225745440.html

2.《每天5分钟玩转Docker容器技术》
https://item.jd.com/16936307278.html

3.《每天5分钟玩转OpenStack》
https://item.jd.com/12086376.html




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