如何删除 Kubernetes“关闭”pod

问题描述 投票:0回答:9

我最近注意到状态为“关闭”的 Pod 大量堆积。我们自 2020 年 10 月以来一直在使用 Kubernetes。

生产和登台运行在相同的节点上,只是登台使用可抢占节点来降低成本。容器在暂存过程中也很稳定。 (故障很少发生,因为之前在测试中发现过)。

服务提供商 Google Cloud Kubernetes。

我熟悉了文档并尝试搜索,但我都不认识谷歌对这种特殊状态的帮助。日志中没有错误。

我没有遇到 pod 被停止的问题。理想情况下,我希望 K8s 自动删除这些关闭 Pod。如果我跑

kubectl delete po redis-7b86cdccf9-zl6k9
,它就会眨眼间消失。

kubectl get pods | grep Shutdown | awk '{print $1}' | xargs kubectl delete pod
是手动临时解决方法。

PS。在我的环境中,

k
kubectl
的别名。

最后一个例子:它发生在所有命名空间 // 不同的容器中。

我偶然发现了一些解释状态的相关问题 https://github.com/kubernetes/website/pull/28235 https://github.com/kubernetes/kubernetes/issues/102820

“当 Pod 在节点正常关闭期间被逐出时,它们会被标记为失败。运行

kubectl get pods
将显示被逐出 Pod 的状态为
Shutdown
。”

kubernetes google-kubernetes-engine
9个回答
8
投票

被驱逐的 Pod 不是故意删除的,正如 k8s 团队在这里所说的1,被驱逐的 Pod 也不是为了在驱逐后进行检查而被删除。

我相信最好的方法是创建一个 cronjob 2,正如已经提到的。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: del-shutdown-pods
spec:
  schedule: "* 12 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - kubectl get pods | grep Shutdown | awk '{print $1}' | xargs kubectl delete pod
          restartPolicy: OnFailure

8
投票

您不需要任何 grep - 只需使用 kubectl 提供的选择器即可。而且,顺便说一句,您无法从 busybox 映像调用 kubectl,因为它根本没有 kubectl。我还创建了一个具有 pod 删除权限的服务帐户。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: del-shutdown-pods
spec:
  schedule: "0 */2 * * *"  
  concurrencyPolicy: Replace
  jobTemplate:
    metadata:
      name: shutdown-deleter
    spec:
      template:
        spec:
          serviceAccountName: deleter
          containers:
          - name: shutdown-deleter
            image: bitnami/kubectl
            imagePullPolicy: IfNotPresent
            command:
              - "/bin/sh"
            args:
              - "-c"
              - "kubectl delete pods --field-selector status.phase=Failed -A --ignore-not-found=true"
          restartPolicy: Never

0
投票

首先,尝试使用以下命令强制删除 kubernetes pod:

$ kubectl 删除 pod -n --grace-period 0 --force

您可以使用以下命令直接删除 Pod:

$ kubectl 删除 pod

然后,使用以下命令检查 pod 的状态:

$ kubectl 获取 pods

在这里,您将看到 Pod 已被删除。

您还可以使用 yaml 文件中的文档进行验证。

大多数程序在收到 SIGTERM 时都会正常关闭,但如果您使用第三方代码或正在管理您无法控制的系统,则 preStop 挂钩是在不修改应用程序的情况下触发正常关闭的好方法。 Kubernetes 将向 pod 中的容器发送 SIGTERM 信号。 此时,Kubernetes 会等待指定的时间,称为终止宽限期。

欲了解更多信息请参阅


0
投票

目前 Kubernetes 默认情况下不会删除已驱逐和关闭状态的 pod。我们在我们的环境中也遇到了类似的问题。

作为自动修复,您可以创建一个 Kubernetes cronjob,它可以删除处于已驱逐和关闭状态的 pod。 Kubernetes cronjob pod 可以使用 serviceaccount 和 RBAC 进行身份验证,您可以在其中限制实用程序的动词和命名空间。


0
投票

您可以使用https://github.com/hjacobs/kube-janitor。这提供了各种可配置的清理选项


0
投票

我对这个问题的看法看起来像这样(来自其他解决方案的灵感):

# Delete all shutdown pods. This is common problem on kubernetes using preemptible nodes on gke
# why awk, not failed pods: https://github.com/kubernetes/kubernetes/issues/54525#issuecomment-340035375
# due fact failed will delete evicted pods, that will complicate pod troubleshooting

---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: del-shutdown-pods
  namespace: kube-system
  labels:
    app: shutdown-pod-cleaner
spec:
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: shutdown-pod-cleaner
        spec:
          volumes:
          - name: scripts
            configMap:
              name: shutdown-pods-scripts
              defaultMode: 0777
          serviceAccountName: shutdown-pod-sa
          containers:
          - name: zombie-killer
            image: bitnami/kubectl
            imagePullPolicy: IfNotPresent
            command:
              - "/bin/sh"
            args:
              - "-c"
              - "/scripts/podCleaner.sh"
            volumeMounts:
              - name: scripts
                mountPath: "/scripts"
                readOnly: true
          restartPolicy: OnFailure
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: shutdown-pod-cleaner
  namespace: kube-system
  labels:
    app: shutdown-pod-cleaner
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["delete", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: shutdown-pod-cleaner-cluster
  namespace: kube-system
subjects:
- kind: ServiceAccount
  name: shutdown-pod-sa
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: shutdown-pod-cleaner
  apiGroup: ""
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: shutdown-pod-sa
  namespace: kube-system
  labels:
    app: shutdown-pod-cleaner
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: shutdown-pods-scripts
  namespace: kube-system
  labels:
    app: shutdown-pod-cleaner
data:
  podCleaner.sh: |
    #!/bin/sh
    if [ $(kubectl get pods --all-namespaces --ignore-not-found=true | grep Shutdown | wc -l) -ge 1 ]
    then
    kubectl get pods -A | grep Shutdown | awk '{print $1,$2}' | xargs -n2 sh -c 'kubectl delete pod -n $0 $1 --ignore-not-found=true'
    else
    echo "no shutdown pods to clean"
    fi

0
投票

我刚刚设置了一个 cronjob 来清理失效的 GKE Pod。 完整的设置包括 RBAC 角色、角色绑定和服务帐户。

服务帐户和集群角色设置。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-accessor-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "delete", "watch", "list"]
---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pod-access
subjects:
- kind: ServiceAccount
  name: cronjob-svc
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: pod-accessor-role
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cronjob-svc
  namespace: kube-system

用 Cronjob 来清理死掉的 pod。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: pod-cleaner-cron
  namespace: kube-system
spec:
  schedule: "0 */12 * * *"
  successfulJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        metadata:
          name: pod-cleaner-cron
          namespace: kube-system
        spec:
          serviceAccountName: cronjob-svc
          restartPolicy: Never
          containers:
          - name: pod-cleaner-cron
            imagePullPolicy: IfNotPresent
            image: bitnami/kubectl
            command:
              - "/bin/sh"
            args:
              - "-c"
              - "kubectl delete pods --field-selector status.phase=Failed -A --ignore-not-found=true"
status: {}

0
投票

受到此处讨论的启发,我在 GitHub 上创建了以下 kube-clean 存储库,并在artifacthub.io 上创建了相应的 kube-clean helm 图表,它为每个指定的命名空间生成了

CronJob


0
投票

我就是这样做的。希望它能帮助某人。在一行中运行下面的代码,不带注释。取出不需要的东西或添加以帮助别人。

##Get the pods in the mmi-medic namespace in json format
kubectl get pods -n YOUR_NAMESPACE -o json 
## get a certain JSON element in each of the pods
| jq '.items[].status.containerStatuses 
##If the pod is standing in false ready status, sign of completed pod
| select(.[].ready == false) 
##Only if the pod is in completed status
| select(.[].state.terminated.reason == "Completed") 
##Only if pod was created by Kaniko Image builder, lets me know I am deleteing correct pods.
| select(.[].name | test("kaniko")?) 
##Set a date that is 24 hours ago. 86400 is how many seconds in 24 hours
| (now - 86400) as $date 
##Get the date element we will compare against.
| select((.[].state.terminated.finishedAt 
##Get the first chars from value.
| .[:18] + "Z" 
##If the finishedAt Date is longer than 24 hours then delete.
| fromdate) < $date) 
##Get the name of the POD to send to xargs but raw sends it without the double quotes that jq leaves behind not part of value.
| .[].name ' --raw-output 
##Finally if empty dont run xargs otherwise delete the pod by name.
| xargs --no-run-if-empty kubectl -n YOUR_NAMESPACE delete pod

我也在我的 K8s cronjob 模板中使用它作为我的图像

image: bitnami/kubectl
© www.soinside.com 2019 - 2024. All rights reserved.