写点什么

洪强宁:宜信的 PaaS 平台基于 Calico 的容器网络实践

2016 年 2 月 25 日

2016 年 1 月 22~23 日,ECUG Con 2015 大会在北京新疆大厦举行,ECUG(Effective Cloud User Group,实效云计算用户组)是由 Erlang 爱好者、分布式领域的知名专家组成的民间技术团体。ECUG Con 是该组织一年一度交流云计算产业前沿技术的大会。来自宜信的洪强宁分享了“基于 Calico 打造容器云网络的实践”。

关于容器云网络的话题,来自七牛的徐兆魁在 ArchSummit 北京 2015 上做过《主流容器 SDN 技术与微服务架构实践》的分享,感兴趣的读者可以延伸阅读。

容器云面临的网络挑战

在传统的 IDC 的架构里面网络是很重要的事情,在虚拟机环境中网络的发展已经有很多成熟的解决方案,现在为什么还在研究新的方案呢?因为云计算。云计算在 2013、2014 年之前的时间段,其主要的发力点在虚拟机。但是从容器技术出现之后,虚拟机被更轻量的容器方式颠覆,从而大幅降低开发、运维、测试和部署、维护的成本。当然也带来了很多在虚拟机里没有面临过的问题。

在网络层面,容器的本质是几个被封装了的进程。这必然导致每个容器都会有自己完整的网络栈、有自己的 IP。所以整个云的基础设施——集群里有大量的网络和 IP 要管理,并且进程的启动和结束是与容器伴生的,进程生灭的频繁程度超过了虚拟机几个量级。创建一个虚拟机会开启很多程序,程序之间彼此通信,但和虚拟机外部的通讯是少很多的。而容器的诞生,从网络管理角度来说,微服务架构呼之欲出。

用容器做迁移的时候,如果一台机器宕机了,对应用而言希望是无感知的。因此,如果容器所在的主机出故障,就带来了新的问题,即容器 IP 的任意漂移。在创建虚拟机的时候,IP 地址的分配是一种静态方式;但是在容器上面,IP 地址的分配通常是动态分配。一个容器启来的时候,通常我们不会知道它的 IP 是什么,只有起来之后才知道。

在容器云的场景下,我们倾向于把多个应用放在一个应用上运行,这导致应用和应用之间需要做安全隔离——我们不希望一个出问题的应用会影响其他的应用。所以说容器之间需要决定哪个容器可以通信,哪个不能通信。以前在虚拟机的时代,通过大量分层可以解决,但容器环境里这件事情的难度提高了。

所以我们选择网络解决方案的需求也发生了变化,最大的要求是容易管理。网络间通信量大了,不能够承受太大的损耗。而当发生容器间迁移的时候,需要一种机制,来保证迁移后的 IP 不会发生变化。同时,它的解决方案是需要细粒度的安全策略。

容器本身是一个单机软件,并没有为跨主机的网络考虑太多。跨主机容器互联的解决方案最典型的是两台主机之间通过一个交换节点实现连通。在主机内起十到几十个主机的规模,考虑到主机上有没有足够的 CPU 和内存,在这个主机上做静态 IP 规划几乎是不太可能。这时候我们就引入 SDN 技术——用软件的方式定义网络,软件数据发生变化时网络就相应地发生变化。

常见 SDN 方案

简单的谈一下 Docker Bridge,关于主机内部的网络管理工作。每个容器里面都有一个虚拟网卡,和主机上的虚拟网卡做配合,所有容器内的虚拟网卡都可以和主机通信。通过端口映射,我调用对方的容器服务的时候,不能使用该容器直接的地址,必须使用它主机的地址。因为有了这样一个转发,网络通讯的性能有所损耗。当然,还有一个问题更严重,访问你的容器先要搞清楚你的主机是什么,这样网络通讯会跳来跳去。不但麻烦,还会带来端口冲突。每创建一个容器会绑定一个端口,怎么管理好这些端口是一个很大的挑战。

第二个解决方案是 Flannel,这个想法很好。每个主机负责一个网段,在这个网段里面分配一个 IP 地址。访问另外一台主机的时候,通过网桥到达主机上的 IP 地址,这边会有一个设备,程序会把你发的包读出来,去判断你的目标地址是什么,归哪台机器管。还会把你的 IP 包外面加一个 UDP 包,发到目标地址。收到之后,会把前面的包扔掉,留下来的就是目标容器地址。这个方法有几个问题,第一个是要做封包的操作。第二个问题是每个主机上的容器是固定的,容器的不同主机之前的迁移必然带来 IP 的变化。

再来说说 Weave,他的思路是共享 IP 而非绑定。在传输层先找到目标地址,然后把包发到对端,节点之间互相通过协议共享信息。Flannel 和 Weave 的特点是类似的,都用的是 UDP 或者是 VxLAN 的技术。事实上使用 UDP 性能是很差的,VxLAN 和 UDP 差不多,它有一个网络切隔,而且在里面可以跑二层协议。还有一种是 IPIP 封包,直接把一个 IP 包封装在一个 IP 包里面。

以上不难看出,原生网络性能比较差,使用 UDP 的时候性能损失在 50% 以上,使用 VxLAN 也会有 20%~30% 的损耗。所以我要在内核上封包,使用硬件来解决这些问题。而且容器和容器之间出现通讯故障,调试的时候非常困难。

关于封包

回过头来想一下,我们为什么要封包?其实它是改包,主要解决的问题是同一个问题。即容器网络里,主机间的不知道对方的目标地址,没有办法把 IP 包投递到正确的地方。

  • 传统的二层网络是用路由来互相访问,不需要封包。但是路由规则怎么维护?利用 BGP(基于 TCP 之间两两连接)搞一个分布式的路由集群能否满足规模?
  • Metaswitch:容器内部配一个路由指向自己宿主机的地址,路由规则下发,这是一个纯三层的网络没有封包,接近原生网络性能。

在容器里面我们怎么做呢?我们发现了 Calico 项目。不同主机上的每个容器内部都配一个路由,指向自己所在的 IP 地址;每台服务器变成路由器,配置自己的路由规则,通过网卡直接到达目标容器,整个过程没有封包。

所以这是一个纯三层网络,没有引入一个 DP,没有封包。在主机内部做另外一个容器,可以三条到达终端,你可以知道是谁出了问题,调试的时候很容易,很好管理。容器内的应用数据传出来,和二层完全隔离,对于我们绝大多数的应用来讲只需要三层就够了,很少有应用处理二层。

那么,路由交换是不是很难呢?用传统的 BGP 技术就可以实现。这个协议在大规模应用下是一个很好的场景。而且 BGP 有一个自治域的概念。在这个场景下会有一个问题,路由之间的信息交换实际上是基于 TCP 协议,每两个之间都有一个 TCP 连接,规模大了以后复杂度非常高。所以在这种场景下,大概是几百个主机直接使用 BGP 的方式来做;再大一点的话,选择分布式互联,这样可以把网络规模继续扩大,最后能够支持到几万台机器。如果不需要这些策略,不做商业逻辑和业务逻辑,只是用 BGP 来做路由互联的话,其实还是很简单和高效的。

金融业务的具体实现

宜信内部的做法是用 powerstrip 实现,还有一个是手工去做,启动容器直接用 Docker,然后自己再去设置 IP。如果容器之间都互通,创建容器的时候都通过配置环境变量,会创建一个 Profile,配置好 iptables 以及 ipset 可以保护我们的服务器。再稍微复杂一点的话,可以修改 ACL 规则,如果有很多个 APP,每个 APP 都需要访问数据库,每增加一个 IP 都要修改配置这样显得太麻烦,我们可以通过给所有的 APP 打标签的方式来解决这个问题。

配置容器的三种方法:

  • 用 powerstrip 来 Hijack 劫持 Docker 的 API,这个思路很有意思。
  • calicoctr container 命令。
  • libnetwork 驱动(需 Docker 1.9 以上)。

因为做的是金融业务,性能其实不是最吸引人的,ACL 应用是宜信关注的重点。比如在宜信的场景下做云平台的时候,会有应用的概念。一个应用有多个容器,互相可访问;不同应用的容器互相不能访问;一个应用对另外一个应用提供服务,作为服务容器并且规定哪些可以访问。所有的应用容器能够访问集群,应用容器不可以访问自己所在的集群的任何一台服务器。总之,我们要实现应用可以访问主机上指定的服务,可以访问除本网段之外的其他网段。

Calico 使用总结

Calico 的应用场景主要是 IDC 内部,推荐部署在二层网络上,这样所有路由器之间是互通的。这种场景是大二层的解决方案,所有服务器都在里面。但大二层主要的问题是弹性伸缩的问题。频繁开关机的时候,容器启停虽然不影响交换机,但容易产生广播风暴。网络规模太大的时候,一旦出现了这样的问题,整个网络都会有故障,这个问题还没有解决的特别好。

Calico 作为一个纯二层的应用问题不大。我们可以把集群分成了很多网段,对外是三层网络的结构。集群内部分成多个自制域,比如一个机柜是一个自制域,之间通过交换路由的方式实现在三层容器到容器的互通。瓶颈在于容器的路由信息容量。所以说本质上它不是一个应对互联网规模的解决方案,但对宜信场景是够用的。

我们实施的时候遇到一些坑,比如容器在启动时没有网络、操作 ETCD 的时候 BGP 配置频繁加载,等等,最后我们多一一解决了。我们也发现了 driver 方案功能方面的弱点,现在还继续使用劫持 API 的方法。如果要在云上使用,如果支持 BGP,直接可以用;如果不支持 BGP 可以用 IPIP。现在英特尔的网卡支持两个协议,一个是 GRE、一个是 VxLAN。如果真的把它放在云上,我们可以考虑一下把 VxLAN 引进来,性能上的差别不是很大。

2016 年 2 月 25 日 04:505037
用户头像

发布了 62 篇内容, 共 16.4 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

Mysql错误:Ignoring query to other database解决方法

一直AC一直爽

MySQL

Apache下error.log文件太大的处理方法

一直AC一直爽

手写实现Promise

GKNick

第七周学习总结

王锟

剪刀爱情

一直AC一直爽

电影

广义表的实现!

烫烫烫个喵啊

算法 广义表

架构师第七周作业

傻傻的帅

英特尔唐炯:把最好、最合适的产品带给最需要的消费者

飞天鱼2017

直播中那几秒延时到底来自哪?

巨侠说

CDN 云直播 直播 直播带货

手把手教你写数独计算器(1)

一直AC一直爽

c++ 算法 数独

MinIO 参数解析与限制

耳东

配置 Minio

技术面试官应该怎么问?面试者应该怎么答?

xcbeyond

面试 自我介绍 面试经验

47 张图带你 MySQL 进阶!!!

cxuan

MySQL 后端

新手村:MySQL 学习经验、资源的分享

多选参数

MySQL MySQL 高可用 MySQL优化

HashiCorp官宣:禁止国内使用其旗下Consul等开源软件?

xcbeyond

Consul 条款

总结:PHP值得注意的几个问题

一直AC一直爽

php

MinIO 分布式集群搭建

耳东

Minio cluster Minio 集群

ZK 从入门到放弃 入门篇

小隐乐乐

如何写出完美的接口:接口规范定义、接口管理工具推荐

xcbeyond

接口规范 接口管理工具 swagger Easy Mock

ARTS-WEEK7

一周思进

ARTS 打卡计划

企业架构框架之FEA

Winfield

企业架构

性能测试和并发压力的关系

王锟

性能测试与优化 和 操作系统与文件系统

满山李子

极客大学架构师训练营

来了,来了,你们要的Nginx教程来了

Java旅途

nginx

秒懂云通信:选云通信到底哪家强?

巨侠说

云通信 通信云

我向面试官讲解了单例模式,他对我竖起了大拇指

cxuan

设计模式 单例模式

【一起学系列】之命令模式:封装一个简单Jedis

Kerwin

设计模式 命令模式 Jedis

JVM系列之:String,数组和集合类的内存占用大小

程序那些事

Java JVM GC JOL

面试官拿System.out.println()考了我半个小时?我傻了

Java小咖秀

Java 面试

读《我的大学,我的苦难》有感

一直AC一直爽

随笔杂谈 读后感

WebRTC框架下的实时视频关键路径

fumingwang

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

洪强宁:宜信的PaaS平台基于Calico的容器网络实践-InfoQ