当前位置: 首页 > news >正文

容器滚动更新过程中流量无损

应用在发布或重启的期间会出现少量的 5xx 异常,应该如何解决?

我们发现导致流量有损的原因有很多,比如:

  • 上线时,应用在就绪前收到流量,导致请求无法被处理;

  • 下线时,应用没有做优雅退出导致请求中断,应用没有正确监听到终止信号导致优雅退出无效,平台路由规则更新不及时导致流量转发到已经销毁的副本等;

传统的解决方式是通过将应用更新流程划分为手工摘流量、停应用、更新重启三个步骤,由人工操作实现客户端不对更新感知,这种方式简单而有效,但是限制较多。不仅需要使用借助网关的支持来摘流量,还需要在停应用前人工判断来保证在途请求已经处理完毕。

滚动更新机制

在容器上线时, ReplicaSet 控制器会向 kube-apiserver 组件发送创建 Pod 的请求,kube-scheduler 组件负责选择合适的节点的节点来运行新的 Pod,并将选择的节点写入 Pod 对象的 spec.nodeName 字段中。

部署在每个节点中的 kubelet 组件会监听 Pod 对象的变化,当新的 Pod 被调度到所在的节点时,kubelet 组件会使用 CRI 来启动容器,并在启动后对 Pod 内每个容器执行启动探测。

在启动探测通过后,再分别对每个容器周期性地执行存活探测和就绪探测,在 Pod 内所有容器都通过就绪探测之后,kubelet 组件会把 Pod 标记为 Ready 状态,同时上报给 kube-apiserver 组件。

而 Endpoint 控制器会监听 Pod 的变化,当 Pod 的状态变为Ready状态时,会将 Pod 的 IP 和端口添加到 Endpoint 对象中, kube-proxy 组件在监听 Endpoint 对象的变化后会使用 ipvs 或 iptables 在节点中生成流量转发的规则。

在容器下线时,ReplicaSet 控制器会向 kube-apiserver 组件发送删除 Pod 的请求,kube-apiserver 不会立即删除 Pod,而是在 Pod 的metadata 中添加 deletionTimestamp 字段,将 Pod 的状态标记为 Terminating。

当 kubelet 组件监听到 Pod 对象的 deletionTimestamp 被设置时,就会调用 CRI 向容器发起停止容器的请求,如果容器设置了 PreStop 钩子,kubelet 会在发送 SIGTERM 信号之前先执行 PreStop 钩子,等待 PreStop 钩子执行完成后再发送 SIGTERM 信号,接着在 terminationGracePeriodSeconds 后发送 SIGKILL 信号去杀死所有容器进程,完成容器的停止过程。

在 kubelet 停止容器的同时,Endpoint 控制器监听到 Pod 的状态变化,会将 Pod 的 IP 从相应的 Endpoint 对象中移除,kube-proxy 组件监听到 Endpoint 对象的变化后,会移除 Pod IP 的转发规则。kube-proxy 在不同的模式下移除转发规则的方式会有所不同,比如 ipvs 模式下会把规则的权重修改为0,iptable 模式下则是直接删除转发规则。

流量有损情况

1、没有配置就绪探测导致服务上线有损

如果没有配置就绪探测,Pod 在启动完成后会立即被视为Ready就绪状态,然后开始接收流量,如果此时容器内的进程还在初始化资源的状态就会造成流量有损。

2、就绪探测配置不当导致服务上线有损

就绪探测提供了三种探测方式:HTTP 探测、命令行探测、TCP 探测,对于常规的 Web 服务,我们应该首选 HTTP 探测、备选命令行探测,尽量避免使用 TCP 探测。

在使用 TCP 探测时,kubelet 组件会向指定端口发送 TCP SYN 包,如果 Pod 响应 TCP ACK包则表明监听的端口处于打开状态,则探测成功。但TCP 探测只能检测网络连接是否建立、服务端口是否打开,无法反应服务的真实健康状态,比如程序的端口虽然已经打开,但如果内部正在初始化资源或者出现了死锁等问题的话,也就无法正常处理流量,即流量打到表面健康但实际不健康的 Pod 上,造成流量有损。

3、没有配置优雅退出导致服务下线有损

服务下线过程中,已进入容器的流量如果没有被处理完,容器就被杀死,导致调用方收到502。

服务下线的过程中,Kubernetes 的 kubelet 和 kube-proxy 组件会同时监听 Pod 的变化,然后分别去清理容器和网络的路由转发规则,这个过程是同时进行的。在某些情况下,kubelet 有可能在 kube-proxy 更新完路由转发规则前就已经销毁了容器,这时新的流量被转发进来时,就会出现异常。

优雅退出可以让程序在退出前执行的一系列保证应用正常关闭的操作,这些操作往往包括等待已有请求执行完成、等待尚未完成的事务处理、清理资源(比如关闭文件描述符、关闭socket)、持久化内存数据(比如将内存中的数据落盘到文件中)等,同时能够让 kubelet 组件在等待一段时间后在执行回收容器的操作,给 kube-proxy 留够清理的时间。

优雅退出本质上是JVM即将关闭前执行的一些额外的处理代码。

4、监听SIGTERM信号但业务程序不是作为1号进程启动

如下代码,程序监听了SIGTERM信号,在收到SIGTERM信号时执行清理工作。

package mainimport ("fmt""os""os/signal""syscall""time"
)func main()  {c := make(chan os.Signal)signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)go func() {for s := range c {switch s {case syscall.SIGINT, syscall.SIGTERM:fmt.Println("退出", s)ExitFunc()default:fmt.Println("other", s)}}}()fmt.Println("进程启动...")time.Sleep(time.Duration(200000)*time.Second)
}func ExitFunc()  {fmt.Println("正在退出...")fmt.Println("执行清理...")fmt.Println("退出完成...")os.Exit(0)
}

(1)使用启动脚本启动

业务程序在容器中没有作为1号进程启动,而是作为启动脚本start.sh的子进程启动,容器中的 1 号进程 start.sh 收到了 SIGTERM 信号但并没有转发给它的子进程,导致业务程序没有办法做优雅退出,最后只能因为 SIGKILL 信号而被强制杀掉。

# 构建
FROM golang:alpine as buildWORKDIR /demoADD . .RUN GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -o app main.go# 运行
FROM ubuntu:22.04 as prodCOPY --from=build /demo/app /demo/
COPY --from=build /demo/start.sh /demo/# 启动服务
CMD ["/demo/start.sh"]

启动脚本

#!/bin/sh# start.sh
# do something
/demo/app

(2)使用shell模式启动

在Dockerfile中CMD和ENTRYPOINT用来启动应用,有shell模式和exec模式。使用shell模式,PID为1的进程为shell;使用exec模式PID为1的进程为业务本身。

shell模式

CMD ./app

exec模式

CMD ["./app"]

需要注意的是 exec模式无法读取环境变量,仅shell模式能够读取环境变量。

(3)解决方式

1)配置prestop

容器在下线时的流程

deletionTimestamp -> prestop -> SIGTERM -> SIGKILL(terminationGracePeriodSeconds)

2)在 Dockerfile 中移除启动脚本 start.sh,让业务程序作为1号进程被启动。

# 让业务程序作为1号进程被启动
CMD ["/demo/app"]

3)保留启动脚本start.sh,使用 exec 命令启动业务程序,exec 用于执行新的命令,同时替换掉当前进程,即覆盖掉原来启动脚本 start.sh 的进程。

#!/bin/sh# do something
exec /demo/app

相关文章:

容器滚动更新过程中流量无损

应用在发布或重启的期间会出现少量的 5xx 异常,应该如何解决? 我们发现导致流量有损的原因有很多,比如: 上线时,应用在就绪前收到流量,导致请求无法被处理; 下线时,应用没有做优雅…...

深入理解JS中的this

1、浅谈this 1.1、调用位置 在学习this的绑定过程之前,首先要理解调用位置,即函数在代码中被调用的位置,因此我们需要分析调用栈,看以下代码 function baz(){// 当前调用栈是baz// 因此调用位置就是全局作用域console。log(&qu…...

rust 基础数据类型

默认类型 大部分情况下,rust 可以基于上下文自动推导出变量的类型。下面代码中,变量 x 没有显式,rust 默认是 i32 类型。 fn main() {let x 5; }但也有一些例外情况,比如,字符串类型的转换中变量 x 的类型&#xff…...

ELK极简上手

目录 引言 首先,下载相关的包 其次,安装启动elasticsearch 下一步,安装并启动logstash 最后,安装并启动kibana 进一步的,测试数据的流动 引言 最近整理电脑发现之前的一篇ELK极简入门笔记,现整理发出…...

在 JavaScript 中,变量的作用域是如何确定的?

在 JavaScript 中,变量的作用域是由作用域链(Scope Chain)来确定的。作用域链是指变量在执行期间访问的作用域的链式结构。 JavaScript 中的作用域分为全局作用域和局部作用域(函数作用域和块级作用域)。 全局作用域…...

常见面试题-TCP三次握手四次挥手

TCP 三次握手/四次挥手 参数用途SYN用于启动和建立连接时,同步设备之间的序列号。0到2^32 - 1的随机数。ACK向另一端确认已经收到 SYN,数值为收到 SYN 增一。SYN-ACK确认之前收到了 SYN,数值为自定义值。FIN终止连接。RST重置连接。 三次握…...

前端框架Vue学习 ——(六)Vue组件库Element

文章目录 Element 介绍快速入门常见组件表格分页Dialog 对话框组件表单 Container 布局容器 Element 介绍 Element:是饿了么团队研发的,一套为开发者、 设计师和产品经理准备的基于Vue 2.0的桌面端组件库。 组件:组成网页的部件,…...

第六章:Property-based Testing and Test Oracles

文章目录 Test OraclesActive and Passive Test OraclesTypes of Test OraclesFormal, executable specificationsSolved examplesMetamorphic oraclesAlternative implementations (备用实现)Heuristic oracles (启发式)The Golden Program!Oracle Deviation (Oracle偏差)T…...

react生命周期函数

React 组件的生命周期可分为三大阶段:挂载阶段(Mounting)、更新阶段(Updating)和卸载阶段(Unmounting)。 1.挂载阶段(Mounting) 在组件被插入到 DOM 中后,会…...

QSqlDatabase使用Sqlite

QSqlDatabase使用Sqlite Sqlite本身就可以被内嵌在程序中,QSqlDatabase也自带Sqlite驱动,无需任何第三方依赖,可以直接使用 QSqlDatabase _db QSqlDatabase::addDatabase("QSQLITE"); QString dbPath "/path/to/xxx.db&qu…...

宝马——使用人工智能制造和驾驶汽车

德国汽车制造商宝马(BMW)每年在全球制造和销售250万台汽车,其品牌包括宝马、MINI和劳斯莱斯。 宝马汽车以其卓越的性能和对新技术的应用而著名,它是道路上最精致的汽车之一,并且和其竞争对手戴姆勒(Daimler)一样,在将自动驾驶汽车…...

java入门,Map<? extends String, ?>

一、前言 是不是平时写业务代码的时候很少用到这个写法&#xff1a;Map<? extends String, ?>&#xff0c;这是Map类型&#xff0c;Map的键是? extends String 类型&#xff0c;值是?。为什么不是我们平时写的Map< String, Object>&#xff0c;这种写法有什么好…...

Spring Boot 统一处理功能

目录 1.用户登陆权限验证 1.1 每个方法验证 1.2 Spring AOP 用户统一登陆验证 1.3 拦截器 1.3.1 自定义拦截器 1.3.2 将自定义拦截器配置到系统设置中&#xff0c;并且设置拦截规则 1.3.3 排除所有的静态资源 1.4 登录拦截器&#xff08;练习&#xff09; 1.5 拦截器原…...

香港金融科技周VERTU CSO Sophie谈Web3.0的下一个风口 手机虚拟货币移动支付

10月31日&#xff0c;香港金融科技周正式拉开帷幕。这项香港金融科技界地年度盛事今年已经踏入了第八届&#xff0c;本届活动吸引超过数百位金融科技专业人士、创业者和行业领袖现场参与&#xff0c;线上参与观众超过10万人次。 在金融科技周的圆桌会议上&#xff0c;VERTU首席…...

分布式单元化

一 分布式单元化 1.1 两地三中心 顾名思义&#xff0c;两地指的是两个城市&#xff1a;同城&#xff0c;异地。三中心指的是三个数据中心&#xff1a;生产中心、同城容灾中心、异地容灾中心。 在同一个城市或者临近的城市建设两个相同的系统&#xff0c;双中心具备相当的业…...

wvp-gb28181-pro接入海康摄像头

网络-高级配置-平台接入 sip服务器信息默认参数如下&#xff0c;一键安装wvp完成之后默认就是这样的参数 设置项 设置值 平台接入方式 28181 本地sip端口 5060 传输协议 tcp、udp&#xff08;外网的话我建议还是用tcp&#xff09; 启用 勾选 协议版本 GB/T28181-201…...

近视眼选择什么台灯好?专家推荐的防近视台灯

年轻的时候不懂&#xff0c;以为自己的眼睛不好&#xff0c;近视度数高&#xff0c;是因为长时间看书造成的&#xff0c;其实我们都忽视了一个最为重要的影响因素&#xff0c;那就是灯光。如今的孩子面临着比我们以前更要繁重的学习压力&#xff0c;因此更需要注意用眼健康了&a…...

数据标注工具【LabelImg】安装使用 用VOC制作自己的数据集

labelImg的安装 ⭐️LabelImg简介⭐️LabelImg的安装⭐️labelImg标注数据集⭐️利用VOC制作自己的数据集 ⭐️LabelImg简介 Labelimg是一款开源的数据标注工具&#xff0c;标签可用于分类和目标检测&#xff0c;它是用python写的&#xff0c;并使用Qt作为其图形界面&#xf…...

Zeus IoT : 基于 SpringBoot 的分布式开源物联网大数据平台

Zeus IoT 是一个集设备数据采集、存储、分析、观测为一体的开源物联网平台&#xff0c;全球首创基于 Zabbix 的物联网分布式数据采集架构&#xff0c;具备超百万级物联网设备的并发监控能力&#xff0c;真正具备工业级性能与稳定性的开源物联网大数据中台。 Zeus IoT 致力于让设…...

面试—如何介绍项目中的多级缓存?

项目中使用的多级缓存也就是 分布式缓存 Redis 本地缓存 Caffeine&#xff0c;那么令 Caffeine 作为一级缓存&#xff0c;Redis 作为二级缓存&#xff0c;在项目中通过记录数据的访问次数&#xff0c;将热点数据放在 本地缓存&#xff0c;将非热点数据放在 Redis缓存 中&#…...

手把手教你用ROS2和ZED2 SDK搭建3D视觉开发环境(Ubuntu 20.04版)

手把手教你用ROS2和ZED2 SDK搭建3D视觉开发环境&#xff08;Ubuntu 20.04版&#xff09; 在自动驾驶、增强现实和机器人导航等领域&#xff0c;3D视觉感知已成为核心技术之一。ZED2相机凭借其双目深度感知能力和高精度SLAM算法&#xff0c;成为开发者构建空间智能系统的首选传感…...

避坑指南:UR5e机器人SpeedL模式下的笛卡尔空间控制,如何避免奇异点和超限?

UR5e机器人SpeedL模式避坑实战&#xff1a;笛卡尔空间控制的三大安全策略 实验室里&#xff0c;机械臂突然发出刺耳的警报声——这可能是每个UR5e初学者都经历过的噩梦。当你在笛卡尔空间用SpeedL指令控制机器人画复杂轨迹时&#xff0c;关节超限、奇异点问题和自碰撞就像三个隐…...

别再让PowerBI报告挤成一团了!用按钮+书签,一个页面搞定趋势和明细分析

PowerBI交互设计进阶&#xff1a;用按钮与书签打造空间魔术 当业务分析报告遇上数据爆炸时代&#xff0c;信息过载与界面拥挤成为每个分析师挥之不去的噩梦。我曾见过某零售企业的季度分析仪表板——12个图表密密麻麻挤在A4纸大小的画布上&#xff0c;趋势线相互缠绕&#xff…...

2026年小红书文案降AI工具怎么选?自媒体人亲测这4款最靠谱

开始做小红书内容之前&#xff0c;我以为降AI只是学生的事。后来才发现&#xff0c;品牌方审稿也在查AI率&#xff0c;小红书平台自己也有AI检测机制。 自媒体文案的降AI需求和论文不一样&#xff0c;核心要求是&#xff1a;保留口语化语感&#xff0c;不能变成学术腔。降完还…...

LeifHomieLib:ESP32/8266轻量级Homie v3 MQTT设备库

1. LeifHomieLib 项目概述LeifHomieLib 是一个专为 ESP8266 和 ESP32 平台设计的轻量级 Homie v3 协议实现库&#xff0c;其核心目标是为资源受限的物联网边缘节点提供符合 Homie 规范的 MQTT 设备抽象能力。该库并非 Homie v3 标准的全功能实现&#xff0c;而是聚焦于与 openH…...

Apache Doris 存储与查询优化实战:从架构设计到性能调优的完整指南

1. Apache Doris 架构设计精要 第一次接触Apache Doris时&#xff0c;我被它简洁的架构设计惊艳到了。这个MPP架构的分析型数据库&#xff0c;用计算存储分离的设计思路&#xff0c;把复杂的大数据分析变得像查普通MySQL表一样简单。FE&#xff08;Frontend&#xff09;和BE&am…...

Qwen3.5-4B-Claude-Opus保姆级教程:Web界面响应延迟归因与优化路径

Qwen3.5-4B-Claude-Opus保姆级教程&#xff1a;Web界面响应延迟归因与优化路径 1. 模型与部署环境概览 Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF是基于Qwen3.5-4B的推理蒸馏模型&#xff0c;特别强化了结构化分析、分步骤回答以及代码与逻辑类问题的处理能力。该…...

如何一键完成飞书文档格式转换:3种高效迁移方法指南

如何一键完成飞书文档格式转换&#xff1a;3种高效迁移方法指南 【免费下载链接】feishu2md 一键命令下载飞书文档为 Markdown 项目地址: https://gitcode.com/gh_mirrors/fe/feishu2md 想要将飞书文档快速转换为Markdown格式吗&#xff1f;feishu2md项目为您提供了一键…...

流程可视化引擎定制指南:从技术实现到业务价值转化

流程可视化引擎定制指南&#xff1a;从技术实现到业务价值转化 【免费下载链接】Drawflow Simple flow library &#x1f5a5;️&#x1f5b1;️ 项目地址: https://gitcode.com/gh_mirrors/dr/Drawflow 在数字化转型过程中&#xff0c;企业面临着业务流程可视化与实际业…...

Qwen3.5-4B-Claude-Opus应用场景:技术博客选题生成、文章大纲结构化输出

Qwen3.5-4B-Claude-Opus应用场景&#xff1a;技术博客选题生成与文章大纲结构化输出 1. 模型概述与核心能力 Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF是基于Qwen3.5-4B的推理蒸馏模型&#xff0c;特别强化了结构化分析和逻辑推理能力。这个经过优化的版本以GGUF…...