前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在 Kubernetes 滚动部署中实现真正的零停机时间:避免断开的客户端连接

如何在 Kubernetes 滚动部署中实现真正的零停机时间:避免断开的客户端连接

作者头像
DevOps云学堂
发布2024-06-19 18:31:06
1980
发布2024-06-19 18:31:06
举报
文章被收录于专栏:DevOps持续集成DevOps持续集成

流行的成语“除了变化之外,没有什么是不变的”来自一位名叫赫拉克利特的希腊哲学家。尽管赫拉克利特生活在公元前 500 年左右,但这句话仍然有效。多亏了像 Kubernetes 这样超高效的编排工具,对我们的应用程序进行更改变得更加无缝。

在软件工程中,我们几乎每天都在进行更改,但是我们如何避免这些更改对用户产生负面影响呢?对用户的负面影响之一是连接中断。我本来很想讨论客户端连接断开的影响,但不是在本文中。

默认情况下,Kubernetes 部署策略涉及滚动部署。是的!滚动部署听起来很有趣,但还有更多。我们需要问自己一些问题。滚动部署期间会发生什么情况?

滚动部署意味着逐步将当前容器替换为新容器。在此过程中,总是有从微秒到秒的停机时间。对于用户群较低的应用程序来说,它可能微不足道。但对于大型应用来说,尤其是支付网关,它非常重要,因为每一秒都很重要。

注意:在 Kubernetes 中部署到生产环境时,还有其他方法可以实现零停机时间,例如利用 Istio 等服务网格或实现蓝绿部署。与滚动部署相比,这些选项消耗的资源更多,从而导致基础设施成本增加。

“滚动部署期间会发生什么?”这个问题可以分为两个。 首先,当 Pod 启动时会发生什么,当 Pod 关闭时会发生什么? 在继续之前,以下是本教程的先决条件:

  • Kubernetes 知识
  • 使用Docker的经验

Pod 的启动阶段

当 Pod 在未配置就绪探测的滚动部署中启动时,端点 Controller 会使用容器的端点更新相应的服务对象,这意味着即使 Pod 尚未就绪,Pod 也会开始接收流量。缺少就绪探测会使应用程序不稳定。

建议对应用程序设置就绪探测。这意味着它只在准备就绪时才接收流量;端点控制器会根据 Pod 的就绪情况探测结果继续监控 Pod。探测成功后,将在服务对象上更新终结点以接收流量。 下面是配置了就绪探测的 Kubernetes 部署文件示例:

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-highly-available-app
spec:
  replicas: 3 # Define desired number of replicas
  selector:
    matchLabels:
      app: highly-available
  template:
    metadata:
      labels:
        app: highly-available
    spec:
      containers:
      - name: highly-available
        image: highly-available-image:latest
        ports:
        - containerPort: 80
        readinessProbe: # Readiness probe configuration
          httpGet:
            path: /health-check
            port: 80
            initialDelaySeconds: 5 # Wait 5 seconds before starting probes
            periodSeconds: 10 # Check every 10 seconds
            failureThreshold: 3 # Mark unhealthy after 3 consecutive failures

我们已经确定了 Pod 启动阶段会发生什么;现在是时候分析关机阶段会发生什么了。

Pod 的关闭阶段

了解 Kubernetes 集群中的组件更像是微服务,而不是整体,这一点至关重要。微服务的工作方式与整体式进程的运行方式不同。在微服务中,所有组件同步需要更多时间。

当 API 服务器收到来自客户端或滚动部署期间的 Pod 删除通知时,它首先在 etcd 中修改 Pod 的状态,然后通知端点控制器和 Kubelet。收到来自 API 服务器的 Pod 删除通知后,端点控制器会从与该 Pod 关联的每个服务中删除该 Pod 端点。

控制平面上的端点控制器通过向 API 服务器发送 REST API 来实现此目的。然后,API 服务器通知其观察者,其中 KubeProxy就是其中之一;KubeProxy更新 iptables 规则以反映与该服务关联的端点集的更改。更新 iptables 规则将阻止新流量被定向到终止 Pod。

上述场景是发生停机的地方,因为更新 iptables 规则所需的时间比 Kubelet 终止容器所需的时间要多。这些阶段同时发生。当从客户端或滚动部署期间收到删除 Pod 的请求时,此请求将到达控制平面上的 API 服务器。一旦 Kubelet 和端点控制器收到删除通知,Kubelet 和端点控制器就会监视 API 服务器的更改。Kubelet 立即向容器发送 SIGTERM 信号,端点控制器向 API 服务器发送请求,要求从所有服务对象中删除 Pod 端点,这是 Kubeproxy在工作节点上执行的任务。

造成这种停机的原因是,在相应服务上更新 Pod 端点之前,容器会被 Kubelet 终止(这是一个更短的进程,因此需要更少的时间)(这涉及更多进程,因此需要更多时间)。由于任务完成时间的差异,服务仍会将流量路由到终止 Pod 的端点,从而导致“连接错误”或“连接被拒绝”等消息。

下图提供了 Kubernetes 架构内部发生的情况的图形视图。

我们已经能够确定在滚动部署期间连接断开的原因;那么我们如何解决这个问题呢?

解决方案

Kubernetes 从未被设计为“即插即用”的编排工具;它需要适当的配置以相应地适应每个用例。由于我们发现任务完成时间的差异是主要问题,因此简单的解决方案是定义代理更新 iptables 的等待时间。

我们可以通过在部署配置中添加 preStop 钩子来实现这一点。在容器完全关闭之前,我们会将容器配置为等待 20 秒。这是一个同步操作,这意味着容器只会在此等待时间完成时关闭。届时,Kubeproxy将更新 iptables,并且新连接将路由到正在运行的 pod 而不是终止 pod。

注意:preStop 钩子是 Pod 生命周期管理中使用的一种机制,用于在 Pod 终止之前执行特定命令或操作 重要的是要了解,当 iptables 更新时,与旧 Pod(正在终止的 Pod)的连接仍会保持,并且在所有进程完成并且 Pod 正常关闭之前,客户端连接不会中断,但新连接会定向到稳定的 Pod。 下面是配置了 preStop 挂钩的部署文件示例:

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-highly-available-app
spec:
  replicas: 3 # Define desired number of replicas
  selector:
    matchLabels:
      app: highly-available
  template:
    metadata:
      labels:
        app: highly-available
    spec:
      containers:
      - name: highly-available
        image: highly-available-image:latest
        ports:
        - containerPort: 80
        readinessProbe: # Readiness probe configuration
          httpGet:
            path: /health-check
            port: 80
            initialDelaySeconds: 5 # Wait 5 seconds before starting probes
            periodSeconds: 10 # Check every 10 seconds
            failureThreshold: 3 # Mark unhealthy after 3 consecutive failures
        lifecycle:
          preStop:
            exec:
              command: ["/bin/bash", "-c", "sleep 20"]

通过上述配置,滚动部署将不再导致我们的基础架构停机。 最后,我们应该始终确保给出的睡眠时间小于 terminationGracePeriodSeconds,默认为 30 秒。较高的值只会导致容器强制关闭。

结论

综上所述,无论每天发布的部署版本数量如何,我们都在确保滚动部署期间稳定的用户连接方面取得了重大进展。我们修改了部署文件,以包含准备探测和预停止挂钩。这些更改使我们能够更有效地管理容器启动和关闭期间的流量。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DevOps云学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Pod 的启动阶段
  • Pod 的关闭阶段
    • 解决方案
      • 结论
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档