记一次K8S无感知不停机升级优化

2023-12-28 19:50

本文主要是介绍记一次K8S无感知不停机升级优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 背景
    • Deployment滚动更新策略
    • 容器探针
      • 检查机制
      • 探测结果
      • 探测类型
    • 删除和新建Pod情况分析
      • 【1】新Pod启动时请求处理
      • 【2】删除pod时请求处理
    • 参考

背景

在部署项目版本升级过程中发现每次都会出现2分钟左右的502停机情况,在进行问题和排查过程中发现如下配置中存在一些可以优化的点,本文是这次操作过程的总结以及一些简单的扩展。
在这里插入图片描述
分析下上面配置,使用是没有问题的,但是没有很好的利用K8s的一些特性机制来提升升级的效率,首先我们使用了Deployment声明式组件,该组件为 Pods 和 ReplicaSets 提供声明式的更新能力,提供了默认的滚动更新机制,如果按照下面所示先执行kubectl delete操作那么会将所有pod删除,等待删除后再依次创建新的pod,那么中间必然存在一个较大的空档期,即副本数被删除完毕,开始创建第一个Pod副本时,此时访问应用就会出现502网关问题,更友好的一种方式是使用RollingUpdate 滚动更新方式,这也是默认的配置。其次,最后俩行的配置是重复了,直接执行kubectl apply是可以完成修改升级操作的。
修改完成之后再次部署发现整个发布过程还是存在一些问题,多次请求下间断性出现一些502和404的错误,经过排查发现是因为Pod启动时未完全启动成功就接入流量导致4XX问题,还有在Pod已经删除后还依然有流量接入导致出现502问题.

Deployment滚动更新策略

疑问:有了Pod组件为什么还需要Deployment组件?
分析
【1】Pod是K8S调度的最小单元。但是Pod中容器出现异常终止了是不会重启的。
【2】Deployment拥有更加灵活强大的升级、回滚功能,并且支持滚动更新
【3】使用Deployment升级Pod只需要定义Pod的最终状态,k8s会为你执行必要的操作
【4】pod是k8s里调度的最小单位,而deployment是更高一层的定义。纯pod我们是无法确保其运行,无法对其异常做出处理的。
在这里插入图片描述
Deployment提供了俩个升级机制RollingUpdate滚动更新,这也是默认的机制。即先创建一个新的 Pod,并待其成功运行以后,再删除旧的。另外一个策略是Recreate,即先删除现有的 Pod,再创建新的。关于 Deployment,还可以设置最大不可用(maxUnavailable)和最大增量(maxSurge),来更精确地控制滚动更新操作,在RollingUpdate滚动更新策略下,Deployment 控制器会不断对 ReplicaSet 进行调和,滚动更新的最大好处就是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性。

容器探针

Kubernetes 中提供了一系列的健康检查,可以定制调用,来帮助解决类似的问题,我们称之为 Probe(探针)。
probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。

检查机制

使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:
exec
在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
grpc
使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是 “SERVING”,则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了 “GRPCContainerProbe” 特性门控时才能使用。
httpGet
对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。
tcpSocket
对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。

探测结果

每次探测都将获得以下三种结果之一:
Success(成功)
容器通过了诊断。
Failure(失败)
容器未通过诊断。
Unknown(未知)
诊断失败,因此不会采取任何行动。

探测类型

针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:
livenessProbe
指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。
readinessProbe
指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。
startupProbe
指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。

删除和新建Pod情况分析

【1】新Pod启动时请求处理

默认情况下,一旦某个 pod 中的所有容器全部启动,k8s 就会认为该 pod 处于就绪状态,从而将流量发往该 pod。但某些应用启动后,还需要完成数据或配置文件的加载工作才能对外提供服务,因此通过容器是否启动来判断其是否就绪并不严谨。通过为容器配置就绪探针,能让 k8s 更准确地判断容器是否就绪,从而构建出更健壮的应用。K8s 保证只有 pod 中的所有容器全部通过了就绪探测,才允许 service 将流量发往该 pod。一旦就绪探测失败,k8s 会停止将流量发往该 pod。
对于Java语言程序来说,可能还需要启动spring boot框架,连接数据库等待,注册服务等等。这样就会导致短暂的服务不可用。尤其是对于启动耗时的应用来说更是如此,就拿参与项目为例,平均启动时间都在30s以上,在升级过程中经常会出现404的问题。
对于该类情况,就需要进行ReadinessProbe 探测来检验容器是否满足需求

【2】删除pod时请求处理

当 Pod 在 kube-proxy 或 Ingress 控制器删除之前终止,我们可能会遇到停机时间。此时,Kubernetes 仍将流量路由到 IP 地址,但 Pod 已经不存在了。Ingress 控制器、kube-proxy、CoreDNS 等也没有足够的时间从其内部状态中删除 IP地址。
理想情况下,在删除 Pod 之前,Kubernetes 应该等待集群中的所有组件更新了 endpoint 列表,但是 Kubernetes 不是那样工作的。

Kubernetes 提供了原语来分发 endpoint(即 Endpoint 对象和更高级的抽象,例如 Endpoint Slices),所以 Kubernetes 不会验证订阅 endpoint 更改的组件是否是最新的集群状态信息。

那么,如何避免这种竞争情况并确保在 endpoint 广播之后删除 Pod?我们需要等待,当 Pod 即将被删除时,它会收到 SIGTERM 信号。我们的应用程序可以捕获该信号并开始关闭。由于 endpoint 不会立即从 Kubernetes 的所有组件中删除。
处理过程:
1:等待一定的时间,然后退出
2:即便有 SIGTERM 信号,但仍然可以处理传入流量。
3:最后,关闭现有的长期连接。关闭该进程。

那么我们应该等多久?默认情况下,Kubernetes 将发送 SIGTERM 信号并等待 30 秒,然后强制终止该进程。因此,我们可以使用前 15 秒继续操作。该间隔应足以将 endpoint 删除信息传播到 kube-proxy、Ingress 控制器、CoreDNS 等,然后,到达 Pod 的流量会越来越少,直到停止。15 秒后,我们就可以安全地关闭与数据库的连接并终止该过程。

如果我们认为需要更多时间,那么可以在 20 或 25 秒时停止该过程。这里有一点要注意,Kubernetes 将在 30 秒后强行终止该进程(除非我们更改 Pod 定义中的 terminationGracePeriodSeconds)。如果我们无法更改代码以获得更长的等待时间要怎么办?我们可以调用脚本以获得固定的等待时间,然后退出应用程序。

在调用 SIGTERM 之前,Kubernetes 会在 Pod 中公开一个 preStop hook。我们可以将 preStop hook 设置为等待 15 秒。下面是一个例子:

apiVersion: v1
kind: Pod
metadata:name: my-pod
spec:containers:- name: webimage: nginxports:- name: webcontainerPort: 80lifecycle:preStop:exec:command: ["sleep", "15"]

目前的解决方式:
1:设置prestop休眠15秒
2:启动时延迟几十秒,进行tcp端口的探测,其中8888端口是容器应用的端口
3:通过本次的修改在现阶段的发布部署基本上不会有任何的升级停机切换的感知了,是非常平稳的滚动升级

       lifecycle:preStop:exec:command: ["sleep","15"]readinessProbe:failureThreshold: 3initialDelaySeconds: 15periodSeconds: 30successThreshold: 1tcpSocket:port: 8888timeoutSeconds: 1

上面的休眠的方式只是一种简单的处理方式,如果你先想要自己的业务更友好的去处理启动和停机,对于SpringBoot应用来说可以进行一些特定的配置修改来完成应用上的优雅停机,Spring Boot 2.3.0.RELEASE引入了Graceful Shutdown的功能。其中所有四个嵌入式Web服务器(Tomcat,Undertow,Netty和Jetty)都为响应式和基于Servlet的Web应用程序提供优雅停机功能。

参考

Pod 的生命周期
https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#container-probes

Spring Boot 2.3.0配置Graceful-Shutdown,Readiness和Liveness
https://blog.csdn.net/fly910905/article/details/106895363

Liveness and Readiness Probes in Spring Boot
https://www.baeldung.com/spring-liveness-readiness-probes

K8s 中优雅停机和零宕机部署
https://zhuanlan.zhihu.com/p/188357747

K8s 应用管理之道 - 升级篇(一)
https://developer.aliyun.com/article/688626?spm=a2c6h.14164896.0.0.47b977b5MUvfoW

这篇关于记一次K8S无感知不停机升级优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/547094

相关文章

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Python包管理工具pip的升级指南

《Python包管理工具pip的升级指南》本文全面探讨Python包管理工具pip的升级策略,从基础升级方法到高级技巧,涵盖不同操作系统环境下的最佳实践,我们将深入分析pip的工作原理,介绍多种升级方... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

Python UV安装、升级、卸载详细步骤记录

《PythonUV安装、升级、卸载详细步骤记录》:本文主要介绍PythonUV安装、升级、卸载的详细步骤,uv是Astral推出的下一代Python包与项目管理器,主打单一可执行文件、极致性能... 目录安装检查升级设置自动补全卸载UV 命令总结 官方文档详见:https://docs.astral.sh/

苹果macOS 26 Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色

《苹果macOS26Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色》在整体系统设计方面,macOS26采用了全新的玻璃质感视觉风格,应用于Dock栏、应用图标以及桌面小部件等多个界面... 科技媒体 MACRumors 昨日(6 月 13 日)发布博文,报道称在 macOS 26 Tahoe 中

华为鸿蒙HarmonyOS 5.1官宣7月开启升级! 首批支持名单公布

《华为鸿蒙HarmonyOS5.1官宣7月开启升级!首批支持名单公布》在刚刚结束的华为Pura80系列及全场景新品发布会上,除了众多新品的发布,还有一个消息也点燃了所有鸿蒙用户的期待,那就是Ha... 在今日的华为 Pura 80 系列及全场景新品发布会上,华为宣布鸿蒙 HarmonyOS 5.1 将于 7

SpringBoot中HTTP连接池的配置与优化

《SpringBoot中HTTP连接池的配置与优化》这篇文章主要为大家详细介绍了SpringBoot中HTTP连接池的配置与优化的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、HTTP连接池的核心价值二、Spring Boot集成方案方案1:Apache HttpCl

PyTorch高级特性与性能优化方式

《PyTorch高级特性与性能优化方式》:本文主要介绍PyTorch高级特性与性能优化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、自动化机制1.自动微分机制2.动态计算图二、性能优化1.内存管理2.GPU加速3.多GPU训练三、分布式训练1.分布式数据