开源的网络组件
Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平网络空间中。这在GCE里面是现成的网络模型,Kubernetes假定这个网络也存在。而在私有云里搭建Kubernetes集群,就不能假定这种网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的Docker容器之间的相互访问先打通,然后运行Kubernetes。
目前已经有多个开源组件支持容器网络模型。本节介绍几个常见的网络组件及其安装配置方法,包括Flannel、Open vSwitch、直接路由和Calico。
Flannel
Flannel之所以可以搭建Kubernetes依赖的底层网络,是因为它能实现以下两点。
(1)它能协助Kubernetes,给每一个Node上的Docker容器都分配互相不冲突的IP地址。
(2)它能在这些IP地址之间建立一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。
现在,通过下图来看看Flannel是如何实现这两点的。
可以看到,Flannel首先创建了一个名为flannel0的网桥,而且这个网桥的一端连接docker0网桥,另一端连接一个叫作flanneld的服务进程。
flanneld进程并不简单,它上连etcd,利用etcd来管理可分配的IP地址段资源,同时监控etcd中每个Pod的实际地址,并在内存中建立了一个Pod节点路由表;它下连docker0和物理网络,使用内存中的Pod节点路由表,将docker0发给它的数据包包装起来,利用物理网络的连接将数据包投递到目标flanneld上,从而完成Pod到Pod之间的直接地址通信。
Flannel之间的底层通信协议的可选技术包括UDP、VxLan、AWS VPC等多种方式。通过源flanneld封包、目标flanneld解包,最终docker0收到的就是原始的数据,对容器应用来说是透明的,感觉不到中间Flannel的存在。
我们看一下Flannel是如何做到为不同Node上的Pod分配的IP不产生冲突的。其实想到Flannel使用了集中的etcd存储就很容易理解了。它每次分配的地址段都在同一个公共区域获取,这样大家自然能够互相协调,不产生冲突了。而且在Flannel分配好地址段后,后面的事情是由Docker完成的,Flannel通过修改Docker的启动参数将分配给它的地址段传递进去:
--bip 172.17.18.1/24
通过这些操作,Flannel就控制了每个Node上的docker0地址段的地址,也就保障了所有Pod的IP地址在同一个水平网络中且不产生冲突了。
Flannel完美地实现了对Kubernetes网络的支持,但是它引入了多个网络组件,在网络通信时需要转到flannel0网络接口,再转到用户态的flanneld程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗。
另外,Flannel模型默认采用了UDP作为底层传输协议,UDP本身是非可靠协议,虽然两端的TCP实现了可靠传输,但在大流量、高并发的应用场景下还需要反复测试,确保没有问题。
Flannel的安装和配置如下。
由于Flannel使用etcd作为数据库,所以需要预先安装好etcd,此处不在过多描述。
安装Flannel
需要在每个Node上都安装Flanel。Flannel软件的下载地址为:
https://github.com/coreos/flannel/releases
将下载的压缩包flannel-<version>-linux-amd64.tar.gz解压,将二进制文件flanneld和mk-docker-opts.sh复制到/usr/bin(或其他PATH环境变量中的目录)下,即可完成对Flannel的安装。
- 配置Flannel
此处以使用systemd系统为例对flanneld服务进行配置。编辑服务配置文件/usr/lib/systemd/system/flanneld.service:
[Unit]
Description=flanneld overlay address etcd agent
After=network.target
Before=docker.service
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/flanneld
ExecStart=/usr/bin/flanneld -etcd-endpoints=${FLANNEL_ETCD} $FLANNEL_OPTIONS
[Install]
RequiredBy=docker.service
WantedBy=multi-user.target
编辑配置文件/etc/sysconfig/flannel,设置etcd的URL地址:
FLANNEL_ETCD="http://20.0.40.51:2379"
FLANNEL_ETCD_KEY="/coreos.com/network"
在启动flanneld服务之前,需要在etcd中添加一条网络配置记录,这个配置将用于flanneld分配给每个Docker的虚拟IP地址段:
etcdctl set /coreos.com/network/config '{"Network": "10.1.0.0/16"}'
由于Flannel将覆盖docker0网桥,所以如果Docker服务已启动,则需要停止Docker服务。
- 启动flanneld服务
systemctl restart flanneld
- 设置docker0网桥的IP地址
mk-docker-opts.sh -i
source /run/flannel/subnet.env
ifconfig docker0 ${FLANNEL_SUBNET}
完成后确认网络接口docker0的IP地址属于flannel0的子网,重启docker服务。