k8s+rancher配置滚动发布更新时服务不可用

问题

配置完了k8s优雅下线后,发现配置了滚动发布后,两个服务同时在running状态,其中旧服务开始下线会导致有三四秒的时间调用该服务的接口会负载均衡到该服务,接口调用就会报错服务异常。

经排查,具体原因是服务虽然会到终止状态,但是nacos上有缓存,导致会调用到旧服务。

滚动发布配置:

负载到已下线pod效果:

依赖

需要健康检查和prometheus的支持

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
            <scope>runtime</scope>
        </dependency>

bootstrap.yaml

加入 actuator 独立的端口配置,避免通过gateway能直接访问

yaml 复制代码
# 优雅下线配置
management:
  server:
    port: 9081
  endpoints:
    web:
      exposure:
        include: '*' #对外公开 health,info,shutdown 端点,默认只会公开前两个

bootstrap-xx.yaml

对应环境的配置文件也需要单独配置,全都配置到bootstrap会失效。暴露对应端点才能使后面k8s配置检查成功

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: 'refresh,info,health,logfile,loggers,heapdump,threaddump,metrics,prometheus,mappings,env' #暴露所有端点
      base-path: /actuator

对应服务需要添加下线端点 NacosDeRegistryEndpoint

优化是可以做到公司的common包里,就不必每个服务都重复引入一遍。

java 复制代码
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.registry.NacosRegistration;
import com.alibaba.cloud.nacos.registry.NacosServiceRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@Endpoint(id = "nacos-deregister")
public class NacosDeRegistryEndpoint {

    private final NacosRegistration nacosRegistration;
    private final NacosServiceRegistry nacosServiceRegistry;
    private final NacosDiscoveryProperties nacosDiscoveryProperties;

    public NacosDeRegistryEndpoint(NacosRegistration nacosRegistration, NacosServiceRegistry nacosServiceRegistry, NacosDiscoveryProperties nacosDiscoveryProperties) {
        this.nacosRegistration = nacosRegistration;
        this.nacosServiceRegistry = nacosServiceRegistry;
        this.nacosDiscoveryProperties = nacosDiscoveryProperties;
    }

    /**
     * 从 nacos 中主动下线,用于 k8s 滚动更新时,提前下线分流流量
     */
    @WriteOperation
    public String endpoint() {
        String serviceName = nacosDiscoveryProperties.getService();
        String groupName = nacosDiscoveryProperties.getGroup();
        String clusterName = nacosDiscoveryProperties.getClusterName();
        String ip = nacosDiscoveryProperties.getIp();
        int port = nacosDiscoveryProperties.getPort();

        log.info("deregister from nacos, serviceName:{}, groupName:{}, clusterName:{}, ip:{}, port:{}", serviceName, groupName, clusterName, ip, port);

        // 设置服务下线
        nacosServiceRegistry.setStatus(nacosRegistration, "DOWN");
        return "success";
    }
}

rancher修改服务配置

主要是设置一个停止服务前的钩子,钩子会执行设置好的命令。这条命令是用配置好的端口9081,以及添加的服务端点 nacos-deregister,做到调用nacos下线接口的操作,避免缓存问题能被负载到。

commonlisp 复制代码
/bin/sh -c 'curl -X POST 'http://127.0.0.1:9081/actuator/nacos-deregister' && sleep 40'

可视化改容易出问题,也可以通过yaml改:

yaml 复制代码
          preStop:
            exec:
              command:
              - /bin/sh
              - -c
              - curl -X POST 'http://127.0.0.1:9081/actuator/nacos-deregister' &&
                sleep 40

最终效果是

相关推荐
我是koten11 小时前
【运维杂谈】K8s遇到Terminating的名称空间删除不了怎么办?(解决方案亲测有效)
linux·运维·服务器·云原生·kubernetes·k8s·名称空间
2601_9621066416 小时前
【Java Set综合实战】商品管理系统 + 图书收藏系统|Product、Book自定义类全套代码
java
RuoyiOffice17 小时前
SpringBoot+Vue3 凭证生命周期设计:审核、过账、冲销与反过账怎样保持账目一致
java·spring boot·事务·springboot3·财务系统·会计凭证·ruoyi office
2601_9621066417 小时前
HashMap入门|工号-姓名键值存储、两种遍历方式、根据key/value查
java
RuoyiOffice17 小时前
KubeSphere 容器云实践:从管理 K8s 到建设企业 PaaS,还需要哪些能力
spring boot·kubernetes·kubesphere·jenkins·paas·微服务部署·ruoyi office
杨凯凡18 小时前
Spring Framework 7 API 版本管理实战:请求头路由、兼容迁移与废弃策略
java·rest api·springframework·spring boot 4·api版本管理
T_Wizard18 小时前
同一个问题写了 4 遍:官方 SDK / HTTP / Spring AI / LangChain4j,到底该选哪个
java·ai编程
hai_android18 小时前
AudioTrack 深度解析:从原理到实战
android·java·kotlin
斯维赤18 小时前
限流、熔断、降级,你真的分得清吗?
java·后端·架构
风吹稻子19 小时前
etcd备份与恢复:删了 etcd.yaml,容器为什么还在跑?——一次 K8s 控制面死锁排查实录
kubernetes