Wednesday, June 10, 2015

从 Kubernetes 谈容器网络

Pod

首先,Kubernetes 中的基本单元是 Pod,而非 Docker 容器。
Pod 是一组共享了下面资源的容器: 进程命名空间 网络命名空间 IPC 命名空间 UTS 命名空间
简单的讲,一个 Pod 是一个小型的“虚拟机”,里面运行若干个不同的进程,每个进程实际上就是一个容器。
Kubernetes 要干的事情是要把这些 Pod 给互相连接起来,是不是联想到了什么了?

设计理念

其实 Docker 默认采用 NAT 的方式已经组成了简单的网络了。但Kubernetes 认为 Docker 的默认网络采用了 NAT 方式,跨节点通信就需要进行端口映射,这会给服务的访问带来麻烦。
设计理念包括如下几点: 所有容器不使用 NAT 就可以互相通信 所有节点跟容器之间不使用 NAT 就可以互相通信 * 容器自己看到的地址,跟其他人访问自己使用的地址应该是一样的(其实还是在说 NAT)

实现

要满足上面的要求,也不难,只需要容器内网络地址空间跟承载网的数据空间打通即可,即容器内网络地址直接暴露到物理网上去。
Kubernetes 的基于 GCE 的实现十分简单,给每个物理节点直接分配一个内部子网(默认是 /24 的),这样每个 Pod 就能分到一个地址了。这个地址是直接暴露到物理网络上的,可以直接进行路由。
想让 Pod 访问外网也很简单,将目的不是到内部子网的流量本地做一把 SNAT 即可。

扩展

当然,在此基础上还可以进行扩展,比如下面几种方案:

CoreOS 的 Flannel

Flannel内部流量出到物理网之前,非本地的流量过一下整个内部网的网关,然后用 VXLAN 封装下,直接 tunnel 到对端后进行解包。

Weave

Weave
Weave 的网络设计也是对承载网这部分进行改进,对这部分流量进行封装,发送到对端的 peer 上,但不清楚封装协议类型。

socketplane

SocketPlane 的思路也是大同小异,在主机之间建 Tunnel,本地网桥默认使用 OpenvSwitch。
不同的主机发现采用 mDNS。
这家被 Docker 给收购了,很奇怪,背后应该有一些故事。

OpenStack Neutron

其实,现在的面向虚拟机的网络方案(比如 OpenStack Neutron)早就已经实现了上面的几点,而且使用网络虚拟化的手段,能做到比上面具有更加丰富和灵活的特性。例如,不同物理机上的容器可以拥有任意相同或者不同的子网,并且可以实现多租户的概念。
如果使用 Nova-Docker 来管容器的话,默认采用的就是 Neutron 网络。

结论和展望

网络的设计离不开对需求的深入分析。
从目前的几个项目来看,大家都是在模仿虚拟机的网络来实现容器的网络,甚至还有不少地方没有达到虚拟机网络的成熟度。
未来至少应该从下面两个方面去考虑设计容器网络:
  • 本地的优化:虚拟机的本地网络经过多年优化已经逼近了线速,但容器网络在这方面还有不少坑,特别对物理设备虚拟化技术的支持等。挖掘性能,降低对主机资源的消耗,仍有一些工作要做;
  • 网络特性的优化:容器网络根本上跟虚拟机网络存在很大的差异,这体现在容器的生命周期和使用行为上有很大的不同,传统的网络特性并不能很好地满足这些需求。

No comments:

Post a Comment