云原生场景下,容器化和微服务还有必要组“CP”吗?
背景
注册中心式CP,东西向流量; 云原生网关式CP,南北向流量; ServiceMesh式CP,东西向、南北向流量; CMDB式CP,运维、架构依赖式流量;
这种方式是如何微服务的访问呢?
网关+CMDB完成应用访问路由和应用系统的关联; 微服务+CMDB完成应用系统和服务器资源的关联;
福兮祸所依
overlay网络,那东西向流量就必须使用注册中心或ServiceMesh解决方案,与CMDB再集成意义不大;
underlay网络,那容器IP可以直接关联业务网段,通过CMDB按业务、应用系统与容器IP进行关联;
当然,天无绝人之路!
祸兮福所伏
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 检测通过就上报会产生部分垃圾数据;
上报后容器信息并不保证可正常使用,因为需要经过 Readiness、Liveness 等检测;
如果容器启动不成功,通过 PreStop 钩子可将容器信息从 CMDB 反注册;
此种方案的优点是方案可行,但是在实际联调过程中有以下几个关键点:
使用 Init 注册要优于 PostStart,因为为保证注册信息上报的准确性,PostStart 的等待时间一定要比 Readiness 时间长,否则未等到 Readiness 检测通过就上报会产生部分垃圾数据; 无论是PostStart、PreStop只支持简单的命令行,还需要由默认的分隔符“,”限制,这意味着太过复杂的参数如json格式就会被意味隔断,从而导致请求错误;
总结,受限于PostStart、PreStop的特性及便捷性,他们在给你带来可能性的同时也可能会束缚你前进的脚步!
K8S事件监控+MQ
Event 是集群中某个事件的报告,它一般表示系统的某些状态变化。Event 的保留时间有限,触发器和消息可能会随着时间的推移而演变。
事件监听服务,每隔一定频率从 kube-apiserver 同步事件,并且K8S提供了类库专门来监听集群内的事件变化,然后再触发自己写的业务逻辑;
事件监听服务需要对事件相关服务进行健康检查,只有正常启动的服务才会将消息发送至mq,因此这需要微服务要有一定的接入标准及规范; 事件监听服务作为 MQ 生产者,根据集群事件可根据ns、IP、port等所需内容进行定制化收集,并将这些内容发送至mq上指定的topic; 至于消费方案可以有多种,一种方案是可以订制单独的消费者服务,消费mq上topic 信息与下游的 CMDB 及其他组件进行注册/反注册;另一种方案是CMDB及其他组件直接消费 topic 上的信息,完成注册/反注册;
这种方案的优势在于灵活可控,但集成难度也相应增加:
有一定的开发成本,例如事件监控服务(go开发)、单独的消费者服务(python、go、java均可)、CMDB及其他组件(根据其开发语言所定); 随着中间组件的引入,不稳定性增加,例如网络抖动、单点mq或mq高可用切换可能会导致生产/消费有问题,如果这期间恰好发生容器事件,可能会导致生产事故;
消息幂等性,为了保证事件消息不遗漏,事件监控服务多副本情况下会发送重复消息,因此会导致重复消费,因此我们需要在下游考虑消息的幂等性;