kubernetes系列之七:一些将legacy应用迁移到kubernetes的经验

25 篇文章 0 订阅
20 篇文章 2 订阅

一、前言

基于kubernetes的应用实际上是微服务在container方向的实例,所以很多微服务的设计原则在kubernetes框架内依然具有参考价值,比如The Twelve Factors

在legacy应用从基于VM的部署向基于kubernetes部署的迁移过程中,需要根据container和微服务的特点,对legacy系统的诸多方面进行调整,满足kubernetes平台微服务的一些基本要求和模式:

  • 功能实现
  • 服务分割
  • 配置管理
  • 集群状态管理
  • 日志监控报警
  • 负载均衡和数据流
  • 集成发布
  • 服务资源配置
  • 规模部署和管理

转载自https://blog.csdn.net/cloudvtech

二、legacy系统

原有的系统状态:
  • 具有一个专有的平台进行计算网络资源管理和应用配置的管理,资源管理是基于VMWare的vSphere而应用配置管理子系统使用脚本语言编写
  • 集群的通信和状态管理使用zookeeper和API
  • 使用发布的ova进行软件安装和配置之后,生成不同功能的虚拟机节点
  • 日志经本地收集之后转发到ELK
  • 使用IPVS进行请求接入负载均衡
  • 该系统具有动态组合的配置信息,但是没有持久化的需求


转载自https://blog.csdn.net/cloudvtech


三、向kubernetes迁移:容器化

1.系统拆分:将松耦合的子系统拆分成独立的服务,不同的服务由一系列的容器组合而成,这样便于和后面kubernetes的service和POD的概念进行对应。

2.容器镜像:选择合适的based镜像,对现有系统的RPM依赖进行分析,去掉不必要的模块,以减少构建出来的应用镜像的大小,中间经过优化,从2.5GB减少到700MB。

3.进程管理:在VM里面,应用程序进程的状态由supervisord进行维护;但是在容器中,kubernetes管理框架需要直接感知容器里面进程的状态,所以需要直接让应用程序作为容器里面的一号进程,使得容器的状态和应用程序的状态保持一致。这里其实也有另外一个选择,就是使用一个脚本管理应用程序进程的生命周期并通过检测程序状态并向外暴露来代理程序的运行状态向容器外部暴露;如果应用程序本身是面向微服务架构设计的,则应用程序可以作为主程序直接对外暴露,对于一些legacy的系统,可能需要这样一个代理机制以能够更好的对外反馈容器内服务的状态。

4.CICD:建立独立的pipeline对镜像进行自动建构和sanity测试。

5.镜像安全性:对于使用的基础镜像,需要遵循内部安全性测试的流程,或者使用公司基础设施部门发布的可信基础镜像。

转载自https://blog.csdn.net/cloudvtech

四、向kubernetes迁移:定义kubernetes服务

在容器化的过程中,已经将系统进行根据松耦合进行拆分,然后对于拆分之后的子系统服务,需要按照kubernetes的原则封装成POD并且通过定义kubernetes的service进行暴露。这里需要说明的是在容器化的过程中,我们只是将应用程序对应的业务服务模块进行容器化,而对于原有系统中计算网络资源管理和应用配置的管理的功能,并没有迁移过来;计算网络资源管理将代理给kubernetes,而应用配置的管理的功能就需要定义和开发新的kubernetes服务了。

所以在系统迁移到kubernetes之后,核心的应用程序被拆分成了三个服务,其中两个应用程序业务逻辑服务只是将原有程序容器化,而应用程序配置管理程序需要开发新的基于kubernetes的服务。

而对于日志监控,将使用运维kubernetes平台的部门提供的基础设施服务。

另外,对于应用程序在容器化之后额外需要的一些服务比如redis或者etcd,可以根据数据存储和访问的需求自行部署或者使用平台提供的服务。这里需要说明的是使用平台服务和使用自定义的服务,在部署、维护、管理和使用各方面各有利弊,需要进行权衡。

转载自https://blog.csdn.net/cloudvtech

五、向kubernetes迁移:应用程序配置管理

原有平台的应用程序配置管理服务是基于虚拟机和多应用进行混合部署的,所以配置管理是在主机和应用,是较粗级别的管理,使用的是zookeeper进行配置和状态的交互。我们并没有将这套和基于VMWare虚拟化平台和基于主机应用程序架构的配置方案迁移到kubernetes,而是重新开发了一套可以使用kubernetes和容器化配置管理功能的新的配置管理系统。

对于基于容器的应用程序配置管理,如果是基于微服务的概念进行开发的,比较好的策略是使用immutable模式,所有的配置在kubernetes的deployment部署和容器启动的时候加载,任何配置的更新其实都是deployment版本的更新,deployment对应的POD都会删除旧的容器并启动带有新的配置的容器。但是在lagecy的系统中,对配置可能具有动态组合、动态增减等复杂需求,需要对应服务的后端POD根据新的配置在不重启的情况下调整配置。

对于配置的管理,这边需要考虑的是配置如何从kubernetes外部传输给容器内部的应用程序。一种方案是使用kubernetes自带的ConfigMap服务,将配置数据作为文件直接mount到容器内部,由应用程序或者配置agent感知并加载,这种方案实现简单,并借助kubernetes存储配置,缺点在于ConfigMap的数据传输存在时延不可控和扩展性的问题。另一种方案是使用etcd等具有事件通知功能的中间件作为消息存储和通知的媒介,由API接受外部的配置、存储到etcd并触动容器内部的监听模块进行配置更新;这个方案具有时效性强、扩展性好等特点,缺点在于实现比较复杂,需要前端API和etcd模块、容器内要有agent跟踪etcd节点状态。


在实际应用场景中,不同规模和部署方式的客户,可能需要不同的配置方式,所以我们在实现过程中对两种方式都进行了支持。

转载自https://blog.csdn.net/cloudvtech

六、向kubernetes迁移:负载均衡和数据流

在kubernetes service里面,提供了基于iptabels的针对service后端POD的简单负载均衡方案,见文章《Kubernetes如何利用iptables对外暴露service》。这个负载均衡的方案仅仅是保证将数据和请求能在不同节点上的POD中间通信,并没有考虑精细控制和性能效率的问题。

对于提供互联网服务的大规模分布式系统,上行流量一本都会远远小于下行流量,对于提供视频流服务的系统而言,这个规律会更加明显(可能在100K:10MB这个级别)。所以在这样的系统中,负载均衡需要考虑更多的是使用三角模式的负载均衡(IPVS的DR模式是一个很好的例子,请求、转发和返回三个路径连接client、IPVS director和后端real server组成一个三角形)来控制数据流。我们的应用系统恰恰是这样一个小请求返回比的系统,所以基于七层的kubernetes Ingress代理方案和默认的基于iptables的kube-porxy负载均衡方案(这个方案存在cross node traffic,对于小请求返回比的系统几乎是灾难)都不能满足系统大流量和线性扩展的需求:


基于kubernetes Ingress的七层负载均衡


基于kubernetes service的四层负载均衡

所以在我们的系统向kubernetes迁移的过程中,基于kubernetes的基础能力和IPVS开发了这样一套负载均衡系统:

  • 作为kubernetes的service进行部署
  • 动态感知kubernetes service后端的能力变化而调整负载均衡权重
  • 没有cross node traffic
  • 跟随node增减能达到流量支持的线性扩展

在这个的解决方案中,数据流从IPVS服务进入,然后根据负载均衡路由方案进入特定的kubernetes节点和节点上的POD进行请求响应,之后直接返回客户,是典型的三角数据传输模型,具有很强的接入能力和扩展能力。

转载自https://blog.csdn.net/cloudvtech

七、向kubernetes迁移:日志监控报警

1.日志

使用由于lagecy系统依赖于td-agent进行log的格式转换,所以加入了一个log处理的side car进行日志的各式处理和向Fluentd导出并转发至ELK,至于新开发的配置管理服务,则直接使用Fluentd对于POD的STD输出向ELK导出日志。

2.监控

对于不同的POD,有不同的metrics exporter翻译并导出,虽然这些exporter都有开源的实现,但是还是有必要根据应用和业务的特点定制一些导出数据。我们使用promethes汇聚数据并根据监控需求对这些数据进行关联计算,prometheus可以通过API向exporter pull数据或者由exporter向prometheus push数据。最后,使用grafana将监控数据在基于Web的GUI上进行展示,并且可以设立简单的告警。


3.报警

应用程序使用sensu client收集不同服务的POD的运行状态数据或者进程直接上报的告警信息,这些信息经由平台的RabbitMQ消息总线服务传送至sensu server,由uchiwa进行展示或者使用pageduty等将告警信息导出至外部通知系统。

转载自https://blog.csdn.net/cloudvtech

八、向kubernetes迁移:集群状态管理

在kubernetes迁移之后,我们的应用程序服务被分割成了几个kubernetes的service,而service实际上是一个虚拟的概念,实际支撑service的是一系列后端POD,这些POD根据service的定义被选为某个service的后端。同时,service会根据POD的状态来决定是否将POD加入到服务可达的列表里面。所以我们需要定义好POD里面每个container的liveness和rediness检测接口,如果rediness通过了,POD便会被加入service的服务列表,如果liveness失败了,POD就会被kubernetes删掉重新启动。

所以先抓整个集群的服务状态和进程状态本质上都是由kubernetes进行管理,我们唯一需要关注的是一些检测接口的实现,以保证liveness和rediness检测接口能准确反应单个服务进程的状态。同时,service后端是由一系列POD replica组成,这个replica数目代表了service的服务能力,如果某个节点或者一些POD出现问题,kubernetes会在其它节点启动新的POD replica来保证需求的服务能力。


转载自https://blog.csdn.net/cloudvtech

九、向kubernetes迁移:服务资源配置

我们的服务本身需要同时处理很大的上行和下行流量,所以对于不同业务层面的需求,需要为POD里面的容器配置不同的处理器和内存资源。为了满足这个需求,我们基于不同的资源配置对POD的能力进行测试,比如一个物理机node配置不同数目不同资源需求的POD,来查看并发服务能力、吞吐率和时延,以此决定不同业务需求场景下推荐的POD配置。



转载自https://blog.csdn.net/cloudvtech

十、向kubernetes迁移:规模部署和管理

在规模部署的时候,需要定义kubernetes的ConfigMap、service和POD deployment配置文件,同时还要定义业务逻辑上的参数,全部加起来应该在一百个参数以上,这些参数多数需要根据特定业务特定部署来设定,所以需要由一个强大的辅助工具对参数进行组合、生成相应配置文件并进行部署。

在生产环境,我们使用ansible来编排这些配置并进行部署。我们编写了众多的ansible role来编排不同的服务,从系统集成、配置转换到服务启动,都有对应的ansible role,这样的话,整个编排部署流程尽量解藕,降低了维护的复杂度。但是由于我们lagecy系统的复杂性,所以导致我们的配置最后集成了普通text、xml、json、yaml和j2 template,而这些不同格式的文件具有不同的文法需求,所以也带来了很多兼容性问题,因此在有条件的情况下,尽量使用一致的配置格式。

同时,在规模部署的时候,经过仔细测试,我们发现kubernetes在一个node上启动一系列POD的时候,是一个近乎线性的过程,并且由于大量读取容器镜像文件,所以存在巨大的disk负载。因此,我们也对于同时部署和扩展给出了一些指导,保证不会由于大量并发对系统服务造成影响。

转载自https://blog.csdn.net/cloudvtech

总的来说,应用向kubernetes迁移的过程中,有很多不适应容器云服务的技术点,需要一一梳理使用创造性的方案进行兼容和解决;但是只要有机会和条件,应该毫不犹豫的向容器云切换,因为现在很多客户都会有内部容器云平台,并且更倾向于统一的平台解决方案,所以应用应该及时拥抱这个趋势。

转载自https://blog.csdn.net/cloudvtech

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值