其他分享
首页 > 其他分享> > Kubernetes在喜马拉雅的实践:测试环境稳定性

Kubernetes在喜马拉雅的实践:测试环境稳定性

作者:互联网

 宋银涛 分布式实验室 

图片



喜马拉雅是专业的音频分享平台,汇聚了有声小说、有声读物、相声小品等数亿条音频。目前平台激活用户超6亿,主播用户超过1000万,大V用户超过100万,活跃用户日均收听时常170分钟,5年时间估值增长1000倍。作为一个产品驱动的互联网公司,公司的业务线扩展迅猛,需求的迭代十分迅速。前期开发在测试环境的发布也相当的频繁,那么所带来的稳定性问题十分突出。因此,我们在2016年底启动了容器化项目,将公司的应用进行容器化改造。在容器化背景之下,如何保证测试环境开发效率的同时兼顾环境的稳定性。
容器化的价值:资源+效率==>效果
即使用更少的资源+更高的开发效率,产生更好的效果。在测试环境当中,更高的开发效率显得更加重要。




容器化的实践

图片


这里我们先来简单介绍一下容器化在喜马拉雅的实践。
给喜马拉雅带来的好处
容器化之前
在进行容器化之前,开发在测试环境会碰到这些问题:
1、新项目创建
开发在接到新的需求之后,创建的新项目,本地开发完成之后,需要部署到测试环境。他们将不得不面对这些问题:


这一套流程下来,至少半个工作日过去了。时间都耗费在这些没有意义的事情上,开发效率相当低下。
2、物理机冲突
由于历史原因,作为一个创业公司,业务发展迅速,开发团队人员极速上升。运维团队相对精简,没有足够的精力运维管理测试环境。导致测试环境的管理相当混乱,主要问题如下:


由于大家共享物理机SSH账号,权限管理混乱。大家都可以随意的配置自己的服务,为了确保自己的服务正常上线,随意占用别人服务的端口,kill掉被人的服务。
这也是导致测试环境不稳定的一个重要因素。
3、断电重启
由于历史原因,老园区每1~2个月都会进行停电检修。机房服务器断电,导致整个测试环境不可用,电力恢复之后,需要开发手动拉起自己负责的业务。整个流程下来,半个工作日就过去了。
当然,现在公司有钱了,有了自己的办公大楼,新建了UPS机房,保证24小时不断电,这些问题是不存在的。
4、小结
针对这些问题,容器化的进程势在必行。因此,2016年底我们引入了容器技术进行容器化改造,来解决这些问题。
容器化之后
对测试环境进行容器化之后,我们取得了以下收益:


容器化现状
整体架构
在架构层面,CMDB-DOCKER(容器化管理平台)如何能与上层业务和底层Kubernetes平台更好地分层和解耦,是我们在设计之初就优先考虑的问题。
我们期望它既要能对业务使用友好,又能最大限度地发挥Kubernetes的调度能力,使得业务层和使用方毋需关注资源关系细节,所求即所得。
同时使发布、配置、负载等逻辑层与底层的Kubernetes平台解耦分层,并保持兼容原生Kubernetes API来访问Kubernetes集群。
从而可以借助于统一的、主流的、符合业界规范的标准,来解决基础架构面临的复杂、多样、不统一的管理需求。

图片


自上而下来看,集群管理与调度平台面向全公司服务,有各个主要业务线、统一的OPS平台,CMDB-DOCKER不可能针对每个平台定制化接口和解决方案,所以需要将多样的业务和需求抽象收敛,最终统一通过CMDB-DOCKER API来屏蔽CMDB-DOCKER系统的细节,做到CMDB-DOCKER与上层业务方的解耦。「CMDB-DOCKER」 API是对业务层和资源需求的抽象,是外界访问「CMDB-DOCKER」的唯一途径。
解决了上层的问题后,我们再来看与下层Kubernetes平台的解耦。
CMDB-DOCKER接到上层资源请求后,首先要进行一系列的初始化工作,包括参数校验、资源余量、IP和Hostname的分配等等,之后向Kubernetes平台实际申请分配机器资源,最终将资源交付给用户,Kubernetes API进一步将资源需求收敛和转换,让我们可以借助于Kubernetes的资源管理优势。此外,因为完全兼容Kubernetes API,可以让我们借助社区和生态的力量,共同建设和探索。
可以看到,CMDB-DOCKER API和Kubernetes API将我们整个系统分为三层,这样可以让每一层都专注于各自的模块。
支持的功能
喜马拉雅在容器化工作上主要支持了以下功能:
1、多语言支持。
目前支持Java、Python、Nodejs、PHP。
2、现有技术栈兼容。
为了无缝迁移传统服务,我们需要做一些兼容性的工作,整合现有的技术栈。
下面对喜马拉雅主要的中间件做一些简单的介绍:


主要解决的问题:
由于容器化以后,实例在重调度、扩缩容、重发布之后,IP是不断变化的,这些中间件要动态的感知到这些事件,对这些实例进行一些实例销毁、新增,服务上下线的操作。
为此,我们开发了Nile Agent组件用于同步这些信息。

图片


主要流程如下:


3、无损发布。
无损发布主要解决的就是应用重新发布时,保证旧实例在新发布的实例就绪时再销毁。在销毁的过程中,需要先进行服务的下线操作,再进行零流量检测,最终销毁容器。

图片


这里主要是用了Kubernetes提供的Liveness、Readiness探针功能,在新的发布ready之后,在进行旧实例的销毁。同时,还使用了容器生命周期管理的Hook preStop功能,在容器销毁之前,下线服务进行零流量检测,没有流量之后销毁旧的实例。
4、静态IP支持。
由于RPC微服务框架只提供了Java版本的SDK,C/C++应用通过IP直连的方式访问服务,因此需要提供固定IP的功能。
5、隔离组支持。
测试环境频繁的发布、发布代码存在bug,经常导致测试环境不稳定,开发效率受到严重的影响。因此,我们提供了隔离组的功能,用来确保测试环境的稳定性。这部分具体内容在下面将会详细说明。
6、监控、告警。
我们提供了应用实例的健康监测功能,在服务不可用时将会发送钉钉消息给相关负责人。




测试环境稳定性解决方案

图片


存在的问题
导致测试环境不稳定的原因主要有以下几个方面:


导致服务不可用。间接导致开发人员在定位问题时浪费较长。
具体场景如下:
测试人员发现某个服务接口返回500,其调用链路为A->B->C->D。如下图所示:

图片


沟通+排查问题时间太长。比如,测试发现A服务提供的接口有问题,找A,A花了五分钟发现是B返回的结果存在问题,B又花了5min,以此类推,最终发现是D的问题。这样花费了这么多的5min,开发效率可想而知。
经常会出现开发5分钟,联调两小时的状况。
隔离组
概念
我们在了解隔离组的概念之前,先回顾一下Git的功能分支模型。
Git功能分支模型:


图片


在开发测试的过程中,可能会存在的问题:
多个feature分支测试代码发布到测试环境麻烦,开发之间会存在冲突。比如,A在测试feature1的功能时,B发布了他的最新代码feature2。两者之间,如果没有有效的沟通或者约定,频繁发布会导致互相影响、降低开发效率。
那么,测试环境急需对这些分支的部署进行隔离,确保多人协作开发的效率,各自在开发、测试的时候不会互相影响。为此,我们提出了隔离组的概念,实现了测试环境的逻辑上的"软隔离"。
隔离组的定义与划分:
隔离组:逻辑上的一组服务实例的集合,由中间件的路由策略来保证它的隔离性。
关于隔离组的划分如下:


stable隔离组的特点:


feature隔离组的特点:


隔离组与Git功能分支模式的关系:

图片


示例:

图片


如上图,正常请求的调用链路如下:
AppClient—>southgate(API Gateway)—>A1—>B1—>C1。
在新的迭代周期,产品提出了两个需求,开发分别在feature1、feature2进行开发。同时,在发布实例时指定不同的隔离组信息。确保三个隔离组的实例同时存在(该特点直接采用Kubernetes中的service可以多版本发布deployment的特点)。
主要的路由规则如下:


从上面可以看出,隔离组的实现主要依赖流量的路由功能,具体的实现方案如下。
实现方案
隔离组,即多版本实例的发布主要依赖Kubernetes多版本发布功能,这里不再赘述。
路由转发实现软隔离,主要是对我们公司中间件的改造,支持根据隔离组标签的路由。
具体的实现如下:


优化
为了提升开发效率,迅速定位调用链的问题服务,解决调用链路黑盒问题。我们做了以下优化:


依赖拓扑查询:

图片


隔离组可视化:

图片


鼠标悬浮到实例上,可获取实例详细信息(IP、端口、健康状态、负责人等)。




测试环境开发效率提升

图片


测试环境除了稳定性之外,还需要注重开发效率。为此,我们开发了一款测试环境的发布工具,用于本地代码的编译、镜像构建、服务发布。借鉴了Kubernetes的配置即发布的思想,可以让开发迅速将自己的服务根据自己的配置文件,发布到容器环境(非stable隔离组),大大提升开发效率。
该工具提供了以下功能:


工具相关命令详情:

image.png

发布配置文件(以Spring Maven项目为例):


apiVersion: 0.0.1apps:- appName: demo-web  alias: web  build:    language: java    maven:      prepareCommand: mvn clean install -am -Dmaven.test.skip=true -Ptest-out      pom:demo-web/pom.xml      war: demo-web/target/demo-web.war  deploy:    isolation: feature1    expire: 1h    instances: 2



该配置文件指定了项目的构建、隔离组、实例数等信息,在项目的根目录下执行:


barge deploy -m demo-web



该项目的代码将会在本地进行编译、构建、镜像打包、push到镜像仓库、部署到测试环境的Kubernetes集群中。成功部署之后,将会给用户发布信息。
执行barge info -m demo-web命令将会显示项目的实例信息,及其健康状态。barge exec -m demo-web 命令将远程登录到容器里面。该工具简化了测试环境的发布流程,实例状态的查看。以类似于mvn命令的方式,进行测试环境服务的发布、管理,避免浏览器的频繁切换。(当然,线上环境并不支持该操作)




总结

图片


今天主要和大家分享了喜马拉雅在容器化方面进行的一些工作。介绍了容器化给我们带来的收益:减少维护成本、提升开发效率。其次,列举了导致我们测试环境不稳定的一些因素:1. 多分支并行开发的频繁发布;2. 开发远程debug,服务短暂不可用;3. 开发发布问题代码导致服务不可用。为此,我们提出了隔离组的概念,实现测试环境的"软隔离"。在隔离组中:首先,我们保证一整套和线上发布一致的stable隔离组,该隔离组保证测试环境稳定。当需要,开发新的分支代码时,创建新的隔离组,保证stable隔离组的实例不受影响,确保了环境的稳定性。其实现原理比较简单,主要是打通了中间件之间的流量管理,通过隔离组信息来进行请求路由。最后,介绍了我们在测试环境使用的小工具,通过简单的命令行方式进行服务的快速发布、日志查看,提升开发效率。



标签:容器,喜马拉雅,服务,隔离,Kubernetes,实例,开发,测试环境
来源: https://blog.51cto.com/u_15127630/2766421