专栏名称: 分布式实验室
最专业的Docker文章,最权威的Docker新闻。关注容器生态圈的发展。
目录
相关文章推荐
51好读  ›  专栏  ›  分布式实验室

携程容器云实践

分布式实验室  · 公众号  · 后端  · 2017-04-01 07:54

正文

一、在线旅游与弹性需求

近年来随着大众旅游消费的火热,携程的业务每年呈高速增长,2016年 Q4 财报显示携程 2016 年全年营业收入同比增长 76%,交通票务营业收入同比增长 98%,酒店预订营业收入同比增长 56%,其他BU也有大幅增长,预计 2018 年携程的 GMV 将突破 10000 亿,并在 2021年 突破2万亿。

我们开发的私有云和持续交付平台为携程超过 20 个 BU/SBU 服务,为了同步支撑业务的高速发展,我们也需要不断的技术革新,持续提升携程运营、研发的效率,缩短产品从 idea 到交付用户的时间。

旅游出行的特点是季节性的,在平时流量都比较低,但节假日前一天流量会突然增高很多。因此每到节假日就会面临成「倍」增长的扩容需求。图 1 中可以明显的看到流量的起伏情况。

图 1

一般情况,临时扩容的需求较多,缩容会比较少,因为流量一上去之后,在短时间内不会下来,另外一方面,哪怕是流量下来了,由于以往资源申请没那么灵活,一般都会占用资源不释放,只能通过一些运维手段来监测资源使用情况然后告知业务部门去主动缩容。

携程目前大部分还是虚拟机,我们想缩短提前扩容的时间,以目前的虚拟机扩容方式,单个虚拟机扩容(从分配资源、调度、网络、OS 基础环境、应用部署等)至少是十分钟级别的,如果是每次扩容上千台的话,确实需要一定的时间,而且还得看看有无足够的资源,比如 1 月 1 日的流量提前一周就扩容好,但这不够灵活,业务流量下来以后需要缩容,目前的速度还是不够快。

针对这一场景,我们需要解决的问题是,能有更快的方案吗?如何能够做到更快速的弹性伸缩满足业务的需求?答案是利用容器。

图 2

再举个例子,携程有个深度学习的小诗机项目,将训练好的模型,对外提供服务,用户只要上传照片,后台的 AI 机器人就会根据照片中的内容自动写诗,这对于现行都市词穷一族来说,瞬间提升了意境,蛮有意思的。

该项目希望在春节前上线,需要紧急扩容 1000 核,以满足春节期间大流量的需求,春节过后立马就可以缩容 90% 的资源。目前我们通过容器可以做到 1000 核的资源,5 分钟内完成 150 个容器实例的扩容,而且这还是 API 同步创建的速度,我们正在优化成异步的方式,相信后续提高并发能力后,速度还可以得到大大的提升。

其实携程的容器化已经进行一年多了,容器给我们最大的感觉是看起来简单,但要做好很难,原理不是很复杂,但是要利用这个技术做出一个产品或服务,中间有非常多的细节需要完善,比如如何做到用户体验更好的 UI 可视化、如何做到灰度发布、容器监控、容器基础镜像版本管理等等。

二、携程容器云定位

携程容器云定位有以下 4 点:

1、打造极致的妙级持续交付体验,服务 20 + BU

秒级意味着所有的扩容、缩容、回滚全部是秒级的,做到秒级是很难的,有很多需要突破的地方。比如,高速的镜像下发系统;高效的调度系统,稳定的容器服务,高度自动化的网络服务。

2、提升资源利用率

为了提高服务器资源利用率,我们采取账单的形式,督促业务线提高资源利用率,优化代码架构。我们对采集到的实时监控数据进行统计分析,按照 CPU、内存、存储、网络等多个纬度,按月计费,每个月会将账单发给业务线的 CTO。

3、组件服务化(MySQL/KV/MQ/…)or PaaS 化

应用所需要依赖的很多组件能够变成服务化,AWS 或者阿里云也做了很多这种服务。携程内部也在尝试把一些公共组件服务化,例如,MySQL,Redis,RabbitMQ 等。拿 MySQL 为例,我们让用户可以在测试环境快速部署 MySQL 实例,并且可以选择性的将测试数据灌入。新建的 MySQL 实例也会自动在数据访问中间件中完成注册,方便开发人员、测试人员快速搭建测试环境和测试数据。

4、从自动化到一定程度智能化

从自动化到一定程度智能化指的是基础设施变得更智能,比如能够具备一定的自我修复能力,如果是从上游到下游的一整套服务都具备智能化修复能力的话,这是一个非常大的突破,对于提升运营效率和故障恢复速度至关重要。

三、容器部署基本原则

以上是携程容器部署基本原则,看起来很容易,却是我们很长时间实践经验的总结。

比如单容器单应用这个原则,历史原因我们有混合部署的情况,单个VM部署多个应用,运维的复杂度会上升很多,比如:应用之间如何做到更好的资源隔离?发布如何避免相互之间的冲突?等等,使得我们的运维工具、发布工具变得格外复杂,开发、测试的持续交付效率也受到极大影响。

容器镜像发布也是我们做的一个比较大的突破,过去是代码编译成可发布的包,直接部署到VM内部,而现在是编译时直接生成容器的镜像,不同环境其实部署的是同一个镜像,并且不允许部署之后单独登陆进行配置修改,通过这种方式做到 immutable infrastructure ,保证开发、测试、生产环境的一致性,同时也保障了自动化扩容、缩容快速高效的进行。

是否在容器内部也运行各种运维 Agent 也是我们经过实践确定下来的;我们希望容器尽量简单,尽可能只包含运行的应用本身,此外将所有的 Agent 合并到 host 层面,也能在很大程度上提升服务器资源利用率,Agent 数量下降一到两个数量级;但配套的管理工具(eg:salt)需要做一次升级改造才能适配新的模式。

四、容器编排选型&取舍

OpenStack

携程除了容器之外的东西都是用 OpenStack 来管理的,OpenStack 可以用一个模块(nova-docker)来管理容器,携程在 OpenStack 方面有多年的二次开发技术积累、也大规模的部署运维经验,但最终没有选用 OpenStack,因为 OpenStack 整体过于复杂,调度效率也比较低,API 调度是 10 秒以上,可以进行优化,但我们觉得优化代价太大,OpenStack 整体的复杂度也很高;

我们早期的胖容器(把容器当 VM 来使用,做代码包发布)的确是用 OpenStack 来做的,原因是我们希望把注意力放在容器本身,以最低的代价将容器先用起来,积累开发、运维经验;而到了瘦容器阶段(基于容器镜像做发布),我们发现 OpenStack 整体的设计理念从本质上讲还是为虚拟机隔离粒度的虚拟化方案设计的,而容器本身与vm其实差别很大,玩法也相去甚远, 于是我们对 Mesos/Kubernetes 进行评估。

回顾我们的容器调度探索之旅,基本上可以用以下三个阶段来总结:

第一阶段,需要最快的使用起来,用最熟悉的技术来解决部署和调度。到了第二阶段有新的需求,引入 Mesos 和 Chronos,提供分布式 cron job 调度。第三阶段是使用 Python 重新实现 Chronos,并且单独实现了 CExecutor 等组件。

图 3

OpenStack 用于管理 BM/VM 是很合适的,并且在网络方面有很成熟的支持,无论是 VLAN + OVS 还是最新的 SDN 都能适配,尤其各大厂商的支持力度都很大;这也是为什么我们虽然不用 OpenStack 调度容器,但容器的网络其实还是用 Neutron 来管理的。

Kubernetes

Kubernetes 有很多很先进的设计理念,比如有 Replication Controller/Pod/Yaml 配置管理等,但这些理念在携程都很难落地,因为跟现有的运维模式、发布流程有较大的冲突。而且当前还缺乏大规模部署案例,网络尚无比较成熟的方案, 例如 L4/L7 负载均衡;而在携程 L4/L7 服务已经比较成熟稳定, 并且与我们现有的发布系统 Tars 集成得非常好。

Mesos

Mesos 和 Kubernetes 解决问题的思路是不一样的,基于 Mesos 我们可以非常容易的开发出适合我们场景的调度框架,并且非常容易和我们现有的运维基础服务对接集成;包括 L4/L7 负载均衡、发布系统等。

图 4


五、容器网络选型

Neutron + OVS + VLan,这个模式非常稳定,对于网络管理也是非常的透明的。这也是携程的选择,现在的网络无论是胖容器还是容器轻量发布都用这种模式。我们也在测试 DPDK 和 https 硬件加速的效果。

我们也评估过类似flannel的网络,要求每个物理机独立网段,通过这个特性来做路由;非常不灵活的一点是容器如果迁移到另外一台物理机就需要换IP,无法满足我们的需求。

接下来会走 VXLAN + 基于BGP EVPN 协议自研轻量级 SDN Controller 的路线,VXLAN offload TOR 解封装提高性能;对于openstack可见的还是大二层网络(VLAN),而实际上是通过 Underlay 的三层路由进行转发;OpenStack与我们的控制器能实现元数据的一致性;关于这块,后续我们也会有相应的分享单独进行探讨。

如何配置容器网络

图 5

如图 5 用dwait 和 dresponse,基于 Go 开发,dwait 会通过 unix socket 请求外部服务 dresponse 做容器的初始化。当这个容器起来的时候,它的网络没有那么独立,在 Docker 里面是需要依赖外部提供信息的,所以需要知道哪个网段或者说创建的 neutronport 再配置到 Docker 容器内。这样做后就不会有网络丢失的情况。

六、Docker遇到的问题

接下来分享一下我们碰到的一些比较经典的Docker/Mesos相关的问题。

Docker Issue

图 6

在我们尝试使用 Chronos 跑 cronjob 时,由于我们的 Job 执行频率非常高,导致物理机上出现非常频繁地容器创建和销毁,容器的创建和销毁比单个进程的创建和销毁代价大,会产生很多次内核的调用,磁盘的分配销毁,这对内核是一个非常大的压力考验。

我们在实际操作过程中就遇到了一个 bug,如图 6 这台机器逐步失去响应,产生了 kernel soft lockup,慢慢的导致所有进程都死锁了,最终物理机重启了。为了避免频繁创建销毁容器,我们没有在 Chronos 这种一个 task 一个容器的路上继续走下去,我们自己研发了 Mesos framework,改成了一个Job,一个容器的调度方式。

Mesos Issue

Mesos 性能很稳定,基本上不需要修改 Mesos 代码,只需要在我们自己写的Framework进行控制调度,控制如何启动容器。

CExecutor

图 7

1)自定义 CExecutor,Go 语言实现
-避免过于频繁创建删除容器,带来的副作用
-cpuload 高而且抖动很大
-频繁启停容器引发的 Docker 和 kernel 的 bug

2)task:container
-1:1->N:1

3)容器持久化

如图 7,可以观察得到前段抖动非常厉害(如果过渡频繁地创建删除容器,会带来非常大的负担,抖动会非常高),在用 1:1 调度之后就变得平缓了。所以携程自定义 CExecutorr(Go 语言实现),避免过于频繁创建删除容器,带来的副作用(抖动非常强、load非常高),之后就基本上处于水平线了。

七、容器监控方案

Mesos 监控

图 8


图 9

如图 8-9 携程用了很多开源技术,Telegraf、InfluxDB、Grafana 并做了一些扩展来实现 Mesos 集群的监控,采集 mesos-master 状态、task 执行数量、executor 状态等等,以便当 Mesos 集群出现问题时能第一时间知道整个集群状态,进而进行修复,此外, 我们还从 Mesos 调度入手,做了一些应用层的监控,比如:针对cron job类型的应用,让用户可以看到 job 应该在什么时候执行,执行的过程,整个 job 的成功率,job 还有多个实例在跑等。

容器监控







请到「今天看啥」查看全文