我们是如何利用容器实现快速弹性伸缩的,携程万台规模容器云平台运维管理实践

作者简介

作者简介:吴毅挺携程系统研发部高级总监

图片 1

周昕毅

2012年加入携程,从零组建携程云平台团队,目前负责携程私有云、虚拟桌面云、网站应用持续交付等研发。

从去年底开始,携程开始计划把Docker引入到携程的云平台,这是系统研发部一部分的工作任务,携程系统研发部的架构师李任现在就在协同研发部从事Docker引入的工作。携程的Docker实践是怎样的?以下正文给你答案:容器对携程的价值为什么要在携程内部推容器?肯定是想获得容器带来的好处。公共的好处大家都会知道,但有一个可能是携程特有的痛点,因为携程有大量的应用是部署在Windows上,因此携程也很希望将来Windows的容器会给它们带来一些提高和帮助。目前携程为容器在内部的推动制订了一些路线图。携程希望尽量以虚拟机的方式来运行容器,这主要是考虑到它带来的优点是对现有的应用和体系的影响小,携程希望尽量以平滑的方式过度到容器中。但是,目前在推广上会有一个困难,大家会在你推销它的时候质疑,因为改变很小意味着带来容器特殊的优势很少。而这个确实是它的缺点。另外目前在携程内部主要是通过 OpenStack来管理云架构的基础设施。携程部署Docker的架构图一图一是携程目前第一阶段部署容器的架构,它选择了一个比较简单的切入点,通过Nova Docker Driver做一些改造来管理容器的生命周期。本身容器的调度、管理和在OpenStack上用管理虚拟机是一样的。图一最上面的Remedy是携程内部的流程管理系统,它会通过一些接口去访问OpenStack 的整个controller的API。因为携程早期是Windows,所以有很多VMWare的虚拟机,它们有专门针对EXSi的nova compute节点,图一右边是KVM的计算节点。引入Docker实际上是在这个架构里面增加了一个新的节点类型,即专门跑容器的Docker的一个节点。图二除了容器本身生命周期之外,网络的架构复用了现在OpenStack管理网络的方式。前面是计算资源的架构,同时也用OpenStack对网络进行管理。基本上容器的网络使用方式和虚拟机在OpenStack里使用网络的方式是很一致的。图二是一个容器的网络图,可以看到一个Docker容器有一对veth的设备。一个在它自己的namespace里面,一个加入到OVS bridge里面,如果这等同于虚拟机的话,下面就是虚拟机的tap设备,之后就和虚拟机网络的PaaS是一样的。通过这个bridge 连到internal 的bridge,右边是出口的 bridge ,中间会做vlanid转换,这样可以接到系统的二层网络里面去。这个是经典的VLAN模型。Docker容器运行携程Docker的容器的运行为了尽可能的讨好用户,更容易让他们接受,现在是以虚拟机的模式进行。在应用部署方面跟现在虚拟机部署一样,拿到一个容器之后通过现在的发布系统部署进去。因为是高度接近虚拟机的环境,所以对于应用的发布系统,用户基本上感知不到。现在携程内部虚拟机的发行版,主要以CentOS6.4为主,但是他们也开始迁移到CentOS7.1,所以携程在Docker容器上支持这两个发行版。以前的虚拟机的方式会导致运维的人上去可能要做很多运维的工作,所以要考虑到权限问题。但有些权限很危险不能给他们,否则会造成很多问题。比如sys_boot,它在里面可以将宿主机重启,如果你把sys_boot给出去的话,这个是很可怕的。镜像有很多种方式,而携程现在选的方式是有一定历史原因的。因为携程OPS有一套基础的环境规范。为了让ops原有的设施能继续工作,这个环境要尽可能演示。但悲剧的是,它没有一个很精确的代码能去描述环境是怎么样的,而只能用一个做好的自动安装的光环去抓取到环境。所以当时携程选择直接把自己的虚拟机的镜像拉过来,然后从虚拟机QCOW2的镜像去踩点至Docker的镜像。携程以虚拟机的方式运行,它运行起来不是很正统的只有一个进程的容器的方式。携程在一个容器里面起了很多进程,而进程像虚拟机一样需要有个初始的守护进程,所以携程也需要这样的守护进程。守护进程很多,而守护进程该如何选择?如果大家看过相关文章的话,有很多的讨论。除了目前已有的守护进程外也涌现着很多新的守护进程。但是比较悲剧的一点,携程还有一个运用规范,运用规范规定了启动服务,在CentOS7.1下一下子很难撼动他们的地位,只能向他们靠拢。另外,如果容器里面Cgroup这个文件系统是可读的,这也意味着在容器里面,分到的CPU内存资源可以随意改变,这个可能在公有云计算是不可接受的事情,但是私有云里面目前只能这样。还有很重要的一点是网络。前面说到携程网络是和OpenStack的那套网络管理一样的方案,其实它有很多手段来实现这些。目前因为携程用novadocker,顺便说一下novadocker 常不靠谱,没法用。携程以前与京东交流,他们给携程出的建议第一句话就是不要用novadocker。novadocker采用的方式,其实和pipework是很类似的,也就是它把容器运行起来,然后进去,通过执行一些命令,再配上网络。但它有一个问题,其实容器在启动到配上虚拟的网卡,这个过程其实是有一段时间的。携程用systemd,而它启动是很快的,这就意味着,有一些服务起来的时候,后面需要配套网络,如果你的应用对于这个是有依赖的就会问题。另外,这个网络的配置信息Docker是不可见的,这意味着Docker不知道这段网络配置。如果Docker daemon把容器重启的话,它是没办法恢复网络配置的,这个是很严重的一个问题。比如到了1.9之后,支持libnetwork做网络的配置。这样就不会有前面丢失网络信息的问题。携程现在还是用novadocker 的方式,本来打算用libnetwork,但是很悲摧的是,上线之前,携程一直使用Ubuntu,后来临上线,到生产的时候,运维说,他们希望统一宿主机版本全部用CentOS。最后没办法,只能把Netron agent这些东西全放到容器里面跑,再跑 novadocker等。Docker监控前面部署其实只是解决了实例运行的一些问题。运维的人的支撑对于一个真的能运营的产品很重要,所以对于Docker来说,假如真正要上业务,监控是很重要的一个话题。携程一般在Linux上监控数据,大多数是来自proc文件系统,proc文件系统在Docker容器里面,我们知道Docker容器做隔离其实提供namespace ,对于PID做得很好的namespace ,这个没有问题,网络统计也是很准确的。但是很多很关键的CPU、内存使用这些在proc系统里是看宿主机。还有一些监控的系统比如sysinfo sysconf这些是没有任何的秘密空间提供的。所以这些数据来源是很成问题的。对于Docker来说,我们监控该怎么办?其实现在有一些方式,比如说在宿主上监控所跑的容器现在也有方案,比如说Docker很早就提供了stats命令,可以看到每一个容器的读数,包括跨设备网络。还有一些比如像cAdvisor方案。为什么会看这个?因为在携程用的方式是zabbix,每个虚拟机里面都跑zabbix。这种方式是在宿主机上。但是下面每个虚拟机的监控数据对于携程来说,其实与现有的监控的方案不是非常的匹配,因为他们希望能够看到每个虚拟机单个作为一个的对象,能看到它的监控数据,而不是在宿主机上看到下面那些挂的。包括监控、告警这些都是有关联的。所以这些方式其实跟现有的监控的方案是有整合的成本在里面的。如果想尽量减少修改,还有一种是容器内部监控它。之前听蘑菇街的分享,他们直接把监控工具改掉。还有一个是很多人很关心的一个项目,它基本的原理用了files文件系统,实现了对proc文件系统的代理,它帮你代理、修改proc文件系统的访问,把数字计算一下获得一个正确的。正确的数据其实都是从cgroup里面读出来的。这个方式解决了这个问题之后。我们可以在容器内部获得正确的监控数据,包括启动时间,上线后怎么登进去了,怎么看到这个容器给它分配的资源是多少。一看宿主机48,怎么分了这么多给它?但是还是有一些问题,比如前面改内核者或者改工具,维护这些改动的成本在里面,还有一些部署。所以也有一些问题。后来携程想到另外一种折中的方式。这个方式是说,它们通过用Linux的Id prelod的机制,劫持对proc文件的访问,真正需要获得的数据是参考IXCFS的实现,重新计算一下,也是通过从cgroup里面计算你分配了多少内存,使用了多少,CPU是怎样的,去计算的一个资源。当然CPU load挺麻烦的,需要额外支持。图三图三中有个例子。可以看到,这个容器里面,用了劫持的方案计算了之后,可以看到大概分了两个G的内存。把环境变量去掉之后,看这个宿主机,大概一百多个G的内存。它的工作方式,比如说,如果是free,就是命令,它真正在运行的时候,会有Id so init去加载二进制文件的时候,会先加载我们的so 文件,它会把真正的open库的实现给劫持掉。到这里是一个标准的劫持的过程。之后free读文件的内存信息的时候,它其实读的是/proc/meminfo文件,劫持过来的时候,真正的逻辑到so文件里面,它读这个文件知道是干什么。实际上它读cgroup和lxcfs是一样的,计算然后把它保存到一个临时文件里面去。最后返回的是这个临时文件fd,Free会读这个临时文件。原理就是这样的。其实携程在容器上还有很多事情要做。比如说,不光是为交付给用户的计算环境提供容器,其实想把自己的一些很多东西都放到容器上去。比如携程的OpenStack平台也想跑到Docker里面去,因为OpenStack很复杂,部署起来也是件很头疼的事情。现在携程是用虚拟机的方式跑容器,其实是很重的。所以也想直接基于镜像的方式来应用持续交付。这就牵涉到很多东西,包括调度,打包,各种系统,包括进项的版本管理等。将来的微软的windows Container也是对携程影响很大的一个技术。另外如何进一步获得更高的的资源调动,如何动态的调度这些资源也是携程需要关注的地方,所以接下来携程还会有很多事情要做。本文是携程系统研发部的架构师李任日前在「七牛云主办的架构师实践日——容器核心技术与最佳实践」的演讲内容整理。PPT、速记和现场演讲视频等参见“七牛架构师实践日”官网。

携程系统研发部云平台高级研发经理

一、在线旅游与弹性需求

前言

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

我分享的主题是“万台规模容器云平台运维管理实践”,给大家分享一下在携程私有云平台管理的实践过程中踩过的坑和遇到的问题,几年前分享的主题是“携程云平台 DevOps 时代发展历程”。今天的分享主要有以下三部分:

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

第一部分携程容器云的概览,有哪些组成部分第二部分从实践的角度讲一下我们的团队如何对容器云进行管理第三部分做一些总结和对未来发展方向的展望

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

一、携程容器云概览

图 1

携程目前是三个自建的数据中心再加上公有云,在阿里云、腾讯云、AWS 都购买了一些资源。携程的应用目前也有六千多个,包含了酒店、机票、汽车票、商旅各个业务部门,每个部门都有自己的研发团队负责应用代码的开发。

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

我们团队就负责为这些内部的业务部门提供基础设施,之前部署应用的时候是提供物理机,后来迈入容器时代,不再关注基础设施的事情。现在容器云有两千台的级别,生产发布七八千次,一次发布就是一个应用的版本,所以发布频率还是很频繁的。

携程目前大部分还是虚拟机,我们想缩短提前扩容的时间,以目前的虚拟机扩容方式,单个虚拟机扩容(从分配资源、调度、网络、os基础环境、应用部署等)至少是十分钟级别的。

2015年底的时候还是用 python 做容器调度管控,当然现在 node.js 有自己的优势。我们团队也吸取先进的经验,全面把我们的容器调度管理平台迁移到 K8S 。携程代码调度平台,很早期用 Application ,后面携程转入了代码技术栈非常多,主流的之外的就是 java 、node.js 、 python、php ,这一块保证每个研发团队按照我们的参数配置来做,这都是有一定的定制方案,是需要制定标准的。

如果是每次扩容上千台的话,确实需要一定的时间,而且还得看看有无足够的资源,比如 1 月 1 日的流量提前一周就扩容好,但这不够灵活,业务流量下来以后需要缩容,目前的速度还是不够快。

资源方面我们以私有云为主,遇到突发流量会在公有云上面扩虚拟机。携程的高峰也是可以预期的,暑期是一个旅游的高峰,十一之前有会有一个很大流量的高峰,春节期间也是很大流量的。在这个阶段我们需要应用公有云的弹性来支撑我们的流量,日常我们还是以私有云为主,可以节省一定的成本。

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

部署在容器云上的应用目前分为两类:一种是标准应用,也就是 java 的应用程序,或者 python 的程序;第二类是 Application ,当然 Cache 的管理是比较大的话题,它也是在容器云上跑。

图2

携程容器云技术选型主要分为三个阶段:

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

第一个阶段,携程从2015 年开始实施 OpenStack ,2014年所有数据中心都具有了 OpenStack 的能力,因为我们对 OpenStack 特别熟悉,所以第一个也会用 OpenStack 部署。

之后开发了 NovaDocker ,避免应用的顾虑,有些业务团队不希望基础设施做比较大的变革,会对性能和稳定性方面有些顾虑。

但是为了尽快迈出这一步,我们采用了相对折中的方式,通过 OpenStack 交互虚拟机的方式,当然这也有不好的地方,就是调度方式不灵活,因为容器时代跟虚拟机的调度和编排的需求不太一样,虚拟机部署出来它的生命周期就是上线周期到下线,容器需要更强的调度迁移的能力。

第二个阶段,到了2016年我们觉得 OpenStack 管理容器的方式很难支撑下去了,当时业界最火的调度技术是 Mesos ,我们调研了 Mesos 并在它的基础上自研了 framework 。

第三个阶段,从2017年到2018年两年时间,我们发现 Mesos 的社区越来越不活跃了,遇到问题也是自己解决,没有社区的力量。

调研之后我们决定全面投向 Kubernetes ,同时交付容器给用户这么一个概念,你在不适用申请虚拟机的情况下虚拟容器了,你申请的是服务,我们容器云给你提供服务,这个服务包括数据的容器、缓存的容器,我们提供一个 PAAS 服务给到团队。

该项目希望在春节前上线,需要紧急扩容 1000 核,以满足春节期间大流量的需求,春节过后立马就可以缩容 90% 的资源。

我们容器云的中间一层是 CDOS ,模仿京东的 JDOS ,我们容器云把所有数据中心管控起来,像操作系统一样,把底层的计算资源、网络资源、存储资源以容器云 PAAS 的方式提供给客户使用,在 CDOS 上层有各大系统和业务框架的系统,包括SOA,相当于携程容器云在携程里处于数据中心的统一交付接口。

目前我们通过容器可以做到 1000 核的资源,5 分钟内完成 150 个容器实例的扩容,而且这还是 API 同步创建的速度,我们正在优化成异步的方式,相信后续提高并发能力后,速度还可以得到大大的提升。

当然我们自身也集成了调度编排、日志监控、存储资源、镜像管理,用统一的方式交付给研发团队比较一致的交付体验。

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

前面讲了这么多会觉得容器云是比较复杂的系统,需要支持非常多的资源管理。基于传统的运维管理方式需要做一些变化,否则无法面对这样的挑战。

二、携程容器云定位

这两年做了比较大的转变,我们很少提 IAAS 这个概念了,做这个项目的时候每天都在说 IAAS ,把基础设施以服务的方式提供出来,这样还是跟不上业务的需求,现在全面转向 PAAS ,我要去申请一个机器或者申请IP直接给你服务,你不需要关注服务跑在物理机上还是容器上,它后台服务的IP地址是什么都不需要去关注。

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

我们一开始想的是,只要把技术平台搞稳定就行了,但是对于业务的需求来说它是希望我们提供秒级发布的体验,我们基础设施团队不能拖研发团队的后腿吧。

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

这个时候我们告诉他发布要排队肯定是不行的,我们容器云支撑秒级的发布。关于智能化也在做尝试,但是目前还是在小范围的探索阶段,没有在大规模用于什么,所以我的分享主要是在 AIOps 全面落地之前用一些相对比较传统的方式管理我们的容器云。

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

容器云有一个比较大的好处,我们具备了弹性计算的能力和应用容量预估的技术基础,最终可以实现提升资源利用率的目标。

2、提升资源利用率

在几年前业务团队申请虚拟机的时候,我们一旦给了用户虚拟机就很难动它了,因为业务部门总有种种理由说,首先我虚拟机迁移是有成本的,而且用户究竟在虚拟机里装了什么软件,做了什么特殊的配置我们是很难控制的。

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

但是在容器云的时代我们完全不管这些了,每一次的容器发布都是做重新的调度,每一次可以给全新的容器,而且确保跟上一个版本完全一样,因为用户没有权限做修改。这到底有什么好处呢?假设我本来有十台虚拟机,很难说把某台数据机腾出来,因为虚拟机的迁移成本比较高。

3、组件服务化(mysql/kv/mq/)or PaaS 化

二、携程容器云运维实践2.1 面对的挑战

应用所需要依赖的很多组件能够变成服务化,AWS 或者阿里云也做了很多这种服务。携程内部也在尝试把一些公共组件服务化,例如,MySQL,Redis,RabbitMQ 等。

容器云面对各种各样的挑战,从基础设施角度来讲,我们要集成计算资源的合理管理,还有存储的管理。存储的管理现在用 Ceph 来做的。

拿 MySQL 为例,我们让用户可以在测试环境快速部署 MySQL 实例,并且可以选择性的将测试数据灌入。新建的 MySQL 实例也会自动在数据访问中间件中完成注册,方便开发人员、测试人员快速搭建测试环境和测试数据。

从网络层面IP的数量其实会有指数级的上升,虚拟机的时代可以单机多应用,会把部分部署在同一个虚拟机上,容器我们强制是单容器单应用,因为每个容器只能是由一个镜像导出来的,这一块只能强制用一个代码。

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

我们目前网络架构是单容器单架构,这样导致容器的数量比较多,IP数量也会多十倍,这样要上一套 SDN 的管理方案来进行多个 VPC 的隔离,传统虚拟机的管理方式已经不够用了。

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

第二个挑战也是每个做容器云遇到的挑战,也就是资源隔离相关的问题。每个业务的峰值是不一样的,如何保证每个业务容器CPU需求和网络流量突发过来的时候,它不影响其他的应用?这也是非常大的挑战。由于容器本身的特性,假设你用GBM自带的值取Disk的值,是获取到宿主机的值。这个 Defunct Process 是一个比较好的值,这时候重启机器的话,一个容器出现了 Process ,剩下的容器都要被迁移走。

三、容器部署基本原则单容器单应用单容器单 IP,可路由的 IP容器镜像发布immutable infrastructure容器内部只运行 App,所有 agent 部署在host 层面-包括监控/ES/salt等agent

还有如何平衡好 CPU Throttle Time , Throttle Time 出现的时候也就是代表某一个容器没有办法申请时间段,几毫秒可能变成了几十毫秒。现在搞容器云投入专人来研究内核,因为容器的特性导致系统调用对内核增加额外系统调用,在3.10内核上造成各种容器相关的 systemd ,一旦出现内核死锁它的影响就很厉害的。还有多个版本升级非常快,从1.6到1.7、1.8到后面11.0、18.0,我们是否跟着升级每一个版本?还有解决遗留Bug,是否跟着社区的步伐?如果单独维护分支的话,没有BAT公司规模的话,从人力资源来说是比较难有这样的投入。

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

2.2 基础运维

比如单容器单应用这个原则,历史原因我们有混合部署的情况,单个vm部署多个应用,运维的复杂度会上升很多,比如:应用之间如何做到更好的资源隔离?发布如何避免相互之间的冲突?等等。

刚才说了一些运维的挑战,回到运维基础来说,我们做了四个方面运维相关的事情。宿主机用的是 Centos 7.1 和 Docker 1.13 版本,Kernel 用的4.14的版本,曾经用的3.10有太多的Bug也没有精力一个一个修了,现在在4.14版本来说坑是最少的。

使得我们的运维工具、发布工具变得格外复杂,开发、测试的持续交付效率也受到极大影响;

容器镜像的管理我们用 Harbor 做的仓库,所有的镜像都是在分布式的存储里,这样保证了它的稳定性,它的容量相对比较大的。

容器镜像发布也是我们做的一个比较大的突破,过去是代码编译成可发布的包,直接部署到 vm 内部,而现在是编译时直接生成容器的镜像,不同环境其实部署的是同一个镜像。

资源隔离目前做的CPU隔离和网络资源的隔离。调度平台前面也介绍了目前三套都是在运行着,逐渐往 K8S 上做牵引。

并且不允许部署之后单独登陆进行配置修改,通过这种方式做到 immutable infrastructure ,保证开发、测试、生产环境的一致性,同时也保障了自动化扩容、缩容快速高效的进行。

2.3 运维工具

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

从运维工具角度来说,配置管理工具我们用了 SaltStack 和 Rundeck 两个比较常用的配置工具,监控告警携程运维团队有一个自研的 Ctrip-Hickwall 工具,开源的是 Prometheus ,稍微做一些配置和改造就可以监控整个云平台各种指标,包括系统层面、调度成功率、资源可靠性都可以搞定。

四、容器编排选型取舍

日志系统也是用的比较主流的技术栈,用 ELK、TIGK 和 ElasticBeats ,可以做日志收集和包的收集,监控告警和日志系统采集的结果会放在中心的数据库,比如说 HDFS 这些存储系统,为 AIOps 的团队提供一个数据的输入。

1、OpenStack

同时我们引入了一个 StackStorm 的软件,在尝试用 ChatBot 的实践,也达到了比较好的效果。

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

2.4 运维流程

我们早期的胖容器(把容器当 vm 来使用,做代码包发布)的确是用 OpenStack 来做的,原因是我们希望把注意力放在容器本身,以最低的代价将容器先用起来,积累开发、运维经验;

从运维流程来讲,所有的运维标准都是通过 SaltStack 来安装的,包括3.10内核和4.14的升级。我们会和容器云做的比较好的公司,比如说阿里、京东、网易做一些学习和交流。我们主要从三块关注容器平台是否做变革,效率、成本、创新。

而到了瘦容器阶段(基于容器镜像做发布),我们发现 OpenStack 整体的设计理念从本质上讲还是为虚拟机隔离粒度的虚拟化方案设计的,而容器本身与 vm 其实差别很大,玩法也相去甚远, 于是我们对 Mesos/K8s 进行评估;

刚才提到了工作流的工具 StackStorm ,它跟传统化运维有些区别。我们整体工具都是用 StackStorm 实现的,它主要是做日常的排障以及云平台持续交付的功能。其中聊天机器人也会跟 StackStorm 工具做集成,可以提高排障的效率。

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

我们写一些脚本关注 OpenStack ,我们会针对 OpenStack 写一些运维的工具。这个工具在容器云的时代是可以被继续用的,它都会被定义不同的 Action ,让我们的运维流程处于不断完善的过程。

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

上图是我们的一个聊天机器人的例子,普罗米修斯对接的机器人,这个机器人对接都会为云平台各个服务做采集,比如说发现了 ChatOps 坏掉了,他会发送到 CdosBot 。它可以跳转相关环境的监控页上去,看一下到底发生什么样的事情,判断故障是什么原因导致的,回复一个消息给机器人,故障从发生以及相应处理是有纪录的,这样就可以很全面的做一个知识库,新加入团队的工程师可以翻聊天室看一看历史上出现了哪个故障,是否有预案应对?

图3

这一块每个业务容器发布失败三次,基本上可以认为是云平台本身的问题导致的,那就需要工程师看一下错误日志,这种错误是很难处理的,但是我们可以让工程师很快发现问题,因为我们把所有相关的错误日志汇总在一个页面,通过点击连接,工程师可以快速把故障建立一个关联。

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

最终的目标还是要往 AIOps 上走,能够自动把日志分析好,判断出故障的原因,在 AIOps 最终落地之前,我们这样的 ChatOps 也为他们提供比较好的数据来源。你事情没做好就是你的问题,事情做好了是应该的。让组内的工程师有干活的动力,我们让他们在 ChatOps 方面充分发挥,对他们来说也是一个知识的传承和工作总结,他们干活也会比较有动力一些。

2、K8S

这里总结一下我个人认为 ChatOps 的好处吧,对于老板来说每个团队都是有困难的,每个团队都是希望招人的,但是往往很难。

K8S 有很多很先进的设计理念,比如有 replication controller/Pod/Yaml 配置管理等,但这些理念在携程都很难落地,因为跟现有的运维模式、发布流程有较大的冲突。

运维工程师也不愿意做去重复的 routine task ,我会跟他们说你们去招聘一个机器人,工程师觉得你这样说也不错,我们的 ChatOps 的工具也提供了这样的可能,对团队协作方面也有很大的提升。

而且当前还缺乏大规模部署案例,网络尚无比较成熟的方案, 例如 L4/L7 负载均衡; 而在携程 L4/L7 服务已经比较成熟稳定, 并且与我们现有的发布系统Tars集成得非常好;

之前也有做工具,有自己的运维平台、运维工具都很丰富,它可能没有那么强的积累和分享的能力,只能在系统日志里看出端倪, ChatOps 会在聊天室里留下记录。

3、Mesos

2.5 关注变化

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

我们容器云运维最关注平台发生的变化,因为平台的变化往往都是故障的先兆,对于异常的事情需要让工程师做深度的挖掘,往往是暂时没有出现影响业务的异常,在深度挖掘之后会是非常大的坑,在不久的将来就会让业务受到比较大的影响。

图4

我们鼓励工程师花时间做深入挖掘而不是满足正常运行就可以了,灰度运行一定要落实的,这个时候也需要提供工具让工程师落地灰度变更,通过流程和工具来做保障。我们会组织一些会议回顾近期踩过的坑,有时候需要把节奏慢下来,在今年年底之前需要把所有宿主机干掉,在这样的工作压力下,也不能让节奏变的太快,也需要不同的回顾。实现关注变化的技术手段依赖于各种监控系统、巡检工具以及 CI/CD 的工具链。

五、容器网络选型Neutron+OVS+VLan

上图是我们镜像的监控,我们认为一个镜像服务维护的水准是一个容器云运维能力非常重要的指标,因为镜像对于容器来说特别关键。我们会从每个数据中心建立一个单独的 Harbor 集群,让用户从第二个备份的数据中心拉容器,第二个数据中心出问题也会有保障,它的带宽变化、相应时间变化都会有分析。

-DPDK

容器云的网络也是我们特别关注的一个点,这个指标会去看每一个端口创建的时间,包括IP资源的情况都会做单独的监控。

-硬件加速

2.6 关注趋势

-单容器单IP,可路由

前面讲的是关注变化,关注变化算是比较基础的一个工作,因为做运维的工程师都会关注我们是否有告警,平台是否有变化,而趋势往往会被工程师所忽视。我们关注趋势可以设定长期目标,让运维工作比较有计划性,运维工作有计划性是非常重要的,怕就怕的是运维工程师每天都在处理突发的工作,没有时间对你管理的平台做前瞻性的规划,把事情做在前面,不要把压力留给自己。所以需要建立技术储备,让工程师有一定的前瞻性,必须要在异常真正发生之前能够解决潜在问题。云平台的组件实在太多了,包括存储、计算每一个环节都会出现问题,监控做的太细的话,让你淹没在日常事件里,核心的指标会被忽视,用户关注的是整个服务的交付的速度和服务整体的可控性。我们目前用的是 TIGK 、StackStorm 、SaltStack 和 ChatOps 。上图是我们做的机器负载变化趋势的看板,可以快速帮助我们发现某一个集群的利用率,这个集群CPU还是比较富裕的,它的内存也只有71.47%。我们会做一些分析,看看是不是给他分配的容器太多了。像左下角这些宿主机要主动的维护,持续增加的话机器某一天就会坏掉了,造成非常大的影响。

vxlan+SDN controller

这是应用维度的变化趋势,像这个应用在线容器数有三百个,但是CPU的表现是很稳定的,CPU突然出现50%左右的增长,我们也会告警他是否做一些分析或者扩容。

-vxlan offload TOR 解封装

2.7 容量管理

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

下面介绍一下我们的容量管理,容量管理往往是老板比较关心的,因为涉及到花钱。每个季度到底投多少钱买宿主机?动态调度的能力有没有?应用有波峰和波谷的,尽量把波峰的应用挫开,我们需要对它进行资源使用情况的预判,这样才能实现弹性计算。

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

为了实现容量管理我们主要借助了监控系统、 Hadoop 平台以及自己运维的监控工具,最终通过 PAAS 平台实现容器弹性的调度。最终目标是把资源合理利用出去,同时又保证一定的稳定性。

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

这是我们容量的整体情况,会发现它的内存基本上用的非常满,这个集群它的CPU资源也是用的比较满,我们会从一些维度去做整体的分析和个别的分析。

如何配置容器网络

三、总结与展望

图 5

前面基本上就是运维大概做的所有事情,下面简单说一下我个人的思考。之前做 OpenStack 私有云的管理,做完之后我们要把运营工具做成产品化,不能用工具的思维做事情,这样不能很好的解决用户的问题。

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

所以我们现在也是在尝试做一些日志产品和监控产品,在云原生的 DevOps 工作方式。我们运维人还是要以用户至上的,整体出发点保证平台稳定、持续、高效运行。还有一个总结是对 ChatBot 与事件的整合有比较好的效果,一方面让事件可追溯,另外一方面让工程师有更好的热情。

六、Docker遇到的问题

展望团队工作的话,接下来会有混合云运维的实践,携程这些采购公有云的产品,阿里云、AWS还没有做很好的整合,下一步把混合云管理起来,真正做到云原生。另一方面业界都在转 Kubernetes ,但还要进行思考,在 Kuberentes 时代下一步要做什么。做容器云的价值就是实现了弹性计算,而我们要在弹性计算这条路上做更多的事情,真正体现出容器的价值。

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

1、Docker Issue

图 6

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

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

2、Mesos Issue

running 的容器数量较多以后,无法再启动新的容器kernel.keys.root_maxkeys debian default 200,centos default 1Mmesos docker inspect 执行低效,尤其是单机容器数量大MESOS_GC_DELAY:6h 20K-1hMESOS_DOCKER_REMOVE_DELAY 1mdocker force pull falseAPI 性能差,功能不完善,获取异步 event 困难overall,很稳定,调度性能足够

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

3、CExecutor

图7

1)自定义 CExecutor,Go 语言实现

避免过于频繁创建删除容器,带来的副作用;cpuload 高而且抖动很大;频繁启停容器引发的 docker 和 kernel 的 bug;

2)task:container

-1:1 - N:1

3)容器持久化

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

七、容器监控方案

1、Mesos 监控

图 8

图 9

如图 8-9 携程用了很多开源技术,Telegraf、influxdb、Grafana 并做了一些扩展来实现 mesos 集群的监控,采集 mesos-master 状态、task执行数量、executor 状态等等,以便当 mesos 集群出现问题时能第一时间知道整个集群状态,进而进行修复。

此外, 我们还从 mesos 调度入手,做了一些应用层的监控,比如: 针对 cron job 类型的应用,让用户可以看到 job 应该在什么时候执行,执行的过程,整个 job 的成功率,job 还有多个实例在跑等;

2、容器监控

图 10

携程监控团队全新开发了一套监控系统 hickwall,也实现了对容器的监控支持;hickwall agent 部署在容器物理机上,通过 docker client 、cgroup等采集容器的运行情况,包括 CPU 、Memory、Disk IO 等常规监控项;

由于容器镜像发布会非常频繁的创建、删除容器,因此我们把容器的监控也做成自动发现,由 hickwall agent 发现到新的容器,分析容器的label信息(比如: appid、版本等)来实现自动注册监控;在单个容器监控的基础上,还可以按照应用集群来聚合显示整个集群的监控信息;

除此之外,携程还做了各个业务订单量的监控,比如说今天有多少出票量、酒店间夜数,而我们可以非常精准地根据历史的信息预测未来的数据,比如说明天的这个时间点订单量应该在多少、准确性在 95% 以上,一旦比预估的偏差太大的话,就会告警有异常,它把一个综合的业务运行健康度提供给业务研发团队,而不仅仅是单个容器的运行情况。

我们在线也会做一些压测,比如说这个集群下面有 10 台机器,这 10 台机器的负载均衡权重都是 0.1,我们会把其中一台调高,看它的吞吐和响应的情况。测出它到了一定极限能提供的 QPS,就可以知道这个集群还剩多少性能高容量,这个容量就是这个集群还能承载多大的压力。

比如说有 25% 的富余,根据订单的变化就可以知道还多多少或者还缺多少,这样就能做到更好的扩缩容调度

目前基于 vm 的应用已经能基于容量规划和预测实现自动扩容,后续容器的扩缩容也会接入,并且做到更实时的扩容和缩容调度;

此外,容器监控对于携程创新工场的团队是很有意义的,这些新孵化的BU对成本控制更严格,随着容器上线,我们能为其提供性价比更高的基础设施。

八、CDOS Overview

图 11

CDOS 全称是 CtripData Center Operating System, 我们希望通过 CDOS 来调度多个数据中心的资源,就好比一个操作系统调度各种资源给各个进程一样,CDOS 会调度多个数据中心的计算、网络、存储的资源给到不同的应用,满足各个应用所需的冗余度,并且会动态的维持这个冗余度,一旦出现异常,可以自动尝试修复,删除出现问题的容器实例,并部署新的实例;这里面会涉及到非常多的模块。

如图 11 最上层是持续交付的发布系统,这一层是跟应用交付相关的东西,开发人员、测试人员都会用的发布系统。下面是针对不同运行模式的应用定制的两套调度管理模块,一个是 cron Job,另一个是 long running service;两者在管理、部署、发布方面都有一些差异化;

底层资源分配是用 Mesos 来实现,历史原因,我们还有大量的服务部署在 windows上, 因而需要同时支持 windows server container 和 docker。长期来看未必是继续使用 Docker,因为 Docker 太激进了,目前已经有多种 container 实现方式可以选择。

Windows 容器方面携程也已经做了一些 POC,实现类似前面提到的 ovs + vlan 的网络接入,遵循单容器单 ip 等原则,并且投入覆盖了部分的测试环境。

图中右边有很多服务,比如 L4/L7 负载均衡、 SOA 的服务,CMS 应用元数据管理、监控、日志收集、镜像管理和推送等模块;

由于我们采用容器镜像发布,要实现秒级交付,对于镜像推送速度有很高的要求,当 base image 没有变化时,只需要把应用新版本 build 出来的 app 层通过我们开发的 Ceph 同步模块推送的多个数据中心;

当 base image 也变更时,情况会更复杂,除了同步到各个数据中心的 Ceph 对象存储,还需要预先下发到可能用到的 Docker 服务器,才能以最快的方式启动容器。

作者:吴毅挺

文章来源微信公众号:高效运维

本文由澳门威斯尼人平台登录发布于服务器&运维,转载请注明出处:我们是如何利用容器实现快速弹性伸缩的,携程万台规模容器云平台运维管理实践

相关阅读