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

最终效果是

相关推荐
chushiyunen12 分钟前
dom操作笔记、xml和document等
xml·java·笔记
whisperrr.12 分钟前
【spring01】Spring 管理 Bean-IOC,基于 XML 配置 bean
xml·java·spring
chushiyunen14 分钟前
tomcat使用笔记、启动失败但是未打印日志
java·笔记·tomcat
天上掉下来个程小白21 分钟前
HttpClient-03.入门案例-发送POST方式请求
java·spring·httpclient·苍穹外卖
ModestCoder_30 分钟前
将一个新的机器人模型导入最新版isaacLab进行训练(以unitree H1_2为例)
android·java·机器人
a180079310801 小时前
软件工程面试题(二十二)
java·面试·软件工程
RainbowSea1 小时前
4. RabbitMQ 发布确认的配置详细说明
java·消息队列·rabbitmq
robin_suli1 小时前
Spring事务的传播机制
android·java·spring
青云交1 小时前
Java 大视界 -- Java 大数据在智能电网电力市场交易数据分析与策略制定中的关键作用(162)
java·大数据·数据分析·交易策略·智能电网·java 大数据·电力市场交易
m0Java门徒1 小时前
Java 递归全解析:从原理到优化的实战指南
java·开发语言