作者:个推研发专家朱明智
前言:随着以Docker为典型代表的容器化理念逐渐兴起,众多的使用分布式架构的公司和企业,开始考虑对原有系统进行容器化升级。传统分布式架构为什么需要容器化?容器化面临怎样的机遇与挑战?作为智能大数据服务商的个推如何将容器化落地?未来将有怎样的发展?本文以个推在容器化上的实践为例,与大家一起探讨及展望。
传统分布式架构的特点
传统分布式架构系统,一般具有以下两个特点:
一、根据业务和资源消耗的不同,开发者会对传统分布式架构系统进行模块划分。例如:根据业务的区分,个推会划分出不同的系统模块,和手机SDK建立长连接的客户端CM模块,以及负责消息路由的IM模块;根据资源消耗的不同,个推会将多次读写Redis 和多次读写MySQL的用户模块拆开成不同的角色。
二、在传统分布式架构系统中,相同的角色模块会有多个实例。这种系统,一方面做到了高可用性,当一个服务器宕机时不影响整体业务。另一方面,在压力变大时方便通过扩容提升吞吐率。例如:当偏重Redis读写的角色请求较多的时候,系统就只需要扩这个角色的实例。
多年实践证明,传统分布式架构系统具有易拓展、高可靠、高效率、低沉本的显著优势,但也具有一定的局限性。
由于角色模块纷繁复杂的特性,传统分布式架构系统在配置管理、服务资源管理、部署环境等工作中难以通过人工快速地完成。例如:针对每个业务模块的不同版本,上线前都需要开发者一一做配置修改;当需要修改具体功能时,必然牵涉很多模块,为开发者产生大量重复的工单。
那么,怎样才能解决这些问题,创建出理想的线上环境和良好的可视化管理系统?这时,我们想到了容器化。
容器化的机遇与挑战
容器化能够有效地解决传统分布式架构系统的一系列问题。其中Docker和Kubernetes是最常用的开源容器引擎和编排工具。
Docker
Docker无疑是目前最受欢迎的开源容器引擎。Docker的原理,是将多个应用以及运行所需要的一切环境,都通过集装箱也就是容器包装起来,这样放置就可以避免很多因不规整而带来的隐患。例如:Docker可以有效避免Java环境版本差异、不同应用相互影响、使用资源相互竞争等问题。
个推在使用Docker时,沿用了Docker镜像的分层策略。首先,个推的各个产品线模块,使用的是各自的基础镜像。其次,个推各产品线的服务程序,打在了各自的基础镜像层之上,这样操作能确保各个容器的运行环境互不冲突。
Kubernetes
Kubernetes是一个用于容器集群的自动化部署、扩容以及运维的开源平台。Kubernetes的理念在于指点每个集装箱的摆放,降低服务器资源难度,让运维管理变得更加简便。
个推选择Kubernetes作为Docker容器编排的工具,主要有两方面的考量。
一、个推遇到的问题:
版本更新迭代快
应用进程多,服务器资源消耗大
服务器环境不统一
需要推进DevOps
二、Kubernetes的优势:
运维自动化
应用容器一次性构建
计算机硬件资源能够充分利用
编排管理具有突出优势
在应用Docker和Kubernetes的过程中,个推受益良多,同时也为个推原有的分布式系统结构带来一些压力。例如:个推系统的原有框架及模块都需要改动适配;原有系统非常庞大,需要逐步进行迁移;对原有的生态服务必须有所取舍。因此,我们通过一次落地的容器化实践来探索这个领域。
个推容器化实践
在个推的某项目中,我们进行了一次全程的容器化实践。
在具体实施前,我们先确定整体的架构图,架构图包含Kubernetes基本的一些结构。例如:在Master节点部署上,APIserver是整个系统的控制入口,Scheduler负责任务调度、命令下发,Controller Manager则作为集群内部的管理控制中心;在Node节点部署上,Kubelet作为Agent监听执行该节点的任务,汇报该节点的状态,而Proxy则负责整个网络规则的连接与转发。
当具体实践时,有状态组件怎样才能成功部署,内外网如何实现互通,需要怎样的配置中心,监控怎么做,都是开发者容易遇到的问题。
有状态组件的部署
在Kubernetes中,存在很多无状态组件,它们对于Pod的管理都是基于无状态、一次性的理念。如Replication Controller,它只是简单地保证可提供服务的Pod数量。如果一个Pod被认定为非健康 的状态,那么Kubernetes就会以非常简单粗暴的态度对待这个Pod:删掉、重建、自动扩缩容。这种处理方式通常适用于业务逻辑处理和内存计算型程序。
但是, Kubernetes可以通过StatefulSet的方式,给Pod提供唯一的标志,从而保证ZooKeeper、MySQL、Redis等有状态组件的成功部署和有序扩展。
但在系统中,如果要满足服务的Pod无论被置于何处,数据都要落地到同一目录的要求,当有状态组件被放置到容器中时,挂载就肯定需要经过网络。然而,使用网络卷进行挂载没有本地挂载可靠,网络的性能损耗也是高于本地的几十倍上百倍。同时,这种组件的维护操作并不频繁,没有为运维带来太多便利。因此,经过综合考虑,个推没有将这类有状态组件放到容器中。
内外网络的互通
内外网络的互通是容器化过程中容易遇到的典型问题。个推使用calico进行虚拟地址的分配,所以同个集群内的网络可以实现互通。集群内的服务访问外部的时候,可以直接使用真实的物理地址。集群外的服务访问内部的时候,需要通过iproute的方式,将虚拟ip映射到真实ip,才能实现内部服务的访问。
配置中心
关于配置中心,可以先整理罗列一些需求点,标出重点后逐个去解决。个推此次容器化实践过程中重点关注的需求点包括配置中心集群化,提供WEB界面化管理和权限管理,支持多种环境配置,开发集成简单,本地有备份等。
在对一系列开源配置中心进行调研后,通过对比QConf、diamond、Xdiamond、disconf、Apollo、mconf以及xxl-conf的各项功能,个推选择了功能更加齐全的Apollo。
(注释:调研具有时效性,图中某些配置中心的最新版本,现在可能已经支持当时还未支持的功能)监控采集
运行在Kubernetes里的应用程序,容易产生如网络同外部隔离、生存周期受集群管理、运行节点不固定等问题。我们通过对自有的监控系统进行一些调整,比如将主服务部署在Kubernetes集群外部,在集群每个Pod里面部署Agent,从而实现数据的采集监控并汇报主服务。
容器化的后续展望
最后,个推希望在吸取本次经验的同时,对未来的容器化实践有所规划与展望。例如,我们可以考虑从业务监控和扩缩容结合、自动化测试、Stateful服务等方面继续深入探索。
业务监控和扩缩容结合,能识别出假死,判断出业务压力。自动化测试,通过补充各个业务和模块的自动化测例,便能在很大程度上节省回归测试的成本,更好地实现快速迭代持续交付的目标,是DevOps进程中非常重要的一步。Stateful服务,后续随着Kubernetes相关技术的发展,能够帮助我们找到更多合适的容器化方式,从而做到完整的容器化,甚至是云服务化。
结语:
现阶段容器化大行其道,容器化在控制成本、保障服务稳定性、提高工作效率上都有极大的优势,然而传统分布式架构却往往因其基础组件和架构的定型,增加了容器化转型的难度,导致船大难掉头。本文希望通过作者的分享,能够帮助开发者在容器化过程中更好地理清自己的思路。
需要注意的是,容器化实践并不是为容器化而容器化,而是在充分理解现有业务需求和解决方案的基础上,通过容器化提供更高效、更稳定的系统服务,这才是容器化真正的价值所在。
网友评论