0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用Kubernetes实现零停机应用程序

马哥Linux运维 来源:马哥Linux运维 作者:马哥Linux运维 2023-09-01 10:04 次阅读

我在本地和托管 Kubernetes 集群方面工作了七年多。我能说的是,容器已经彻底改变了托管格局!它带来了许多需要复杂设置的设施。拥有多个实例,具有滚动重启、零停机、健康检查等功能。以前真是费时费力(实现 VRRP 解决方案、使用 monit 之类的应用程序监控重启、负载均衡 haproxy 之类的)!

因此,现在使用 Kubernetes 可以更轻松地访问一切,但如果您想为应用程序的生命周期构建完美的设置,您仍然必须了解它的工作原理以及根据您的情况应遵循哪种策略。
在本文中,我将解释为什么以及如何使用 Kubernetes 实现零停机应用程序。

容器镜像位置

如果您已经使用Docker一段时间,那么这看起来很简单。拉取和使用容器镜像非常简单。但是,在生产环境中,如果您不是映像所有者,您通常不想依赖远程且不受控制的映像注册表。为什么?

注册表可能会消失,并且您无法再拉取镜像( Kubernetes 上出现ImagePullBackOff错误)

您正在使用的图像标签已被删除(相同的ImagePullBackOff错误)

图像标签没有改变,但图像内容不再相同(非不可变图像,因此图像哈希值不同)。集群的不同节点上的图像之间的行为不相同(取决于标签何时更改并在集群节点上拉取)

它不符合您要求控制这些图像的安全要求(SOC2、HIPPA…)。

存在多种解决方案。一种是将容器映像从源注册表同步到您自己的注册表

Pod 数量(应用程序实例)

这听起来很明显,但如果您正在寻求高可用性,则您的应用程序至少需要2 个 Kubernetes 副本(2 个 Pod)。例子:

apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx
spec:
replicas:2#tellsdeploymenttorun2podsmatchingthetemplate
template:
..

我多次听到的关于 Kubernetes 的一个常见错误是:“我不需要两个实例,因为 Kubernetes 执行滚动更新,因此它将在关闭当前实例之前启动一个新实例”。确实如此,但它仅适用于部署更新
以下是不适用此规则的其他场景:

当您丢失运行应用程序的节点时(节点崩溃、硬件故障......)。您的应用程序pod 必须从头开始:

1/镜像拉取(如果节点上尚未存在):拉取时间取决于镜像大小

2/磁盘附件(如果有):需要几秒钟(通常观察到最多 1 分钟)

3/应用程序启动:可能会有所不同,具体取决于受影响的资源和应用程序类型(Java 应用程序通常需要更长的时间才能启动)

4 / probes:它们正在等待您的应用程序准备好提供服务,并增加了几秒钟的时间

当集群请求节点耗尽时(例如在 EKS 升级或节点类型更改期间):
要替换的节点上的 Pod 会收到SIGTERM信号以正常停止。Pod 正在从RUNNING状态切换到TERMINATING状态。此处,Kubernetes 服务已更新,以停止向TERMINATING pod 发送流量。因此,您不会再收到流量并且会出现停机时间。然后创建一个新的 Pod(请参阅上面的场景),在此期间,您不会收到任何流量。不幸的是,Kubernetes 在杀死一个 pod 之前不会启动一个新的 pod。

这就是为什么设置两个实例是避免停机的最低要求(另请参阅 Pod 反关联性部分)。

Pod 中断预算

PodDisruptionBudget (PDB) 是一个 Kubernetes 对象,它指定在部署、维护或任何给定时间不可用的 Pod 数量。这有助于确保您的应用程序保持可用,即使某些 pod 被终止或驱逐也是如此。
让我们举一个例子,我的应用程序有三个 pod(实例);我总是希望始终拥有至少两个running;我可以应用一个 PDB 对象,这将保证我始终有至少两个正在运行的 pod!

apiVersion:policy/v1
kind:PodDisruptionBudget
metadata:
name:my-pdb
spec:
maxUnavailable:1
selector:
matchLabels:
app:my-app

部署策略

Kubernetes 部署有两种策略:
RollingUpdate:默认更新,部署顺利。重新创建:在启动较新版本的应用程序之前强制应用程序完全关闭。
031dd28c-480c-11ee-97a6-92fbcf53809c.png
0335dc10-480c-11ee-97a6-92fbcf53809c.png
0363aa6e-480c-11ee-97a6-92fbcf53809c.png
037dad56-480c-11ee-97a6-92fbcf53809c.png
03900e56-480c-11ee-97a6-92fbcf53809c.png

默认情况下,应用 RollingUpdate 策略。但是您可以使用其他选项(例如最大不可用百分比和最大激增)来调整部署的方式。当您面临繁重的流量负载并且想要控制部署速度以最大程度地减少性能影响时,这些选项非常有用。

自动回滚部署

不幸的是,自动回滚并不是 Kubernetes 默认提供的功能。一般来说,您必须使用 Helm、ArgoCD、Spinnaker 等第三方工具才能实现自动回滚。
大多数人想要的很简单:如果我的应用程序无法正常启动,不要向其发送流量并回滚。
例如,对于 Helm,使用 Helm 实现它的一些选项很有趣:

— wait

— wait-for-jobs

— atomic

为了获得运行良好的解决方案,必须设置并正确配置探针(请参阅下一节)。如果 pod 没有通过其活性探针正常启动,则会自动回滚。

Probe 探针

不幸的是,探针经常被低估,但它们对于实现零停机非常重要!
验证应用程序健康状况的两个最重要的探测器是“Liveness”和“Readiness”探测器。比长篇大论更好的是,这里有一个解释目标的模式:

Kubernetes 探针工作流程
Liveness探针可确保您的应用程序处于活动状态,并将决定 pod 是存活还是死亡!
如果活性探测未成功:

Pod 停止接收流量

Pod 重新启动,尝试恢复健康状态。任何进一步的重新启动都会应用指数退避(指数延迟)

Readiness 探针决定是否将流量发送到您的 Pod。

如果您的流量出现突发(并且活性探针正在响应),但您的应用程序开始变慢,则就绪状态可以决定停止向您的应用程序发送流量。让它恢复到更加健康的状态。

如果就绪探针没有响应,则不会重新启动您的 Pod。它仅请求负载均衡器停止向该 Pod 发送流量。

在什么情况下配置自定义活跃度和就绪度探测器有用?
答案是“永远”!当然,您可以使用简单的 TCP 检查,但它永远不会像您自己在应用程序中构建的自定义探针(例如,REST API 上的专用端点)那样可靠。

初始启动时间延迟

初始启动时间可能需要延迟。它可能发生在不同的情况下:

您的应用程序使用大量 CPU 来启动(例如 SpringBoot 应用程序)。

您的应用程序需要在启动时执行比以前更多的操作(由于新功能),并且您没有升级分配的 CPU 资源。

您的应用程序必须加载数据库中的架构和其中的数据,并且在数据库准备就绪之前它才可用。

还存在其他几个例子……

但这是可能发生片状启动的示例。如果您遇到这种情况或想要预见它,您应该像这样更新initialDelaySeconds :

livenessProbe:
initialDelaySeconds:60
httpGet:
...

注意:存在专用启动探测器,但在大多数情况下可能没有用。一般来说,initialDelaySeconds选项就足够了。

优雅终止期 GrancePeriodSeconds

这个 Kubernetes 选项并不直接与零停机功能相关,而是更多地涉及忽略应用程序正常关闭的重要性的缺点效应。
仅当应用程序能够拦截 SIGTERM时,优雅终止期才能起作用!如果应用程序未编码为拦截 SIGTERM,则它只会硬终止应用程序,无论是否存在大于 30 秒的优雅终止期,这都可能导致数据丢失。
不管理 SIGTERM 可能会带来几个问题:

糟糕的用户体验:用户遇到错误、空白页面或更糟的情况

丢失数据:数据尚未提交,用户事务丢失

不可恢复的数据:刷新磁盘上的数据突然停止,您的应用程序无法处理它

还存在其他原因,但您会看到让应用程序足够快地关闭是多么重要。
硬件故障总是有可能的,因此您的应用程序应该始终能够在此类故障后恢复。然而,类似的常规故障不应频繁发生。
多给你一点时间让你的应用程序正常停止通常是很好的做法(<5 分钟)。Kubernetes 默认值为 30 秒,但您可以使用终止GracePeriodSeconds 选项进行调整。

Pod 反亲和力

Pod 反关联性可让您避免同一节点上存在同一应用程序 (Pod) 的多个实例。当所有实例都位于同一节点上时发生节点崩溃时,您可以想象会发生停机。
为了避免这种情况,您可以要求 Kubernetes 避免所有 pod 都位于同一节点上。存在两个版本:

软反亲和性Soft Anti-Affinity

PreferredDuringSchedulingIgnoredDuringExecution:它将尽最大努力避免它,但如果它不能(缺乏资源),它将在同一节点上添加两个实例。这个版本具有成本效益,并且在 95% 的情况下都能发挥作用。

Hard Anti-Affinity

requiredDuringSchedulingIgnoredDuringExecution:这将是一个硬性要求,不能在同一节点上有两个 pod。但如果您要求同一应用程序有 50 个 pod,则需要 50 个节点。这很快就会变得非常昂贵。

这是它在 Kubernetes 上的样子:

affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
-labelSelector:
matchExpressions:
-key:security
operator:In
values:
-S1
topologyKey:topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
-weight:100
podAffinityTerm:
labelSelector:
matchExpressions:
-key:security
operator:In
values:
-S2
topologyKey:topology.kubernetes.io/zone

资源

资源是最常见的问题之一。当设置的资源不足时,您的应用程序可以:

内存不足 (OOM) 并被内核驱逐。所以你会遇到停机、连接严重关闭等情况……

你设置的CPU够用了吗?您的应用程序可能需要很长时间才能响应,甚至有时在活动检查成功之前无法启动。运行 100% 的 CPU 可能会强制自动缩放程序添加过多的实例。而您只需要利用当前的 CPU 数量即可。除非您知道自己在做什么,否则低于 100m 通常不好。

自动缩放Autoscaling

自动缩放是避免流量负载下停机的好方法。默认基于CPU(可以使用其他自定义指标)。这是自动部署更多实例(Pod)的简单方法。
自动缩放并不是魔法!您必须在 Kubernetes 上正确配置您的应用程序。
因此,例如,当您的 pod 短时间内运行超过 60% 的 CPU 时,Kubernetes 会触发一个新的 pod 来处理负载并减少当前正在运行的应用程序的使用率。
以下是 Kubernetes 上的示例:

apiVersion:autoscaling/v2
kind:HorizontalPodAutoscaler
spec:
...
minReplicas:1
maxReplicas:10
metrics:
-type:Resource
resource:
name:cpu
target:
type:Utilization
averageUtilization:50

结论

Kubernetes 确实有神奇的作用,但只有当应用程序尽可能是云原生且配置正确时,它才能发挥神奇作用。
总之,当您想将应用程序引入 Kubernetes 时,您至少应该注意:

最少两个实例

添加健康检查(探针)

您的应用程序必须处理 Sigterm

配置自动缩放器

给予足够的资源

使用 pod 反亲和力

添加 PDB

如果一切设置正确,Kubernetes 体验将令人难以置信,您将不会再遭受任何停机。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    481

    浏览量

    21883
  • 应用程序
    +关注

    关注

    37

    文章

    3136

    浏览量

    56400
  • 负载均衡
    +关注

    关注

    0

    文章

    97

    浏览量

    12189
  • Docker
    +关注

    关注

    0

    文章

    437

    浏览量

    11603
  • kubernetes
    +关注

    关注

    0

    文章

    219

    浏览量

    8568

原文标题:结论

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Kubernetes 网络模型如何实现常见网络任务

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernetes 网络模型可以使你能够正确运行、监控和排查
    的头像 发表于 10-08 11:32 839次阅读

    阿里云宣布推出Serverless Kubernetes服务 30秒即可完成应用部署

    ,而是更专注在编写应用程序逻辑上。据悉,在Serverless Kubernetes模式下,开发者只需指明应用容器镜像、CPU和内存需求,选定对外服务模式,即可直接启动应用程序,敏捷便利部署于包括web
    发表于 05-03 15:38

    如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes

    前言 在之前的一篇文章中,我们介绍了  如何将一个本地的 Java 应用程序直接部署到阿里云 ECS  ,有不少读者反馈,如果目前已经在使用阿里云容器服务 Kubernetes 了,那该如何配合这个
    发表于 12-28 16:06 314次阅读
    如何在 Intellij IDEA 更高效地将应用部署到容器服务 <b class='flag-5'>Kubernetes</b>

    在Windows 10上创建单节点的Kubernetes实施示例

    Kubernetes使开发人员和系统管理员可以快速部署应用程序并将其扩展到其需求,而无需停机Kubernetes系统是高度可配置的,几乎所有内容都围绕四个重要概念:节点,pod,部署
    的头像 发表于 05-05 21:01 1652次阅读
    在Windows 10上创建单节点的<b class='flag-5'>Kubernetes</b>实施示例

    首次部署 Kubernetes 应用程序需注意的“陷阱”

    根据我的个人经验,大多数人似乎倾向于通过 Helm 或者手动方式将应用程序甩给 Kubernetes,之后就坐等每天轻松调用的美好生活。但在 GumGum 公司的实践当中,我们体会到
    的头像 发表于 10-08 14:43 1548次阅读
    首次部署 <b class='flag-5'>Kubernetes</b> <b class='flag-5'>应用程序</b>需注意的“陷阱”

    新版本Portworx PX-Backup助力Kubernetes有状态应用程序实现跨云数据保护与迁移

    最新Portworx调查显示数据流动性和数据保护为Kubernetes有状态应用程序管理的最大挑战。
    的头像 发表于 11-10 15:06 3564次阅读
    新版本Portworx PX-Backup助力<b class='flag-5'>Kubernetes</b>有状态<b class='flag-5'>应用程序</b><b class='flag-5'>实现</b>跨云数据保护与迁移

    使用NVIDIA操作符加速Kubernetes

      Kubernetes 是一个开源的容器编排系统,用于自动化计算机应用程序部署、扩展和管理。它是一个非常流行的工具,可以用于自动展开和回滚、水平扩展、存储编排等。对于许多组织来说, Kubernetes 是其基础架构的关键组件
    的头像 发表于 04-11 16:13 810次阅读

    Kubernetes网络模型介绍以及如何实现常见网络任务

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernetes 网络模型可以使你能够正确运行、监控和排查
    的头像 发表于 05-05 20:22 1484次阅读

    KUBERNETES开源平台的定义、工作原理及重要意义

    Kubernetes 是一个开源平台,用于自动进行容器编排,即容器化应用程序的部署、扩展和管理。
    的头像 发表于 06-10 12:00 1504次阅读

    Kubernetes网络模型的基础知识

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernetes 网络模型可以使你能够正确运行、监控和排查
    的头像 发表于 07-20 09:46 926次阅读

    跟踪Kubernetes的网络流量路径

    通过本文,你将了解在 Kubernetes 内外,数据包是如何转发的,从原始的 Web 请求开始,到托管应用程序的容器。 在深入了解在 Kubernetes 集群中数据包如何流转的细节之前,先明确一下
    的头像 发表于 10-24 10:22 797次阅读

    Commvault宣布扩展面向Kubernetes工作负载的保护

    企业正越来越多地采用Kubernetes实现企业环境的现代化,并加快应用程序向云端的迁移。据Gartner预测,到2025年,全球85%的企业将在生产中运行容器化应用程序
    的头像 发表于 10-27 14:16 395次阅读

    如何从零开发Kubernetes Operator?

    大多数人使用Kubernetes的方式是使用原生资源(如Pod、Deployment、Service等)部署应用程序。但是,也可以扩展Kubernetes的功能,从而添加满足特定需求的新业务逻辑,这就是Operator的作用。
    的头像 发表于 01-05 11:27 972次阅读

    探讨使用YAML文件定义Kubernetes应用程序

    Kubernetes已经占据如何管理集容器化应用程序的核心位置。因此,存在许多定义Kubernetes应用程序的约定文件格式,包括YAML、JSON、INI等。
    的头像 发表于 04-20 10:03 350次阅读

    Jenkins pipeline是如何连接Kubernetes的呢?

    Kubernetes 是一个开源的容器编排平台,可以帮助开发团队管理和部署容器化的应用程序
    的头像 发表于 10-23 11:13 1500次阅读
    Jenkins pipeline是如何连接<b class='flag-5'>Kubernetes</b>的呢?