Springcloud基于K8S滚动更新方案设计与原理

前言

由于近期使用k8s进行发布发现后端微服务流量有损失:

  • 发布过程中接口偶尔返回500状态
  • 微服务间接口调用返回500

本文分析产生原因,k8s组件工作原理及pod生命周期,最终解决方案。

K8S滚动更新介绍

K8S 滚动更新是Deployment默认更新策略,其本质是启动一个新pod然后在停止一个旧pod直到所有pod更新完成。滚动更新发布速率可以通过如下参数进行控制

maxSurge

maxUnavailable

  1.  表示当前deployment运行2个pod
  2. 更新deployment(应用发布)
  3. 创建新的pod(蓝色pod)新pod启动成功k8s检测到readniess状态ready后停止老pod(红色)
  4. 老pod停止后(红色pod)继续创建新pod
  5. 新pod状态为ready 停止老pod(红色)
  6. 发布完成,所有pod都为新pod,老pod全部停止删除老版本replicateset

K8S服务发现介绍

在pod创建好以后k8s会为pod分配ip但次ip只能在k8s内部访问,随着pod的频繁创建删除ip也会随时改变,因此k8s提供service关联一组pod并对外进行服务发现,当service设置lable后k8s会自动创建endpoint并维护一个ip列表代表当前service下有那些pod与之关联。

下图表示删除pod与新增pod对应service的endpoint的IP列表变化

  1. 代表正在运行的service维护的pod列表
  2. 新增pod当pod的状态变为ready后,endpoint 监听到有新pod自动将新pod ip 加入到自己的列表,次列表存储在etcd中
  3. 当pod收到 terminal信号后,endpoint watch到该信号后将次pod ip 从ip列表中删除

K8S pod生命周期

 pod是Kubernetes 中创建和管理的、最小的可部署的计算单元。pod的生命周期中对位提供不同的调用方式方便做一些回调处理。

  • initContainer是pod中运行的init容器可以对pod进行初始化例如设置文件路径,设置环境变量等,initContainer可以存在多个,在pod启动中顺寻执行
  • poststart是一个回调接口在maincontainer启动时进行回调,但此接口为异步接口
  • maincontainer 为主容器,微服务主要运行在此容器中
  • readniess 为回调接口,表示主容器中的应用是否启动完成并可以对外部提供服务,如果readniss返回成功,pod的状态才会变为ready,否在会不停尝试重启pod
  • healthness为pod运行时k8s检测内部应用是否运行的回调接口,如果检测接口返回失败则重新创建pod
  • prestop 为pod停止时前置执行回调接口,此接口运行逻辑运行完才会停止主容器,此接口为同步接口

在了解了以上内容的工作逻辑后,下面重点分析为什么在k8s中发布微服务会产生流量损失,本文微服务的注册中心采用nacos且独立部。

K8S 启停微服务产生流量损失的原因

下图为k8s发布某个微服务时各个组件的状态以及其他的微服务注册信息变更逻辑

  1. 发布新的deployment根据滚动更新策略创建新pod,pod状态编程ready后endpoint更新新pod ip到etcd表中,然后向nacos注册自己(绿色线部分)
  2. 停止老pod,endpoint删除etcd中老pod ip,但此时老pod ip 并未从nacos中删除,因为nacos与服务提供者通过心跳方式维护服务提供者状态,当服务提供者15内没有发动心跳nacos标记服务提供者为不健康状态,超过30才会将ip从nacos中删除
  3. 其他微服务获取nacos中的服务列表通过拉去的方式进行,每次拉去最新的列表时间间隔为30秒,30秒内会将服务列表缓存在本地机器。

因此在某个服务发布的过程中其他微服务还是会持有下线服务机器ip 大概30秒左右的时间,在此期间调用就会出现流量损失,因为老服务ip对应的pod已经停止无法相应请求了。

在分析完产生原因后提出如下改造方案。

K8S 发布微服务实现方案

在pod创建过程中因为新pod的状态是在ready后才被k8s服务发现因此部存在流量损失问题,产生生问题在pod停止时发生因此在pod停止时做如下处理:

  1. pod停止后调用prestop先将自身ip从nacos摘掉不对外提供服务
  2. 由于微服务每隔30s从nacos同步服务列表,因此在摘到nacos中ip后接口prestop接口阻塞90s,90s包含nacos同步时间间隔以及老的相应完处理的时间
  3. 90s过后在停止pod中的应用

因此在代码中增加nacos取消注册的接口如下所示

 在deployment中增加prestop回调函数

通过以上改造完美解决了流量损失问题。

springcloud服务注册流程

springcloud启动时合适向nacos中注册服务ip?

带着这个问题我们看下nacos注册的源代码,其本质就是在服务注册时会监听当前应用启动状态是否为完成状态,由于微服务都是web应用因此在web启动完成后springcloud会发布一个web初始化完成的事件。监听到此事件后向nacos中注册服务

 

总结

以上也是在网上使用的比较多的方案,本文进行简单总结分析,欢迎大家交流

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值