问:可以简要介绍下知乎现在的Docker研发及使用情况吗?
林晓峰:知乎平台架构团队,采取研发和运维一体的DevOps模式;其中容器平台项目组目前的人数是2.5人。知乎几乎全部业务和服务(100+)都运行在容器平台(Bay)上,服务器资源申请已经对业务部门关闭。在业务峰值时段,平台整体容器数量会动态扩容到接近万个。
问:是在怎样的情况下,知乎选择了Docker?它是否帮你们实现了所有的预期目标呢?为什么知乎认为使用容器方案是“重要决策”?
林晓峰:随着知乎业务的增长和微服务化的演进,越来越迫切的需要解决三个问题:
1. 环境隔离:在物理机时代,由于每个业务依赖的系统环境不同,服务器之间无法通用,服务器负载也各不相同;各个业务都需要独立管理服务器容量,处理服务器故障,对业务开发造成较大负担。
2. 精细资源隔离: 服务隔离要求按照服务接口对进程物理隔离,防止因为某一个接口而影响整体服务的问题,同时也需要根据不同接口的特性,设置不同的进程数、CPU和内存配置,实现更加精细的资源管理。
3. 资源动态调整: 业务需要快速自动适应流量负载的变化。在负载高峰期快速增加资源,保证业务服务质量;在负载低峰期释放资源给其它服务,提高集群资源利用率。
上述问题抽象出来,其实需要一套高效的资源管理和调度系统。
容器技术可以帮助我们实现应用环境的封装隔离以及CPU、内存等资源限制;结合集群管理方案,能够实现资源的统一调度和动态调整:由此解决上述三个问题。从而实现业务开发人员可以专注开发业务逻辑,而资源调度和管理、负载监控、服务器故障等处理统一交于平台自动处理或者在必要时人工干预。
知乎容器平台(Bay)建设和实践到现在,从最初“邀请”业务迁移到容器平台,到现在业务要求使用容器平台,间接证明容器平台实现了预期目标。总体来说,容器平台有力的支撑了知乎的微服务化和迅速增大的业务规模,已经成为知乎基础架构的重量级组成。
问:能否介绍下知乎在搭建Docker平台架构时,是怎样考虑Docker运维模块的?
林晓峰:在搭建 Docker 平台时,我们的一个主要理念是DevOps,通过这种模式来解决各个层面的运维效率问题。
1、对业务用户层面,容器平台明确业务开发能够完成的工作都由业务开发人员来操作,如日常的服务发布、配置变更。通过这种方式,既充分满足业务开发人员操作的便捷性,同时也减轻平台维护人员的日常工作量。
2、对平台内部层面,也是通过开发的思路来解决运维问题,即日常的处理尽量自动化完成。以下面三类情况举例说明:
容器集群扩容:在新服务器安装系统时,会运行 Salt 配置、安装并运行 Docker 相关后台进程和Mesos-Slave节点,这样机器就自动加入到了容器集群。
服务运行的容器数量:可以通过预定义的指标实现自动的伸缩,业务流量增长和正常的流量波动无须人工调整资源。
个别容器或者服务器故障:我们认为它是一种日常的、节点级别的“正常现象”,对其进行自动处理,而不是作为异常情况报警等待人工干预。相对的,容器组和集群整体的健康情况才是平台维护人员的关注对象,具体细节可以参考文末阅读原文链接关于容器云平台的演讲稿。
问:Docker的使用都给知乎运维带来了哪些挑战?可否介绍下针对这些挑战,知乎采取了怎样的措施?
张阜兴:总结而言有三大挑战:
容器平台的工作负担加重
系统的整体复杂性增加
某些异常情况出现
首先,原本由业务本身负责的系统运维工作转交给了容器平台(如业务资源变更,物理机异常处理等),加重了容器平台的工作负担。对此知乎的解决方案是:一方面通过设计集群的容错机制,自动处理物理机故障,避免人工响应;另一方面,总结业务通用的需求,例如业务容量的动态调整,开发新的平台功能来满足。
其次,Docker 集群方案引入了一些其他系统组件,如Consul,HAProxy,Cadvisor,Graphite 等,增加了系统的整体复杂性。同时Docker本身还在快速发展,存在各种不稳定因素,相比于成熟的物理机运行环境需要处理的异常更多。为了解决此问题,知乎采用的措施是:针对容器平台的特点,合理使用这些系统组件,简化调用方式,例如在使用Consul做服务发现时,使用了Consul的kv功能来实现实例的批量注册和反注册。对于 Docker 自身的问题,一方面借助社区力量修复BUG,另一方面通过开发一些工具来处理。例如Docker网络方案在使用Iptables时会存在配置清理失败的情况,我们分析原因后,定制了Iptables系统包,避免了这种情况。
最后,随着容器平台集群规模的增大,某些异常情况出现的概率大大增加,某些组件的性能瓶颈逐渐暴露。对此,知乎的解决方案包含三个部分:一是在设计阶段尽量避免性能单点,如 Docker Registry默认为单机版,我们改用 HDFS 作为其存储后端,实现了Registry的分布式水平扩展。二是在预估的集群规模下进行充分的压力测试,例如验证单机能够容纳的容器数以及启动速度;三是监控集群性能,在接近性能瓶颈时及早报警发现。
问:现有Docker几个监控开源方案,比如Prometheus、Sysdig、cAdvisor,你们有研究或使用过吗?如果有,可否评论下这些开源方案?
张阜兴:在使用容器前,知乎已经有了一套比较完善的监控系统,采用的是Statsd(采集)+ Graphite(存储)+ Grafana(图表展示)+ Halo(自研报警系统)。这套系统已经能较好的满足知乎业务运维需求,因此容器平台监控主要是采集指标与这些已有的系统进行整合。
对于这三个监控开源方案:
Prometheus的指标存储,展示,报警等功能与知乎已有系统重合,整体替换风险较大,所以未做考虑。
Sysdig 是一个将各种调试工具集成在一起快速诊断应用行为的方案,但是不适合做常规指标监控使用。
我们采用了cAdvisor 作为容器指标收集工具,并根据业务需求对 cAdvisor 进行了定制开发,实现了容器指标与已有监控系统的整合。
问:知乎是如何实现的Docker及Docker集群的监控呢?
张阜兴:我们使用 cAdvisor 收集容器指标,存入 Graphite,前端使用 Grafana 展示,通过自研报警系统 Halo 发送报警。
具体监控指标分为如下几类:
业务容器实例监控:容器的 CPU、内存、网络、磁盘;
业务容器组监控:容器组内容器重启次数,容器组内健康容器比例等指标;
平台层面监控:Mesos 集群指标,Docker 进程及附属组件状态等监控;
服务器层面监控:服务器的 CPU、内存、硬盘、网络等指标。
监控的意义在于及早发现问题,要避免和减少监控对服务的影响。作为一个 DevOps式的平台,应该将合适的监控报警发送至合适的人员,比如业务层面的指标会通知业务开发人员处理;而平台和服务器层面的报警发给平台维护人员,同时还应该设置合适的报警阈值,避免无效报警带来的干扰。
问:能否说明当一个Docker容器服务发生故障时,平台的处理流程?
张阜兴:对于在线调用的 RPC 服务,一个容器发生故障时,服务反向代理 HAPrxoy 会通过健康检查发现该容器故障,并将流量转发到其它容器;同时Mesos 探测到容器故障后会在服务发现上解注册该容器,并在集群中重新启动该容器:整个过程都是自动完成的。
问:自动扩容的流程又是怎样的呢?
张阜兴:用户开启了自动扩容功能后,监管进程会定时采集应用容器指标,如 CPU利用率,根据一定算法设置合适容器数目,进而完成自动扩容或者缩容。在实际应用中,为了避免定时间隔的滞后效应和负载的震荡,一方面我们会控制定时间隔,另一方面我们采用了“快增慢减”的策略,在负载升高时快速的增加容器,在负载降低时缓慢的减少容器。
问:对于Docker日志处理,你们采用的是什么技术栈呢?
张阜兴:Docker日志处理分为两部分:
业务日志由进程直接写入 Kafka,其他组件通过订阅 Kafka 实现更丰富的日志处理。例如,使用 Flume 订阅 Kafka,并将日志写入 HDFS 和 ElasticSearch。
容器的标准输入输出则通过 json文件写到本地磁盘,从而在进程异常时候,能够通过 Mesos 提供的 url 获取故障信息。Mesos可以定时帮助我们清除过期容器日志,不用担心磁盘空间占用的问题。
问:在整个Docker平台的实践中,两位有什么感触最深的经验或者建议可以分享给其他的Docker使用者们?
林晓峰:Docker 作为一种容器技术,为企业提高产品研发效率和改善基础设施提供了新的思路和方向,应该是作为一个组件融入到企业整体的研发体系中,而不是“革现有研发体系的命”;引入Docker 让某个解决方案变得优雅,而不是为了 Docker 而 Docker。实践Docker,应该在充分理解业务需求和现有基础设施后,找到适合自己的 Docker 的使用姿势,这样才能真正让Docker技术在企业内落地,并服务于业务,实现 Docker 的价值。
张阜兴:在平台搭建过程中,由于Docker本身还在快速发展,不可避免的会存在一些不稳定因素,需要通过上层的容错机制来降低影响。
林晓峰,知乎技术平台团队负责人。负责建设知乎各类基础设施平台、抽象各个基础设施的服务,以及为业务开发提供统一的基础设施平台接入。高性能 Linux 网络协议栈实现 Fastsocket 协议作者。
张阜兴,知乎平台架构工程师。负责知乎内部弹性计算平台,以及知乎容器平台搭建实施和各业务容器化进程。在高性能网络流量处理和分布式存储系统方面有过多年实践经验,目前致力于构建统一资源调度框架,分布式系统设计等方向。
本文作者:林晓峰 张阜兴 来源:聊聊架构
CIO之家 www.ciozj.com 微信公众号:imciow