DockOne微信分享(一零四):艺龙部署体系的演进

本文讲的是DockOne微信分享(一零四):艺龙部署体系的演进【编者的话】随着公司业务规模的逐渐扩大,传统的基于机器层面的部署系统在面对服务扩缩容、故障迁移、成本控制等方面已经越来越力不从心,于是,我们开始将容器技术与当前公司内部已有的自动化运维体系相结合,来实现一套艺龙的容器云平台,以期解决上述问题。

原有部署平台的架构设计

在讲解部署系统之前,我先给大家讲一下目前艺龙自动化运维的业务模型。早期艺龙的运维,因为规模较小,通常人工处理,当规模大了以后,就开始尝试基于Puppet等脚本的方式操作。随着规模的进一步扩大,逻辑需求的增加,使得原有的这种基于行为的模型很难更高效的进行管理。

因此,我们抽象出服务这个概念,用户对服务做出定义,服务之间采用树形关联,服务节点上挂载元信息,而机器也是元信息之一,因此,新的模型就变为人去定义服务,而服务去关联机器。无论上线,监控,还是日志收集,都是基于服务粒度的,而不再需要关注底层的机器。

在服务树的元信息之下,是这套系统的核心部分,控制系统。控制系统有两部分,一个是由erlang-OTP编写的控制中心,它负责将任务下发给像相应的客户端,并控制任务运行的流程,比如串并行、暂停恢复等,一个是每台机器上运行的客户端,负责具体执行逻辑。

控制中心采用了我们自主研发的一套基于Raft的分布式库进行开发,整体采用主从结构,主写从读,保证强一致性,当主节点宕机后,执行中的任务仍然能无缝的迁移到从机。客户端执行的任务是以插件形式开放的任何可执行应用,控制系统整体平台化,依赖于这个特点,我们在控制系统之上开发了很多业务系统,比如部署系统,就是通过部署插件来完成的。

控制系统图

我们基于控制系统开发了一个部署插件,用户将已经打好等待部署的代码上传到FTP上固定的位置,然后调用部署API对某个服务触发一次该版本的部署操作,控制系统就会根据用户定义的控制策略下发给相应的服务器上的客户端,客户端执行部署插件,由插件进行包下载、解压、部署、启停等操作,完成整个上线。

上线图

我们的整个部署架构如下:

部署架构图

基于容器化的部署平台架构设计

当前的自动化部署体系已经能够实现系统的快速部署,但是,由于公司规模的发展,服务的规模越来越大,硬件设备购买和运维的成本也都越来越高。同时,对于电商网站,经常会遇到比如黄金周,双11,抢红包这种请求量的突增的情况,对于系统能够随时快速的扩展,以及过后机器快速回收就提出了要求,因此,为了更进一步,我们要解决两个问题:

  1. 弹性扩缩容
  2. 控制规模化成本

通过解决这两个问题,我们想在最终够实现,在任意云平台或IDC,做到全服务快速迁移的目标,也就是将艺龙的运维体系打造为可以依托任意IaaS的混合云模式。

对于服务的快速迁移部署,最终会落地到两个关键问题的解决上:即上下游依赖,以及环境依赖。我们通过容器化应用以及名字服务来解决上述两个问题。

对于一个已经有一定体量以及基础架构设施层面已经比较完善的公司而言,推广层面的问题要比技术层面的问题更加棘手,我们有万这个级别的机器在线上运行,因此并没有直接使用Kubernetes之类,因为改造、迁移成本过高。因此,我们将Docker与当前自动化运维体系中的各个业务系统打通,从而减少业务的迁移成本。我们希望的是将Docker视为一种打包方式,而不是重度依赖整套体系。我们的目标是在解决业务痛点的情况下,简化设计,最小依赖,降低迁移以及运维复杂度。

最终,我们的系统架构转变如下:

部署架构图 2

从图中我们可以看到,我们的改造很简单,在原有体系的基础上,增加了三个主要部分:

第一个是镜像构建系统,用来屏蔽掉底层容器,我们依旧复用了FTP以及全量部署的结构,改变的仅仅是打包方式。用户操作流程不变,只是在触发部署操作时,系统会检测该代码版本是否有已经构建完毕的镜像,如果有则直接部署,如果没有,则进行构建。

另外一个增加的部分是资源调度系统,这个系统只去做资源调度,也就是资源的筛选和分配。它直接和运维的CMDB挂钩,负责管理公司所有的机器。用户部署时描述资源需求,资源调度根据需求分配机器,然后下发控制系统进行部署。

我们并没有做动态调度,也没有去做故障的自动迁移、资源自动调整迁移等,因为对于我们来说痛点是快速迁移。并且目前整个系统处于推广中,稳定性重要于功能性,尤其是网络抖动等层面非常容易导致动态调度工作异常。

第三个就是每个机器上的插件了,我们新开发了容器部署插件,主要功能就是在机器上获取镜像,然后启动容器。

根据我刚才描述的整个流程,我们做到了在业务无感知的情况下,将基于机器的部署转变为基于容器化的部署,当然,在这一过程中我们还打通了监控、配置管理、日志收集、门神(安全登录)等等,就不细说了,有兴趣的可以私下沟通。

上面我主要描述了对于环境依赖我们的解决方案,接下来,我来给大家介绍一下我们的上下游依赖解决方案。

服务发现与名字服务

对于服务发现层面,我们总结了几种常用的手段:

  1. 基于配置文件,类似Confd之类的配置文件模板方式
  2. 基于SDK
  3. 基于getHostByName+DNSd方式

我们起初最先考虑的是基于SDK的方式,服务注册与发现统一由一个类ZooKeeper的服务提供,这里可以稍微提一下的地方就是,我们采用的是一个基于Raft的Pyxis服务,也是我们部门自研的服务,并没有用开源的ZooKeeper以及etcd。

一是由于ZooKeeper基于Java编写,在GC层面存在一定的问题,数据量过大时候会导致服务可用性降低(我们希望基于它同时做配置管理),二是我们阅读了它的源码,它的Recovery在检测不一致时处理也比较暴力,同时ZAB协议较复杂,这个从它的论文上就可以看出来,因此运维起来成本较高。

而etcd在我们调研Paxos以及Raft时还刚刚起步,用户较少,因此在当时我们选择自己开发一套类似于ZooKeeper的分布式协调服务。

回到刚才的话题,如果是基于sdk的方式,那么必然要求对调用方甚至被调用方的程序要有一定的侵入性,这种侵入性存在一定的风险,而且公司内部目前也存在着不同的语言版本(PHO/C#/C++/Java......)、甚至不同的操作系统环境(Windows/Linux),推广起来难度极大,因此,SDK的方式最先被否决。

最终,我们决定采用研发一个名字服务Agent来实现1、3两个方案,即配置文件以及DNSd的方式来解决上下游依赖问题。

我们的名字服务Agent运行在所有的Docker容器以及每一个拥有服务的物理机/虚拟机上,提供服务注册以及发现的功能,每个服务需要编写它的描述文件,其中描述了服务的名字、端口、用户的配置文件存放路径、用户的配置文件模板存放路径等信息。

同时,我们要求每个服务必须有4个脚本文件,即启动脚本、停止脚本、服务健康监测脚本以及服务Reload脚本。当服务启动时,Agent就会根据描述文件的信息将服务作为一个服务实例的Active状态节点注册到相应的服务名字下,同时定期调用健康监测脚本来作为踢出负载和报警。

服务启动时用户会在配置模板内描述要关注的名字,当名字对应的机器列表发生变更时,Agent便会拉到最新的名字对应的实例数据,然后实例化模板为新的配置文件,并调用应用的Reload脚本(类似Confd)。

通过配置文件的方式,我们实现了七层负载均衡与名字服务打通,实现了基于Nginx层面的上下游服务解依赖。

我们提供的另一种方式就是基于DNS的方式,即我们对每一个用户创建的服务名字自动创建一个域名,比如我们有个服务是hotel,该服务的名字也叫做hotel,那么我们就会为该名字生成一个类似域名hotel.ns.corp.elong.com的域名。

我们将名字服务与DNS服务器打通,DNS服务器会根据某个域名对应的服务名字下的实例在Pyxis上的存活状态来变更该域名对应的IP列表,而同时,Agent也在这个里面起到了另一个角色,就是本地的DNSd,他会Cache域名的状态,用户的DNS请求会先落到本地的Agent上,Agent根据名字服务的数据进行解析,如果不存在,在继续访问真实的DNS服务器,如果存在,则返回名字服务上该域名对应的名字的实例列表。

一个访问流程如下,UI是用户直接干预基于名字服务的方式。

上述就是我们名字服务的整个工作方式,同时,我们还在这套系统基础上设计诸如同机房流量优先调度、用户强制介入的流量调度、名字服务结合nginx层实现的负载均衡、灰度流量调度等等。

遇到的问题以及解决方案

因为我们对Docker层面的依赖较少,所以就使得我们在这一层面遇到的问题也较少,我整理了两个大家可能都遇到过的问题:

1. 容器rootfs文件系统问题

我们最开始采用的是默认的device-mapper方式作为容器的rootfs,如果应用没有大量的IO操作还好,但是毕竟不是每个用户都能按照最佳实践去做,因此早期经常由于某个服务大量占用IO资源而导致整个宿主机的容器都被影响,

而且由于dm的特性,IO比较差,很容易占满,而且我们也没有那么多的资源去深入调研类似于device-mapper这些分层的文件系统,所以考虑了我们的业务场景,同时我们又是基于ftp的全量拉包,就暂时使用了VFS作为容器的rootfs。

2. 网络问题

我们早期使用了默认的基于NAT的方式,结果遇到了非常多的问题,比如我们在做HTTP的压测时,发现性能无论如何都上不去,看了内核的日志,发现大量的 NAT ip_conntrack: table full,才发现是TCP的Established Connection记录满了。

后来也发生过连接被莫名的关掉,或者是数据包莫名的阻塞很久等问题,debug过程非常耗精力,因此我们就干脆换掉了NAT模式,采用了桥接的模式,不但性能得到提升,而且稳定性更好,同时每个容器一个IP,出现问题也可以直接定位到某个IP,对debug也更加友好。

TO DO

1. 调度层面:我们根据目前的需求并未添加动态调度的功能,等到所有的目前的工作ready,我们会重启这一工作,实现动态扩缩容以及动态故障迁移的功能,让整个平台全自动的运转起来。

2. 名字服务Agent层面:我们目前一个容器内部包含了一个Agent,这会导致每一次名字服务Agent的升级就要牵扯到用户服务也必须跟着升级,这是很难做到的一件事,因此我们现在正在着手将名字服务Agent移到容器的外部。

我们同时也打算支持本地HTTP协议的名字服务Agent作为用户解析名字的一个方式,来代替SDK的方式,watch服务可以用本地Agent回调方式实现。

3. DNS层面的负载均衡:目前的负载均衡我们还是在用户的层面去做的,用户基于我们的系统还只能解析到IP列表,我们之后希望能够将负载均衡也集成到我们的系统中,我们的DNS服务端会做负载均衡的策略,用户解析域名直接就可以得到一个负载均衡后的IP。

4. Windows:公司内部还有一部分服务依旧运行在Windows(.net服务)上,这一方面接下来需要着重考虑。

以上就是我今天分享的全部内容,谢谢大家,大家有自动化运维层面的相关问题,都可以和我交流交流哈~

Q&A

Q:麻烦问一下,桥接的网络是给容器的分配一个物理网络的IP吗?另外依据什么来确定每台主机运行多少容器?

A:是的,我们给每个容器分配了一个物理网络的IP,我们根据目前我们物理机的规格去制定的容器数量,目前每台物理机分配上限是64个。

Q:Docker存储考虑过Overlay当时吗?据说这种构建镜像比较快。

A:考虑过,当时也做过各个方面的测试,这种增量式的构建,肯定最快,但是我们需要有专人从源码级别对其进行维护,成本对于我们还是有点高,我们后期打算采用环境和代码分离的方式,即环境部署一次,代码多次部署来提升效率。

Q:.net不是也可以跑到Linux上了吗?有.net镜像吧?

A:我们调研过,但是这个技术太新了,稳定是我们使用一个新技术的前提,而且我们的.net服务大多已经是很多年前的老服务,折腾起来比较费力,暂时.net方面我们只能搁置,但是也会继续跟进。

Q:请问没有采用ZooKeeper和etcd而选择自研的原因是什么?是否如何进行技术对比的?

A:就是我刚才说的,对于ZooKeeper来说,ZooKeeper基于Java编写,在GC层面存在一定的问题,数据量过大时候会导致服务可用性降低,我们希望用他做配置管理,我们甚至有一些上M的配置文件,最终的配置无论是配置项,还是最终大小,都会是一个比较大的量级。二是我们阅读了它的源码,它的Recovery在检测不一致时处理也比较暴力,同时ZAB协议较复杂,这个从它的论文上就可以看出来,因此运维起来成本较高。

而etcd是基于Raft实现的,Raft是14年出的论文(我没记错的话),我们就是在论文出来第一个月开始弄的,也就是说那个时候etcd也刚起步。

以上内容根据2016年12月20日晚微信群分享内容整理。分享人董春明,艺龙旅行网基础架构部容器云平台负责人,专注于自动化运维体系的技术与产品化方向。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

原文发布时间为:2017-01-17

本文作者:董春明

原文标题:DockOne微信分享(一零四):艺龙部署体系的演进

时间: 2024-09-19 09:05:25

DockOne微信分享(一零四):艺龙部署体系的演进的相关文章

DockOne微信分享(一四零):Serverless云函数架构精解

本文讲的是DockOne微信分享(一四零):Serverless云函数架构精解[编者的话]继虚拟机,容器技术之后,无服务器化成为新的行业热点,无服务器云函数可以让用户无需关心服务器的部署运营,只需开发最核心的业务逻辑,即可实现上线运营,具备分布容灾能力,可依据负载自动扩缩容,按照实际调用次数与时长计费.本次主要分享腾讯云无服务器云函数在技术实现上的挑战及架构实现原理. [烧脑式Kubernetes实战训练营]本次培训理论结合实践,主要包括:Kubernetes架构和资源调度原理.Kubernet

DockOne微信分享(一四二):容器云在万达的落地经验

本文讲的是DockOne微信分享(一四二):容器云在万达的落地经验[编者的话]容器生态是现在非常火热的技术生态之一,个人认为它主要囊括着四个方面的技术栈:一是容器核心技术栈(包括 Docker.rkt 及第三方公司自主研发的容器 Engine 等):二是容器基础技术栈(包括容器网络.存储.安全及服务发现等):三是容器编排技术栈(包括 Mesos/Marathon.Swarm.Kubernetes 及 OpenShift 等):四是容器应用技术栈(主要包括 CI/CD.监控.日志及微服务框架等).

DockOne微信分享( 一零一):构建容器服务平台(CaaS)

本文讲的是DockOne微信分享( 一零一):构建容器服务平台(CaaS)[编者的话]容器技术作为这两年最令人瞩目的技术,在各个行业无论是互联网还是传统行业都得到广大的应用.作为致力于打造金融行业领先的平安云,于今年引进容器技术,研发平安云容器服务平台,吧容器技术应用到业务中,推动业务和技术快速发展.本次分享的核心内容即是从用户 痛点及特征分析想如何构建平安云容器平台.分为4个部分: 容器平台定位 容器平台设计 容器平台架构 容器平台设计技术 一.定位 用户 首先平安集团旗下的子公司包含了金融行

DockOne微信分享( 一零二):基于容器的日志管理实践

本文讲的是DockOne微信分享( 一零二):基于容器的日志管理实践[编者的话]业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集.存储以及告警等方面的实践经验. 2013年以来Docker迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控.日志.网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验. 基于ELK的日志管理系统架构

DockOne微信分享(一四三):FreeWheel基于Kubernetes容器云构建与实践:应用编排与服务质量保证

本文讲的是DockOne微信分享(一四三):FreeWheel基于Kubernetes容器云构建与实践:应用编排与服务质量保证[编者的话]随着公司业务不断发展以及逐渐向微服务的转变,我们借助于Kubernetes容器化解决方案来标准化和简化应用发布的整个流程,使原来需要大量人工维护和干预的工作变为自动化.本次内容主要是FreeWheel现阶段基于Kubernetes容器化经验和实践的总结,目标是提供一个持续.稳定.高效的容器云平台. 服务健康检查与自我恢复 对线上业务来说,保证服务的正常稳定是重

DockOne微信分享(一二四):轻松筹监控系统实现方案

本文讲的是DockOne微信分享(一二四):轻松筹监控系统实现方案[编者的话]监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况.虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化.这样既可以更灵活的满足自身业务的监控需求,也可以为以后自建机房提供技术积累.通过以下7个方面来建设监控系统. [3 天烧脑式 Docker 训练营 | 上海站]随着Docker技术被越来越多的人所认可

DockOne微信分享(一一零):Docker在沪江落地的实践

本文讲的是DockOne微信分享(一一零):Docker在沪江落地的实践[编者的话]容器化是很多公司技术层向往又惧怕的一项热门技术,它的高效性,封装性能给开发.运维带来许多便利,但其本身也需要较强的技术能力去控制,否则会变成一个无法落地的概念.沪江作为教育界的独角兽,随着业务的增长,在开发.测试.运维上的成本增加日益显著.经过我们一年的探索,终于使Docker技术在沪江落地,不但成功的降低了成本,并吸引了其他部门的关注与试用,取得良好的成效. [上海站|3天烧脑式微服务架构训练营]培训内容包括:

DockOne微信分享(一零六):乐视云基于Kubernetes的PaaS平台建设

本文讲的是DockOne微信分享(一零六):乐视云基于Kubernetes的PaaS平台建设[编者的话]本次分享主要介绍乐视云两代PaaS平台的变迁过程,着重介绍第二代PaaS平台LeEngine的架构设计和遇到的问题. 背景 2014年乐视云开始尝试Docker的推广和使用,我们的团队开始开发第一代容器云平台Harbor (分享网址:http://dockone.io/article/1091 ).(在这里提醒一下,这与VMware公司中国团队为企业用户设计的Docker Registry e

DockOne微信分享(一零九):中小型团队的容器化之路

本文讲的是DockOne微信分享(一零九):中小型团队的容器化之路[编者的话]GrowingIO是基于用户行为的新一代数据分析产品,提供全球领先的数据采集和分析技术.企业无需在网站或APP中埋点,即可获取并分析全面.用数据驱动用户和营收的增长.为了应对高速变化的业务增长,我们在系统设计之初就采用了微服务的架构,获得良好的可扩展性.随着时间的推移,微服务的缺点也渐渐体现,人肉运维的成本太高,导致研发效率下降.作为一个中小型团队,我们经过了半年的探索,使用容器相关技术来搭建团队内部的私有PaaS,取