在不停机的情况下升级 Kubernetes 集群

在不停机的情况下升级 Kubernetes 集群

Kubernetes 集群的升级过程

在某些时候,当使用 Kubernetes 集群时,需要更新正在运行的节点。 这可能包括软件包更新、内核更新或新虚拟机映像的部署。 在 Kubernetes 术语中,这称为 “自愿中断”.

这篇文章是 4 篇文章系列的一部分:

  1. 这个帖子。
  2. 正确关闭 Kubernetes 集群中的 Pod
  3. 删除 Pod 时延迟终止
  4. 如何使用 PodDisruptionBudgets 避免 Kubernetes 集群停机

(预计在不久的将来会翻译该系列中的其余文章)

在本文中,我们将介绍 Kubernetes 提供的所有工具,以实现集群中运行的节点零停机。

问题定义

我们首先会采取一种简单的方法,找出问题并评估这种方法的潜在风险,并积累知识来解决我们在整个周期中遇到的每个问题。 结果是使用生命周期挂钩、就绪探针和 Pod 中断预算的配置来实现我们的零停机目标。

为了开始我们的旅程,让我们举一个具体的例子。 假设我们有一个包含两个节点的 Kubernetes 集群,其中运行一个应用程序,后面有两个 pod Service:

在不停机的情况下升级 Kubernetes 集群

让我们从两个 pod 开始,其中 Nginx 和 Service 在两个 Kubernetes 集群节点上运行。

我们想要更新集群中两个工作节点的内核版本。 我们如何做到这一点? 一个简单的解决方案是使用更新的配置启动新节点,然后在启动新节点时关闭旧节点。 虽然这可行,但这种方法会存在一些问题:

  • 当您关闭旧节点时,其上运行的 Pod 也将被关闭。 如果需要清除 Pod 以正常关闭怎么办? 您正在使用的虚拟化系统可能不会等待清理过程完成。
  • 如果同时关闭所有节点怎么办? 当 Pod 移动到新节点时,您将获得相当长的停机时间。

我们需要一种方法来从旧节点优雅地迁移 Pod,同时确保在对节点进行更改时没有任何工作进程在运行。 或者,当我们对集群进行完全替换时,如示例中所示(即替换虚拟机映像),我们希望将正在运行的应用程序从旧节点转移到新节点。 在这两种情况下,我们都希望阻止新的 pod 在旧节点上调度,然后从其中驱逐所有正在运行的 pod。 为了实现这些目标我们可以使用命令 kubectl drain.

重新分配节点上的所有 Pod

Drain 操作允许您重新分配节点中的所有 Pod。 在drain执行期间,节点被标记为不可调度(标志 NoSchedule)。 这可以防止新的 Pod 出现在其上。 然后drain开始从节点驱逐pod,关闭当前在节点上运行的容器,发送信号 TERM pod 中的容器。

虽然 kubectl drain 会很好地驱逐 Pod,但还有两个因素可能导致排空操作失败:

  • 您的应用程序必须能够在提交后正常终止 TERM 信号。 当 pod 被驱逐时,Kubernetes 会发送一个信号 TERM 容器并等待它们停止指定的时间,之后,如果它们没有停止,则强制终止它们。 无论如何,如果您的容器无法正确感知信号,如果 Pod 当前正在运行(例如,数据库事务正在进行中),您仍然可能会错误地终止它们。
  • 您将丢失包含您的应用程序的所有 pod。 当新容器在新节点上启动时,它可能不可用,或者如果您的 Pod 部署在没有控制器的情况下,它们可能根本不会重新启动。

避免停机

为了最大限度地减少自愿中断(例如节点上的排空操作)造成的停机时间,Kubernetes 提供了以下故障处理选项:

在本系列的其余部分中,我们将使用这些 Kubernetes 功能来减轻 Pod 迁移的影响。 为了更容易理解主要思想,我们将使用上面的示例和以下资源配置:

---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 2
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.15
       ports:
       - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
 name: nginx-service
spec:
 selector:
   app: nginx
 ports:
 - protocol: TCP
   targetPort: 80
   port: 80

此配置是一个最小的示例 Deployment,它管理集群中的 nginx pod。 另外,配置描述了资源 Service,可用于访问集群中的 nginx pod。

在整个周期中,我们将迭代扩展此配置,使其最终包含 Kubernetes 提供的用于减少停机时间的所有功能。

如需在 AWS 及其他平台上实现零停机的 Kubernetes 集群更新的完全实施和测试版本,请访问 Gruntwork.io.

另请阅读我们博客上的其他文章:

来源: habr.com

添加评论