k8s cron作业运行多次

Alb*_*rto 1 bash shell amazon-web-services kubernetes

我有以下 cronjob,它删除特定命名空间中的 pod。

我按原样运行作业,但似乎作业不会每 20 分钟运行一次,而是每隔几(2-3)分钟运行一次,我需要的是,作业每 20 分钟就会开始删除 pod指定的命名空间然后终止,知道这里可能出了什么问题吗?

apiVersion: batch/v1
kind: CronJob
metadata:
  name: restart
spec:
  schedule: "*/20 * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 0
  failedJobsHistoryLimit: 0
  jobTemplate:
    spec:
      backoffLimit: 0
      template:
        spec:
          serviceAccountName: sa
          restartPolicy: Never
          containers:
            - name: kubectl
              image: bitnami/kubectl:1.22.3
              command:
                - /bin/sh
                - -c
                - kubectl get pods -o name | while read -r POD; do kubectl delete "$POD"; sleep 30; done
Run Code Online (Sandbox Code Playgroud)

我真的不知道为什么会发生这种情况......

也许删除 pod 会崩溃

更新

我尝试了以下操作,但没有删除任何 Pod,知道吗?

apiVersion: batch/v1
kind: CronJob
metadata:
  name: restart
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 0
  failedJobsHistoryLimit: 0
  jobTemplate:
    spec:
      backoffLimit: 0
      template:
        metadata:
          labels:
            name: restart
        spec:
          serviceAccountName: pod-exterminator
          restartPolicy: Never
          containers:
            - name: kubectl
              image: bitnami/kubectl:1.22.3
              command:
                - /bin/sh
                - -c
                - kubectl get pods -o name --selector name!=restart | while read -r POD; do kubectl delete "$POD"; sleep 10; done.
Run Code Online (Sandbox Code Playgroud)

The*_*ool 5

该 cronjob pod 将在执行过程中的某个时刻删除自身。导致作业失败并另外重置其回退计数。

文档说

当作业的 Pod 被删除或成功且该作业的任何其他 Pod 在此期间失败时,回退计数将被重置。

您需要应用适当的过滤器。另请注意,您可以使用单个命令删除所有 Pod。

spec.jobTemplate.spec.template.metadata添加可用于过滤的标签。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: restart
spec:
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            name: restart # label the pod
Run Code Online (Sandbox Code Playgroud)

然后使用此标签删除所有不是 cronjob pod 的 pod。

kubectl delete pod --selector name!=restart
Run Code Online (Sandbox Code Playgroud)

由于您在评论中声明,您需要一个循环,完整的工作示例可能如下所示。

---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: restart
  namespace: sandbox
spec:
  schedule: "*/20 * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 0
  failedJobsHistoryLimit: 0
  jobTemplate:
    spec:
      backoffLimit: 0
      template:
        metadata:
          labels:
            name: restart
        spec:
          serviceAccountName: restart
          restartPolicy: Never
          containers:
            - name: kubectl
              image: bitnami/kubectl:1.22.3
              command:
                - /bin/sh
                - -c
                - |
                  kubectl get pods -o name --selector "name!=restart" |
                    while read -r POD; do
                      kubectl delete "$POD"
                      sleep 30
                    done
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: restart
  namespace: sandbox
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-management
  namespace: sandbox
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: restart-pod-management
  namespace: sandbox
subjects:
  - kind: ServiceAccount
    name: restart
    namespace: sandbox
roleRef:
  kind: Role
  name: pod-management
  apiGroup: rbac.authorization.k8s.io
Run Code Online (Sandbox Code Playgroud)
kubectl create namespace sandbox
kubectl config set-context --current --namespace sandbox
kubectl run pod1 --image busybox -- sleep infinity
kubectl run pod2 --image busybox -- sleep infinity
kubectl apply -f restart.yaml # the above file
Run Code Online (Sandbox Code Playgroud)

在这里您可以看到第一个 Pod 如何被终止。

$ kubectl get all
NAME                         READY   STATUS        RESTARTS   AGE
pod/pod1                     1/1     Terminating   0          43s
pod/pod2                     1/1     Running       0          39s
pod/restart-27432801-rrtvm   1/1     Running       0          16s

NAME                    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/restart   */1 * * * *   False     1        17s             36s

NAME                         COMPLETIONS   DURATION   AGE
job.batch/restart-27432801   0/1           17s        17s
Run Code Online (Sandbox Code Playgroud)

请注意,这实际上有点错误。因为从您读取 Pod 列表到删除列表中的单个 Pod,该 Pod 可能不再存在。您可以使用下面的方法来忽略这些情况,因为当它们消失后,您不需要删除它们。

kubectl delete "$POD" || true
Run Code Online (Sandbox Code Playgroud)

也就是说,由于您将作业命名为 restart,我认为这样做的目的是重新启动某些部署的 Pod。实际上,您可以利用 Kubernetes更新策略进行正确的重启。

kubectl rollout restart $(kubectl get deploy -o name)
Run Code Online (Sandbox Code Playgroud)

使用默认的更新策略,这将导致首先创建新的 Pod,并确保它们在终止旧的 Pod 之前准备就绪。

$ kubectl rollout restart $(kubectl get deploy -o name)
NAME                        READY   STATUS              RESTARTS   AGE
pod/app1-56f87fc665-mf9th   0/1     ContainerCreating   0          2s
pod/app1-5cbc776547-fh96w   1/1     Running             0          2m9s
pod/app2-7b9779f767-48kpd   0/1     ContainerCreating   0          2s
pod/app2-8d6454757-xj4zc    1/1     Running             0          2m9s
Run Code Online (Sandbox Code Playgroud)

这也适用于 deamonsets。

$ kubectl get all
NAME                         READY   STATUS        RESTARTS   AGE
pod/pod1                     1/1     Terminating   0          43s
pod/pod2                     1/1     Running       0          39s
pod/restart-27432801-rrtvm   1/1     Running       0          16s

NAME                    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/restart   */1 * * * *   False     1        17s             36s

NAME                         COMPLETIONS   DURATION   AGE
job.batch/restart-27432801   0/1           17s        17s
Run Code Online (Sandbox Code Playgroud)