【问题标题】:Why does Kubernetes not terminating PODs after a node crash?为什么 Kubernetes 在节点崩溃后不终止 POD?
【发布时间】:2020-07-25 21:53:43
【问题描述】:

我正在运行一个自我管理的 Kubernetes 集群 1.18.1。我已经部署了一些具有持久性卷的 pod(基于 longhorn 项目)。 现在经过一些测试后,我观察到以下行为:

如果我模拟一个节点的硬关闭,在一段时间(5 分钟)后,Kubernetes 会识别出丢失并开始将 POD 从死节点重新调度到另一个节点。

由于我的节点具有持久性卷,新的 POD 将永远不会启动。原因是旧的 pod(在死节点上)现在在终止状态下是持久的。

驻留在崩溃节点上的 Pod 没有终止这一事实似乎是众所周知的 Kubernetes 限制。另见问题描述here

我的问题是:为什么 Kubernetes 不提供自动终止旧 POD 和持久卷等资源的功能。为什么我必须以管理员身份手动干预?对我来说,这种行为似乎与 Kubernetes 做出的承诺不合逻辑。

这是例如我的 yaml 文件的样子:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: db
  labels: 
    app: db
spec:
  replicas: 1
  selector: 
    matchLabels:
      app: db
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
      - env:
        - name: POSTGRES_DB
          value: office
        image: postgres:9.6.1
        name: db

        livenessProbe:
          tcpSocket:
            port: 5432
          initialDelaySeconds: 30
          periodSeconds: 10

        ports:
          - containerPort: 5432        
        resources: {}
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: dbdata
          subPath: postgres
      restartPolicy: Always
      volumes:
      - name: dbdata
        persistentVolumeClaim:
          claimName: office-demo-dbdata-pvc


# Storrage
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: office-demo-dbdata-pv
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  claimRef:
    namespace: default
    name: office-demo-dbdata-pvc
  csi:
    driver: io.rancher.longhorn 
    fsType: ext4
    volumeHandle: office-demo-dbdata
  storageClassName: longhorn-durable
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: office-demo-dbdata-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-durable
  resources:
    requests:
      storage: 2Gi
  volumeName: "office-demo-dbdata-pv"

如上所述,该卷是在 Longhorn 上创建的。但是即使kubernetes开始将pod重新调度到另一个节点后,附件也没有释放。

如果我手动删除'volumeattachment',可以释放挂在终止状态的pod

$ kubectl delete volumeattachment csi-08d9842e.......

但无论如何,这是手动操作。

【问题讨论】:

  • 持久卷通常不绑定到特定节点。 (在 AWS 上下文中,持久卷通常是 EBS 卷,它可以重新附加到不同的节点。)如果在删除节点时自动删除 pod 和卷,我必须作为操作员手动干预重新启动它们,目标是避免这种情况。
  • @Ralph,请使用您使用的 yamls(部署、pv、pvc 等)编辑您的问题!通过这种方式,我们可以重现您的环境并确定它是设计问题还是可以修复的问题。我试图弄清楚:你部署了什么样的 PV? PV在哪里?
  • @DavidMaze 我认为你应该写下你的评论作为答案并进一步解释你的观点。
  • 一天后再次阅读这个问题,我认为我的评论本身并不是一个答案。实际的问题似乎是关于阻止访问 ReadWriteOnce 卷的陈旧(终止)pod;如果 pod 被删除,那么这些卷可以重新挂载到其他地方。
  • 我将我的 yaml 文件添加到问题中。

标签: kubernetes


【解决方案1】:

5 分钟是 Kubernetes 控制平面组件设置的默认驱逐时间。如果你想自定义可以使用 taint based evictions 并在部署 yaml 中添加以下内容

tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 60

请注意,Kubernetes 会自动为node.kubernetes.io/not-readytolerationSeconds=300 添加容差,除非用户提供的 pod 配置已经具有node.kubernetes.io/not-ready 的容差。同样,它为node.kubernetes.io/unreachable 添加了对tolerationSeconds=300 的容忍度,除非用户提供的pod 配置已经对node.kubernetes.io/unreachable 有容忍度

【讨论】:

  • 这里的 5 分钟不是问题。问题是为什么具有关联持久性卷的 pod 不会被终止。因此,重新安排的 pod 将无法启动,因为 PV 尚未解除绑定。而且这种状态是永久性的,只能通过手动管理操作来解决。
  • @Ralph 因为如果节点的 kubelet 不可用,这并不意味着整台机器都已关闭,但仍可能挂载了一个卷。然后在其他地方再次安装它会损坏数据。
  • 是的,我现在更好地理解了这个问题。还有this actual discussion on github。但似乎 kubernetes 不会提供解决方案 :-(
【解决方案2】:

根据Longhorn Documentation on Node Failure

当 Kubernetes 节点安装 CSI 驱动程序失败时(以下所有内容均基于 Kubernetes v1.12 的默认设置):

  1. 一分钟后,kubectl get nodes 将报告故障节点的NotReady
  2. 大约五分钟后,NotReady 节点上所有 pod 的状态将更改为 UnknownNodeLost
  3. 如果您使用 StatefulSet 或 Deployment 进行部署,您需要确定强制删除在丢失节点上运行的工作负载的 pod 是否安全。见here
    1. StatefulSet 具有稳定的身份,因此 Kubernetes 不会为用户强制删除 Pod。
    2. Deployment 没有稳定的身份,但 Longhorn 是一种 Read-Write-Once 类型的存储,这意味着它只能附加到一个 Pod。因此,由 Kubernetes 创建的新 Pod 将无法启动,因为 Longhorn 卷仍连接到丢失节点上的旧 Pod。
    3. 在这两种情况下,Kubernetes 都会自动驱逐丢失节点上的 pod(为 pod 设置删除时间戳),然后尝试用旧卷重新创建一个新的。因为被驱逐的 pod 卡在Terminating 状态并且附加的 Longhorn 卷无法释放/重用,新的 pod 将卡在ContainerCreating 状态。这就是为什么用户需要决定强制删除 pod 是否安全。

这是 LongHorn 的当前状态(仍处于测试阶段)。

Github 上有一个未解决的问题:Improve node failure handling #1105 可以准确解决这个问题,但目前如文档中所述,管理员必须手动干预。

Kubernetes Github 中还有更多的问题,例如 this 一个,我认为这是一个问题,位于 kubernetes 和 CSI 之间的边缘,这是一个相互验证:CSI 是 read-write-once 并设置存储作为稳定并锁定存储。在 kubernetes 部分,它看到 pod 具有终结器(如上面的问题),并且在任务完成之前不会删除它们。

不幸的是,到目前为止,无论哪种方式都需要人工干预。

  • 从 longhorn 的角度来看,您应该运行 delete volumeattachment
  • 从 kubernetes 端,您可以删除 pod finalizers 允许它删除 pod,here 是如何更改终结器的示例。

编辑:

Github Kubernetes Issue #69697 移除终结器的示例:

kubectl patch pvc <PVC_NAME> -p '{"metadata":{"finalizers":null}}'
kubectl patch pod <POD_NAME> -p '{"metadata":{"finalizers":null}}'

您可以创建一个脚本来删除您的终结器,这样您就不必像另一个 Kubernetes Open Issue #77258 中建议的那样手动制作它:

这是从系统中的所有 pv 中删除终结器的单行代码:

kubectl get pv | tail -n+2 | awk '{print $1}' | xargs -I{} kubectl patch pv {} -p '{"metadata":{"finalizers": null}}'

这里最大的问题是终结器是由 LongHorn 添加的,所以据我了解,如果没有它,您将无法创建 pod,因为它是由 LongHorn 之后添加的。

我添加了来自 Github 的文档和未解决的问题,以向您表明这是一个当前问题,尚待 Longhorn 和 Kubernetes 的开发人员解决。

【讨论】:

  • 我已经知道删除volumeattachment可以解决问题。但是我可以告诉 Kubernetes 在后台自动执行此操作吗?我可以在部署或 persistencevolumeclaim 中定义不同的 pod 终结器吗?
  • @Ralph 你看到 finalizes 的例子了吗?该链接解释了它发生的原因。花一些时间阅读它们,它将帮助您更好地理解终结器机制。
猜你喜欢
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2021-05-05
  • 2019-04-15
  • 2017-07-09
  • 2018-04-29
  • 2018-07-31
  • 1970-01-01
相关资源
最近更新 更多