云计算·大数据 频道

云原生场景下,容器化和微服务如何组CP?

  背景

  云原生1.0定义容器、微服务、不可变基础设施和声明式API,其中容器化虽然是微服务运行的载体,但是以何种方式组CP,这可能出乎我们的想想:

  注册中心式CP,东西向流量;

  云原生网关式CP,南北向流量;

  ServiceMesh式CP,东西向、南北向流量;

  CMDB式CP,运维、架构依赖式流量;

  以上几种方式其实在容器化建设场景中真实存在的,因为架构是随着技术的发展不断演进的。例如注册中心->云原生网关->ServiceMesh,容器因生命周期发生IP不断变化,可通过注册中心、Endpoint Controller 来检测并更新,但是众多架构中总会特殊的一种:既没有注册中心又没有支持云原生场景的网关或其他兼容性组件,但好在微服务+CMDB+网关可以实现服务的可触达。

  这种方式是如何微服务的访问呢?

  网关+CMDB完成应用访问路由和应用系统的关联;

  微服务+CMDB完成应用系统和服务器资源的关联;

  其中CMDB在整条访问链路中起着承上启下的作用,在传统架构中这是CMDB发挥重大作用的数据支撑场景之一,可谓是运维辛苦付出得到的福报之一啊!

  福兮祸所依

  正当我们欢天喜地送走传统微服务架构,锣鼓喧天鞭炮齐鸣的迎来云原生架构,以为终于可以享受容器编排带给我们的便利时,岂料曾使我们洋洋得意的CMDB成为了我们的心结,运维是否要亲手革了CMDB的命?

  为什么会出现这种情况呢?最大的问题就在于容器生命周期过程中的IP变化以及underlay/overlay网络选型:

  overlay网络,那东西向流量就必须使用注册中心或ServiceMesh解决方案,与CMDB再集成意义不大;

  underlay网络,那容器IP可以直接关联业务网段,通过CMDB按业务、应用系统与容器IP进行关联;

  诚然,我们在努力培养CMDB在云原生场景中生存的土壤,但是传统架构下依赖CMDB Agent的自动采集上报信息的能力将再一次被诟病,因为容器的生命周期变化如此之频繁,这让Agent的能力大打折扣!但在应用容器化过程中,我们不太可能一下子就推翻当前使用多年且非完全兼容云原生的架构,只能是循序渐进平稳过渡,因此我们需要更开放性及发展性的眼光来重新寻找一个可行性方案。

  当然,天无绝人之路!

  祸兮福所伏

  既然underly网络可以使用业务网段,因此我们的希望之火将被重新点燃。在经历一番探讨与交流后,关于容器化和CMDB的CP组合方案,我们有了新方案!

  Init容器+PostStart

  上图是容器生命周期的过程,其中有几个关键信息:

  Init容器, 在 Pod 内的应用容器启动之前运行, 它们总是运行到完成。如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。

  PostStart钩子,回调在容器被创建之后立即被执行。但是,不能保证回调会在容器入口点(ENTRYPOINT)之前执行。没有参数传递给处理程序。

  PreStop钩子,在容器因 API 请求或者管理事件(诸如存活态探针、启动探针失败、资源抢占、资源竞争等) 而被终止之前,此回调会被调用。

  那么K8S中的这几种原生特性,是如何让容器化和CMDB结合呢?

  与CMDB Agent采集主机数据上报不同的是,Pod在启动过程中:

  由于Init容器最先启动,此时可将容器字段,如IP、容器名等信息注册至CMDB;

  如果不使用init容器,也可以通过PostStart钩子将容器信息注册至CMDB;

  上报后容器信息并不保证可正常使用,因为需要经过Readiness、Liveness等检测;

  如果容器启动不成功,通过PreStop钩子可将容器信息从CMDB反注册;

  此种方案的优点是方案可行,但是在实际联调过程中有以下几个关键点:

  使用Init注册要优于PostStart,因为为保证注册信息上报的准确性,PostStart的等待时间一定要比Readiness时间长,否则未等到Readiness检测通过就上报会产生部分垃圾数据;

  无论是PostStart、PreStop只支持简单的命令行,还需要由默认的分隔符“,”限制,这意味着太过复杂的参数如json格式就会被意味隔断,从而导致请求错误;

  总结,受限于PostStart、PreStop的特性及便捷性,他们在给你带来可能性的同时也可能会束缚你前进的脚步!

  K8S事件监控+MQ

  image.png

  ❝

  Event 是集群中某个事件的报告,它一般表示系统的某些状态变化。Event 的保留时间有限,触发器和消息可能会随着时间的推移而演变。

  ❞

  K8S集群支持事件查看,因此这种方案的几个关键信息点为:

  事件监听服务,每隔一定频率从kube-apiserver同步事件,并且K8S提供了类库专门来监听集群内的事件变化, 然后再触发自己写的业务逻辑;

  事件监听服务需要对事件相关服务进行健康检查,只有正常启动的服务才会将消息发送至mq,因此这需要微服务要有一定的接入标准及规范;

  事件监听服务作为mq生产者,根据集群事件可根据ns、IP、port等所需内容进行定制化收集,并将这些内容发送至mq上指定的topic;

  至于消费方案可以有多种,一种方案是可以订制单独的消费者服务,消费mq上topic信息与下游的CMDB及其他组件进行注册/反注册;另一种方案是CMDB及其他组件直接消费topic上的信息,完成注册/反注册;

  这种方案的优势在于灵活可控,但集成难度也相应增加:

  有一定的开发成本,例如事件监控服务(go开发)、单独的消费者服务(python、go、java均可)、CMDB及其他组件(根据其开发语言所定);

  随着中间组件的引入,不稳定性增加,例如网络抖动、单点mq或mq高可用切换可能会导致生产/消费有问题,如果这期间恰好发生容器事件,可能会导致生产事故;

  消息幂等性,为了保证事件消息不遗漏,事件监控服务多副本情况下会发送重复消息,因此会导致重复消费,因此我们需要在下游考虑消息的幂等性;

  总结

  容器化进程中,CMDB式的CP可以在不改变当前架构的情况下兼容容器场景,这个错位CP虽然给我们的架构带来了时间和空间上的过渡,但是架构不易,要想改变现状还需要架构及解决方案等大佬们去统筹全局,而非一朝一夕能够完成!

0
相关文章