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

最终效果是

相关推荐
bing_158几秒前
Java 中求两个 List集合的交集元素
java·list
工业互联网专业19 分钟前
基于springboot+vue的高校社团管理系统的设计与实现
java·vue.js·spring boot·毕业设计·源码·课程设计
九圣残炎21 分钟前
【ElasticSearch】 Java API Client 7.17文档
java·elasticsearch·搜索引擎
m0_748251521 小时前
Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
java·ubuntu·centos
Bro_cat1 小时前
深入浅出JSON:数据交换的轻量级解决方案
java·ajax·java-ee·json
等一场春雨2 小时前
Java设计模式 五 建造者模式 (Builder Pattern)
java·设计模式·建造者模式
hunzi_12 小时前
Java和PHP开发的商城系统区别
java·php
V+zmm101342 小时前
教育培训微信小程序ssm+论文源码调试讲解
java·数据库·微信小程序·小程序·毕业设计
十二同学啊2 小时前
Spring Boot 中的 InitializingBean:Bean 初始化背后的故事
java·spring boot·后端
我劝告了风*2 小时前
NIO | 什么是Java中的NIO —— 结合业务场景理解 NIO (二)
java·nio