spring cloud kubernetes项目负载均衡pod模式下,如何实现平滑访问?

Posted 水中加点糖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring cloud kubernetes项目负载均衡pod模式下,如何实现平滑访问?相关的知识,希望对你有一定的参考价值。

如果再回到从前

所有一切重演

我是否会明白

生活重点


简介

如果spring cloud项目使用kubernetes作为服务的注册中心,最方便快捷的办法就是直接引入spring cloud kubernetes组件,具体的操作办法可以看下以前的文章:
spring cloud项目改造为spring-cloud-kubernetes项目

spring cloud kubernetes负载均衡方式

对说spring cloud kubernetes项目来说,它支持两种负载均衡模式,详情可看loadbalancer-for-kubernetes的官方说明。

根据官方文档我们可知它具体的两种负载均衡模式分别为:

  • pod
  • service

其配置方式通过修改配置:

spring.cloud.kubernetes.loadbalancer.mode

如想采用service的方式设spring boot项目的配置文件中添加如下配置即可:

spring.cloud.kubernetes.loadbalancer.mode=SERVICE

负载均衡方式中pod和service的区别

查看spring cloud kubernetes的源码可知,loadbalancer的默认mode为POD方式。

	/**
	 * {@link KubernetesLoadBalancerMode} setting load balancer server list with ip of pod
	 * or service name. default value is POD.
	 */
	private KubernetesLoadBalancerMode mode = KubernetesLoadBalancerMode.POD;

其中pod方式与service方式的主要区别是:

service方式的负载均衡请求服务时,是直接向kubernetes集群中对应的service(svc)发起请求的;

pod方式的负载均衡请求服务时,是先由服务调用者通过调用kubernetes的api先获取到对应的服务的pod列表,之后再保存到一个list中,再使用spring cloud项目所配置的loadbalancer负载均衡策略进行请求。

也就是说,当负载均衡方式mode为service时,spring cloud项目中所配置的关于loadbalance的配置是无效的,因为它将是通过k8s中的service进行访问的。 当负载均衡方式mode为pod时,可以利用spring cloud项目中的loadbance配置进行负载。

service方式(负载均衡时的压力在k8s端)

pod方式(负载均衡时的压力在spring cloud项目端)

至于具体选择哪个,需要根据项目的情况进行选择。

一般来说,如果k8s集群资源比较多为了方便省事,选service方式即可。
如果想要做到更加灵活,并减少一些k8s集群的压力,可以选择pod方式。

负载均衡pod和service方式式的平滑访问

servcie模式下服务平滑访问

如果spring cloud kubernetes项目配置的是service方式,想要做到服务的平滑访问,其主要配置pod的两个探针即可,它们分别是:

  • 就绪探针(readinessProbe)
  • 存活探针(livenessProbe)

具体可以看下spring boot官方的说明,其链接如下:

https://docs.spring.io/spring-boot/docs/2.5.3/reference/htmlsingle/#actuator.endpoints.kubernetes-probes

pod模式下服务平滑访问

如果选择的是pod模式的负载均衡配置,由于spring-cloud-loadbalancer组件为了提高性能,一般会对pod的列表进行缓存。

当然也可不开启缓存,如果k8s集群的配置不咋样,高并发时k8s的api-server则有很大的负载,一不小心k8s挂了都有可能

正如其官方文档中所介绍的那样(链接地址为:https://docs.spring.io/spring-cloud-commons/docs/3.0.3/reference/html/#default-loadbalancer-cache-implementation)

The default setup includes ttl set to 35 seconds and the default initialCapacity is 256.

默认为35秒的缓存。

意思也就是说默认情况下,拉取到k8s集群中最新的有效pod列表的时间延迟最长可能为35秒。

例如有这样两个sring cloud服务:gateway和user这两个服务,gateway调用user服务。

user在k8s中部署了10个节点(Replica Sets),现在对user服务进行升级,则在升级过程中就可能会出现user服务中的某些副本已经被销毁,其pod的ip也已访问不了,则可能会出现gateway服务中存在的关于user服务的ip仍然是以前user服务ip。

如果想进行测试,可能通过DiscoveryClient来进行观察。调用discoveryClient.getInstances方法即可获取k8s集群中有效果的某个服务的pod列表。

那么如何解决呢?

查看spring boot的官方说明文档,就能找到合适的答案:

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#deployment.cloud.kubernetes

在向k8s中部署微服务时,添加preStop的lifecycle配置,让其pod正式销毁前睡眠一段时间,以做完让所有的服务都已经拉取到了最新的pod信息。

spec:
  containers:
  - name: haiyang-example-container
    image: haiyang-example-image
    lifecycle:
      preStop:
        exec:
          command: ["sh", "-c", "sleep 36"]

其中具体睡眠多久,需要根据spring cloud loadbalancer缓存的时长来进行配置,大于缓存的ttl时长就行,比如缓存配置的是35秒,这里配置36秒就可以。

注意点:设置preStop时需要注意,preStop睡眠的时间不能小于terminationGracePeriodSeconds的时间(默认为30秒)

也就是k8s官方文档生命周期部分介绍的那样:

Note: If the preStop hook needs longer to complete than the default grace period allows, you must modify terminationGracePeriodSeconds to suit this.

之所以terminationGracePeriodSeconds的时间不能小于preStop睡眠的时间是因为:

If one of the Pod’s containers has defined a preStop hook, the kubelet runs that hook inside of the container. If the preStop hook is still running after the grace period expires, the kubelet requests a small, one-off grace period extension of 2 seconds.

When the grace period expires, the kubelet triggers forcible shutdown. The container runtime sends SIGKILL to any processes still running in any container in the Pod. The kubelet also cleans up a hidden pause container if that container runtime uses one.

整体就是说,如果超过了terminationGracePeriodSeconds的时间,kubelet会向pod发送一个强制关闭的命令.

至于在spring cloud kubernetes中为何配置preStop睡眠一段时间,就可以让服务平滑访问的原因在k8s的文档中也能找到答案:

At the same time as the kubelet is starting graceful shutdown, the control plane removes that shutting-down Pod from Endpoints (and, if enabled, EndpointSlice) objects where these represent a Service with a configured selector. ReplicaSets and other workload resources no longer treat the shutting-down Pod as a valid, in-service replica. Pods that shut down slowly cannot continue to serve traffic as load balancers (like the service proxy) remove the Pod from the list of endpoints as soon as the termination grace period begins.


不知道在那天边可会有尽头

只知道逝去光阴不会再回头

每一串泪水伴每一个梦想

不知不觉全溜走

以上是关于spring cloud kubernetes项目负载均衡pod模式下,如何实现平滑访问?的主要内容,如果未能解决你的问题,请参考以下文章

spring cloud kubernetes项目负载均衡pod模式下,如何实现平滑访问?

spring-cloud-kubernetes官方demo运行实战

在本地禁用 Spring Cloud Kubernetes

kubernetes部署spring cloud微服务项目

#yyds干货盘点#spring-cloud-kubernetes官方demo运行实战

想了解 spring-cloud-kubernetes,那就先来实战一把官方demo