Docker容器跨主机访问之flannel网络
Docker跨主机访问
flannel
安装配置etcd
先在主机10.211.55.17上创建并编写脚本a.sh
sudo vim a.sh
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/
编写好脚本后保存并退出,并赋予该脚本可执行权限
sudo chmod u+x a.sh
运行脚本
启动etcd并打开2379监听端口
etcd -listen-client-urls http://10.211.55.17:2379 -advertise-client-urls http://10.211.55.17:2379
测试etcd是否可用
etcdctl --endpoints=10.211.55.17:2379 set foo "bar" etcdctl --endpoints=10.211.55.17:2379 get foo
结果表明已经可以正常在etcd中存取数据了
安装配置flannel
build flannel
(1)下载并重命名image
sudo docker pull cloudman6/kube-cross:v1.6.2-2
sudo docker tag cloudman6/kube-cross:v1.6.2-2 gcr.io/google_containers/kube-cross:v1.6.2-2
(2)下载flannel 源码
sudo git clone https://github.com/coreos/flannel.git
(3)开始构建
cd flannel
sudo make dist/flanneld-amd64
(4)将flanneld 执行文件拷贝到host1 和host2
sudo scp dist/flanneld-amd64 10.211.55.20:/usr/local/bin/flanneld sudo scp dist/flanneld-amd64 10.211.55.21:/usr/local/bin/flanneld
将flannel 网络的配置信息保存到etcd
先将配置信息写到文件flannel-config.json 中,内容为:
{ "Network":"10.2.0.0/16", "SubnetMin":"10.2.1.0", "SubnetMax":"10.2.255.0", "Backend":{"Type":"vxlan"} }
Network定义该网络的IP池为 10.2.0.0/16。
SubnetMin和SubnetMax指定IP分段
Backend为vxlan,即主机间通过vxlan通信,后面我们还会讨论host-gw。
将配置存入etcd
etcdctl --endpoints=10.211.55.17:2379 set /docker-test/network/config < flannel-config.json
/docker-test/network/config是此etcd数据项的key,其value为flannel-config.json的内容。key可以任意指定,这个key后面会作为flanneld的一个启动参数。执行etcdctl get确保设置成功
启动flannel
在两台主机上分别执行以下命令
sudo flanneld -etcd-endpoints=http://10.211.55.17:2379 -iface=enp0s5 -etcd-prefix=/docker-test/network
-etcd-endpoints指定etcd url
-iface指定主机间数据传输使用的interface
-etcd-prefix指定etcd存放flannel网络配置信息的key
flanneld启动后,主机内部网络会发生一些变化
(1)一个新的interface flannel.1被创建,而且配置上subnet的第一个IP 10.2.39.0
(2)第一台主机添加了一条路由,目的地址为第二台主机的flannel网络的数据包都由flannel.1转发
配置Docker连接flannel
编辑第一台主机的Docker配置文件/etc/systemd/system/multi-user.target.wants/docker.service,设置--bip和--mtu
这两个参数的值必须与/run/flannel/subnet.env中的FLANNEL_SUBNET和FLANNEL_MTU一致
重启Docker daemon
sudo systemctl daemon-reload
sudo systemctl restart docker.service
Docker会将10.2.39.1 配置到Linux bridge docker0 上,并添加10.2.39.0/24 的路由
另一台主机配置类似
将容器连接到flannel网络
在两台主机上分别运行容器bbox1和bbox2
两个容器的IP分别为10.2.39.2和10.2.101.2
flannel网络连通性
测试bbox1和bbox2的连通性
bbox1能够ping到位于不同subnet的bbox2,通过traceroute分析bbox1到bbox2的路径
(1)bbox1与bbox2不是一个subnet,数据包发送给默认网关10.2.39.1(docker0)
(2)根据第一台主机的路由表(如下图),数据包会发送给flannel.1
(3)flannel.1将数据包封装成VxLAN,通过enp0s5发送给第二台主机
(4)第二台主机收到包解封装,发现数据包目的地址为10.2.101.2,根据如下路由表将数据包发送给flannel.1,并通过docker0到达bbox2
另外,flannel是没有DNS服务的,容器无法通过hostname通信
flannel网络隔离
flannel为每个主机分配了独立的subnet,但flannel.1将这些subnet连接起来,相互之间可以路由。本质上,flannel将各主机上相互独立的docker0容器网络组成一个互通的大网络,实现了容器跨主机通信。flannel没有提供隔离
flannel host-gw backend
与vxlan不同,host-gw不会封装数据包,而是在主机的路由表中创建到其他主机subnet的路由条目,从而实现容器跨主机通信。要使用host-gw首先修改flannel的配置flannel-config.json
{ "Network":"10.2.0.0/16", "SubnetMin":"10.2.1.0", "SubnetMax":"10.2.255.0", "Backend":{"Type":"host-gw"} }
Type用host-gw替换原先的vxlan。更新etcd数据库
停掉之前两个主机的flannel进程并重新启动
查看第一台主机的路由表,增加了10.2.101.0/24的路由,网关为第二台主机的IP 10.211.55.20
第二台主机类似
从 /run/flannel/subnet.env可以看出host-gw使用的MTU为1500
这与vxlan MTU=1450不同,所以应该修改docker启动参数--mtu=1500并重启docker daemon
下面对host-gw和vxlan做一个简单的比较
(1)host-gw把每个主机都配置成网关,主机知道其他主机的subnet和转发地址。vxlan则在主机间建立隧道,不同主机的容器都在一个大的网段内
(2)虽然vxlan与host-gw使用不同的机制建立主机之间连接,但对于容器则无需任何改变,bbox1和bbox2仍然可以通信
(3)由于vxlan需要对数据进行额外打包和拆包,性能稍逊于host-gw