DevOps专题|玩转Kubernetes网络
Kubernetes无疑是当前最火热的容器编排工具,网络是kubernetes中非常重要的一环,
本文主要介绍一些相应的网络原理及术语,以及kubernetes中的网络方案和对比。
Kubernetes本身并不提供网络功能,只是把网络接口开放出来,通过插件的形式实现。为了满足不同的网络功能及需求,使容器在创建或销毁时能够容易地配置容器网络,CNI(Container Network Interface)应运而生,CNI旨在定义运行时和插件之间的接口,在kubernetes中,CNI连接kubelet和网络插件来为容器配置对应的网络设置。
1 背景
容器网络是容器选择连接到其他容器、主机和外部网络的机制。在kubernetes网络模型设计中,往往需要每个Pod都拥有一个独立的IP地址,而且假定所有的pod都在一个可以直接连通的、扁平的网络空间中。用户不需要额外考虑如何建立Pod之间的连接,也不需要考虑将容器端口映射到主机端口等问题。所有节点都可在不用NAT的方式下同所有容器通讯,容器的地址和别人看到的地址是同一个地址。
2 技术术语
IPAM: IP地址管理;这个IP地址管理并不是容器所特有的,传统的网络比如说DHCP其实也是一种IPAM,到了容器时代我们谈IPAM,主流的两种方法:基于CIDR的IP地址段分配地或者精确为每一个容器分配IP。但总之一旦形成一个容器主机集群之后,上面的容器都要给它分配一个全局唯一的IP地址,这就涉及到IPAM的话题。
Overlay: 在现有二层或三层网络之上再构建起来一个独立的网络,这个网络通常会有自己独立的IP地址空间、交换或者路由的实现。
BGP: 主干网自治网络的路由协议,用于管理边缘路由器之间数据包的路由方式。BGP通过考虑可用路径,路由规则和特定网络策略,帮助弄清楚如何将数据包从一个网络发送到另一个网络。BGP有时被用作CNI插件中的路由机制,而不是封装的覆盖网络。
封装: 封装是指在附加层中封装网络数据包以提供其他上下文和信息的过程。在overlay网络中,封装被用于从虚拟网络转换到底层地址空间,从而能路由到不同的位置(数据包可以被解封装,并继续到其目的地)。
3 CNI
Container Network Interface (CNI) 最早是由CoreOS发起的容器网络规范,是Kubernetes网络插件的基础。其基本思想为:Container Runtime在创建容器时,先创建好network namespace,然后调用CNI插件为这个netns配置网络,其后再启动容器内的进程。
CNI Plugin负责给容器配置网络,必须实现为由容器管理系统(rkt或者kubernetes)调用的可执行文件,包括两个基本的接口来配置网络:
配置网络: AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result, error)
清理网络: DelNetwork(net NetworkConfig, rt RuntimeConf) error
在Kubernetes中,kubelet决定了容器应该加入哪个网络以及它需要调用哪个插件。然后插件会将接口添加到容器网络命名空间中,作为一个veth对的一侧。接着它会在主机上进行更改,比如将veth的其他部分连接到网桥。再之后,它会通过调用单独的IPAM(IP地址管理)插件来分配IP地址并设置路由。
4 IPAM
以上CNI插件解决了Pod内网络配置的问题,但是网络还有一个问题要解决的便是IP管理,为了解耦网络配置和ip管理, CNI定义了第二种类型的插件-ip地址管理插件(IPAM插件)。
与CNI插件一样,IPAM插件通过运行可执行文件来调用。IPAM插件负责为接口配置和管理IP地址。
CNI插件在执行时调用IPAM插件,IPAM插件来确定接口IP /子网,网关和路由等信息,从而在容器启动时分配IP地址并配置网络,并将此信息返回给CNI插件,在删除容器时再次调用它以清理这些资源。
IPAM插件可以通过协议(例如dhcp),存储在本地文件系统上的数据,网络配置文件的“ipam”部分或上述各项的组合来获取信息。
5 介绍两种常见的k8s网络方案
flannel
flannel是CoreOS团队设计的一个网络方案,以etcd作为存储,给node上的每个容器分配全局唯一的IP地址, 容器间通过overlay网络互相通信。
Pod间通信如下:
• Pod1和pod不在同一宿主机
数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡(veth pair),flanneld服务监听在网卡的另外一端,Flannel通过Etcd服务维护了一张节点间的路由表,利用etcd来管理可分配的IP地址段资源,同时监控etcd中每个Pod的实际地址,源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一下的有docker0路由到达目标容器。
• Pod1和Pod2在同一台宿主机
Pod1和Pod2在同一台主机的话,由Docker0网桥直接转发请求到Pod2,不经过Flannel。
calico
Calico是一个纯3层的数据中心网络方案,而且无缝集成像OpenStack这种IaaS云架构,能够提供可控的VM、容器、裸机之间的IP通信。
通过将整个互联网的可扩展IP网络原则压缩到数据中心级别,Calico在每一个计算节点利用Linux Kernel实现了一个高效的vRouter来负责数据转发,而每个vRouter通过BGP协议负责把自己上运行的workload的路由信息像整个Calico网络内传播——小规模部署可以直接互联,大规模下可通过指定的BGP route reflector来完成。这样保证最终所有的workload之间的数据流量都是通过IP路由的方式完成互联的。
Calico节点组网可以直接利用数据中心的网络结构(无论是L2或者L3),不需要额外的NAT,隧道或者Overlay Network。
Calico还提供了丰富而灵活的网络Policy,保证通过各个节点上的ACLs来提供Workload的多租户隔离、安全组以及其他可达性限制等功能。
6 k8s网络在云翼的实践
容器技术的诞生,伴随自己诸多的优点被广泛应用。容器消除了部署环境差异,保证了应用生命周期的环境一致性标准,高资源利用率和隔离性,以及快速部署的特性,给企业的生产提升了效率,节约了成本。
随着京东云业务的快速增长,业务部署不能再局限于物理机、虚拟机等传统的方式, 云翼早在2017年就开始了容器方向的探索之路,我们发现容器背后的理念很超前,但现实中生产环境有许多存量的业务,无法与之匹配,理念上是有一些差异, 如社区的容器倡导one process one container(在容器中只运行一个应用)。
云翼作为京东云DevOps平台,提供了集部署、运维、监控、日志等诸多功能,这些功能实现大多都是需要在实例内部署Agent与对应的服务通信,而实例如何标识到自身往往是使用IP的方式,容器在内部落地的一个很强烈的需求就是能够固定IP,使运维或者开发能方便登录容器排查问题;另外很大一部分存量的业务架构依赖固定IP;还有内部的一些基础系统都是通过IP来过滤,例如接入/LB 等后端需要填写IP地址。容器在内部的落地,不能完全不考虑存量业务的兼容性,很难放弃原有的技术体系, 我们希望容器的引用能减轻上手成本,能更贴近传统运维的习惯,为了方便管理,我们把容器的网络和机房的内网放在一个平坦的网络。
我们开发了ipamD,大概的实现原理是pod每次创建时调用IPAMclient去请求ipamD申请地址, ipamD是一个常驻进程,维护了各个应用下对应分组的地址信息,通过pod前缀名可以查到对应实例的IP,通过这种方式实现了IP地址固定的需求。
另外为了降本增效,提升并满足一些业务方的特定需求,希望容器能够跑在京东云的虚拟机上以方便管控相关的业务,我们开发了相应的网络插件来满足在云主机中运行容器的需求,使云翼的用户能无差别的使用IaaS的资源。
云主机上的CNI插件借助弹性网卡、路由策略实现了:
- 所有容器可以不需要NAT双向互通
- 所有容器到Node可以不需要NAT双向互通,反之亦然
(图片来自https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md)
注:具体实现可参考amazon-vpc-cni-k8s(https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md)
云翼借助 docker/k8s 大幅提升了开发、测试、运维的生产力,简化了人工和自动系统管理工作。如果你想了解更多关于京东云翼,欢迎点击“阅读”~
欢迎点击“京东云”了解更多精彩内容