探究PaaS网络模型设计

【编者的话】PaaS的抽象逻辑使得其网络模型与IaaS有所不一样,本次经过重点说明Kubernetes和Docker的网络,从而来探究PaaS的网络模型设计。docker

【3 天烧脑式容器存储网络训练营 | 深圳站】本次培训以容器存储和网络为主题,包括:Docker Plugin、Docker storage driver、Docker Volume Pulgin、Kubernetes Storage机制、容器网络实现原理和模型、Docker网络实现、网络插件、Calico、Contiv Netplugin、开源企业级镜像仓库Harbor原理及实现等。安全

PaaS和IaaS的网络需求

概念上来讲,IaaS是基础架构即服务,PaaS是平台即服务。从服务化角度来讲二者对于网络的需求有共同点:微信

  1. 一台宿主机的网络隔离,一台宿主机要运行多个环境黑盒(VM或者容器),这时候每一个环境黑盒的网络须要隔离。
  2. 环境变动后的访问一致性,好比VM或者容器迁移到其余宿主机的时候,如何保证外部访问不感知,比较通用的解决方案网络代理层来解决。

实现上来讲,IaaS是VM管理,PaaS是容器编排,二者的网络也会有些不一样:网络

  1. 容器比VM轻量级,启停更快,更方便迁移,因此PaaS的整个调度策略会更灵活,容器的迁移频率是高于VM,当容器迁移的时候,PaaS须要更加快速的解决变化后的网络访问。
  2. VM安全高于容器,IaaS这部分会更多在隔离和安全上有所考虑,固然这个多是公有云和私有云的一个定位,我的认为IaaS比较适合公有云,PaaS比较适合私有云。

PaaS的网络模型设计

以上部分咱们讨论了PaaS网络需求,总结来讲PaaS须要解决宿主机的网络隔离和环境变动后的访问一致性问题,而后在灵活性上须要更加注重,私有云的定位能够减小由于安全和隔离的代价,保证高性能。架构

宿主机的网络隔离

网络隔离最基本问题就是要解决端口冲突,一种思路是容器经过端口映射访问,宿主机的端口由系统分配避免端口冲突,这种方式对使用的便利性是有意义的,但并不理想,由于须要对各类端口进行映射,这会限制宿主机的能力,在容器编排上也增长了复杂度。负载均衡

端口是个稀缺资源,这就须要解决端口冲突和动态分配端口问题。这不但使调度复杂化,并且应用程序的配置也将变得复杂,具体表现为端口冲突、重用和耗尽。分布式

NAT将地址空间分段的作法引入了额外的复杂度。好比容器中应用所见的IP并非对外暴露的IP,由于网络隔离,容器中的应用实际上只能检测到容器的IP,可是须要对外宣称的则是宿主机的IP,这种信息的不对称将带来诸如破坏自注册机制等问题。工具

因此就要引入一层网络虚拟层来解决网络隔离,如今说的比较多的大二层网络,L2 over L3,好比OVS、Flannel、Calico等等。性能

环境变动后的访问一致性

一个通用方案来讲经过代理层提供不变的访问入口,像OpenStack的网络节点就是一个L3(IP)的访问入口,而PaaS更多的是提供L4(TCP、UDP)和L7(HTTP)的访问,L4比较流行的开源方案有LVS,L7的是Nginx和Haproxy。优化

所以PaaS的网络结构有:

  1. 物理网络
  2. 虚拟层网络
  3. 代理层网络

Kubernetes和Docker的网络说明

Kubernete Docker做为目前最流行的开源PaaS实现,经过其实现细节能够更加理解PaaS的网络模型实践。

容器网络

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每一个容器的默认网关。由于在同一宿主机内的容器都接入同一个网桥,这样容器之间就可以经过容器的Container-IP直接通讯。


Docker网桥是宿主机虚拟出来的,并非真实存在的网络设备,外部网络是没法寻址到的,这也意味着外部网络没法经过直接Container-IP访问到容器。

Pod内部容器通讯

Kubernetes中Pod是容器的集合,Pod包含的容器都运行在同一个宿主机上,这些容器将拥有一样的网络空间,容器之间可以互相通讯,它们可以在本地访问其余容器的端口。

实际上Pod都包含一个网络容器,它不作任何事情,只是用来接管Pod的网络,业务容器经过加入网络容器的网络从而实现网络共享。

Pod的启动方式相似于:
$ docker run -p 80:80 --name network-container -d <network-container-image> $ docker run --net container:network-container -d <image>
因此Pod的网络实际上就是Pod中网络容器的网络,因此每每就能够认为Pod网络就是容器网络,在理解Kubernetes网络的时候这是必需要须要清楚的,好比说Pod的Pod-IP就是网络容器的Container-IP。

Pod间通讯

Kubernetes网络模型是一个扁平化网络平面,在这个网络平面内,Pod做为一个网络单元同Kubernetes Node的网络处于同一层级。


在这个网络拓扑中知足如下条件:

  • Pod间通讯:Pod1和Pod2(同主机),Pod1和Pod3(跨主机)可以通讯
  • Node与Pod间通讯:Node1和Pod1/ Pod2(同主机),Pod3(跨主机)可以通讯

为此须要实现:

  • Pod的Pod-IP是全局惟一的。其实作法也很简单,由于Pod的Pod-IP是Docker网桥分配的,因此将不一样Kubernetes Node的Docker网桥配置成不一样的IP网段便可。
  • Node上的Pod/容器原生能通讯,可是Node之间的Pod/容器如何通讯的,这就须要对Docker进行加强,在容器集群中建立一个覆盖网络(Overlay Network),联通各个节点,目前能够经过第三方网络插件来建立覆盖网络,好比Flannel和Open vSwitch等等。

Flannel由CoreOS团队设计开发的一个覆盖网络工具,Flannel 经过在集群中建立一个覆盖网络,为主机设定一个子网,经过隧道协议封装容器之间的通讯报文,实现容器的跨主机通讯。Flannel将会运行在全部的Node之上,Flannel实现的网络结构如图所示:

代理层

Kubernetes中的Service就是在Pod之间起到服务代理的做用,对外表现为一个单一访问接口,将请求转发给Pod,Service的网络转发是Kubernetes实现服务编排的关键一环。

Service都会生成一个虚拟IP,称为Service-IP, Kuberenetes Porxy组件负责实现Service-IP路由和转发,在容器覆盖网络之上又实现了虚拟转发网络。

Kubernetes Porxy实现了如下功能:

  • 转发访问Service的Service-IP的请求到Endpoints(即Pod-IP)。
  • 监控Service和Endpoints的变化,实时刷新转发规则。
  • 负载均衡能力。

Kubernetes Porxy是一种分布式L3代理转发, 默认是基于Iptables实现,这从设计上很值得借鉴,可是性能部分有待验证。

Kubernetes中的Ingress提供了一个统一的对外代理入口配置,好比HTTP的访问配置,而后经过实现Ingress-Controller,Ingress-Controller的实现能够用Nginx、LVS等等,以Nginx来讲,就Ingress-Controller监控Kubernetes API,生成Nginx配置,而后加载生效,而Nginx跟Pod的通讯,能够走Service,可是考虑到Kubernetes Porxy的性能问题,建议直接和Pod通讯。下面就是一个实现图:


总体来看的一个网络模型以下:

Q&A

Q:有这么多虚拟网络,覆盖网络,会不会有网络延迟?

A:网络虚拟会带来性能损耗,好比Flannel须要将报文封装到UDP包中传输,这中间的封包解包就会带来损耗。因此网络虚拟化的部分,软件的实现还有待优化,其实更好的方式是硬件支持,好比如今提的不少的SDN网络。

Q:Pod为何要有个网络容器?

A: 一方面这是解耦,经过网络容器来负责网络配置,这样对于业务容器来讲稳定性会更高,好比在多个业务容器中,某一个业务容器断了,这样就不会致使网络中断。

Q:Calico默认全网是打通的,怎么作基于网段之间的隔离?

A:目前来讲要作网段隔离,可能偏向安全性比较高的场景,咱们目前是作私有云场景,对隔离的要求没那么高。因此若是要作隔离的话,能够参考OpenStack的OVS方案。

Q:在某些应用场景下,Pod的IP须要固定,而不是重启以后IP可能会变化,请问如何知足这种场景的需求?

A:Pod的IP须要固定的话,一种方式是修改Docker的代码,据我所知腾讯有实现过。另外的方案就是作L3的代理,给Pod一个浮动IP,有点像OpenStack的实现。

Q:Ingress的流量默认是先走Service而后到Pod,仍是直接到Pod?

A:取决你的实现,官方的实现是先走Sevice再到Pod,咱们是直接到Pod。

Q:Ingress-Controller实现除了使用LVS和Nginx外,可否采用商用负载设备来实现?实现是否取决于和Kubernetes API的对接?

A:能够,只要有接口均可以实现,经过实现Ingress-Controller,好比对接F5的硬件设备,只要F5支持相关的API。

Q:代理入口上有哪些方法解决单点失效的问题呢?

A:这个比较传统了,软件实现就Keepalived之类的。

Q:Igress-Cntroller比较好的库都有哪些,分别基于Nginx Haproxy LVS的?

A:GitHub有蛮多实现的,其实仍是比较简单的,像go语言的话,直接套用官方提供的demo便可,其余语言能够对接Kubernetes的API实现。

Q:这么多层的网络,多层转发后网络性能怎么样?有没有办法实现高速数据转发解决方案?

A:代理层,虚拟层都会有损耗,这个就是要考虑管理成本和性能的权衡了。如何要实现高性能的话,就是要往SDN网络研究,经过硬件层的支持来实现虚。

以上内容根据2017年07月11日晚微信群分享内容整理。分享人吴龙辉,网宿科技云计算架构师,负责设计开发PaaS平台,《Kubernetes实战》做者。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同窗加微信:liyingjiesa,进群参与,您有想听的话题或者想分享的话题均可以给咱们留言。

相关文章
相关标签/搜索