如何安排Pod重新启动

Leo*_*aro 8 kubernetes

是否可以根据时间自动重启Pod?

例如,我想每天早上8:00 AM重新启动集群的容器。

OhJ*_*eez 94

使用 cronjob,但不是运行 Pod,而是安排 Kubernetes API 命令,该命令将每天重新启动部署 ( kubectl rollout restart)。这样,如果出现问题,旧的 pod 将不会被关闭或移除。

Rollouts 创建新的 ReplicaSets,并等待它们启动,然后杀死旧的 pod,并重新路由流量。服务将继续不间断。

您必须设置 RBAC,以便从集群内部运行的 Kubernetes 客户端有权对 Kubernetes API 进行所需的调用。

---
# Service account the client will use to reset the deployment,
# by default the pods running inside the cluster can do no such things.
kind: ServiceAccount
apiVersion: v1
metadata:
  name: deployment-restart
  namespace: <YOUR NAMESPACE>
---
# allow getting status and patching only the one deployment you want
# to restart
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployment-restart
  namespace: <YOUR NAMESPACE>
rules:
  - apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    resourceNames: ["<YOUR DEPLOYMENT NAME>"]
    verbs: ["get", "patch", "list", "watch"] # "list" and "watch" are only needed
                                             # if you want to use `rollout status`
---
# bind the role to the service account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deployment-restart
  namespace: <YOUR NAMESPACE>
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: deployment-restart
subjects:
  - kind: ServiceAccount
    name: deployment-restart
    namespace: <YOUR NAMESPACE>
Run Code Online (Sandbox Code Playgroud)

和 cronjob 规范本身:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: deployment-restart
  namespace: <YOUR NAMESPACE>
spec:
  concurrencyPolicy: Forbid
  schedule: '0 8 * * *' # cron spec of time, here, 8 o'clock
  jobTemplate:
    spec:
      backoffLimit: 2 # this has very low chance of failing, as all this does
                      # is prompt kubernetes to schedule new replica set for
                      # the deployment
      activeDeadlineSeconds: 600 # timeout, makes most sense with 
                                 # "waiting for rollout" variant specified below
      template:
        spec:
          serviceAccountName: deployment-restart # name of the service
                                                 # account configured above
          restartPolicy: Never
          containers:
            - name: kubectl
              image: bitnami/kubectl # probably any kubectl image will do,
                                     # optionaly specify version, but this
                                     # should not be necessary, as long the
                                     # version of kubectl is new enough to
                                     # have `rollout restart`
              command:
                - 'kubectl'
                - 'rollout'
                - 'restart'
                - 'deployment/<YOUR DEPLOYMENT NAME>'
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望 cronjob 等待部署推出,请将 cronjob 命令更改为:

command:
 - bash
 - -c
 - >-
   kubectl rollout restart deployment/<YOUR DEPLOYMENT NAME> &&
   kubectl rollout status deployment/<YOUR DEPLOYMENT NAME>
Run Code Online (Sandbox Code Playgroud)

  • 相反:不要托管能够自我修改 k8s 集群的资源,将这些任务隔离在集群外部的单独 cronjob 工具中。理想情况下,该工具应该是管理集群的服务提供商提供的工具 - 例如 GKE 的 https://cloud.google.com/scheduler,或者对于 AWS,第二个 ECS 集群用于在其他ECS集群 (8认同)
  • 来自 https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs。**注意**:所有 CronJob 计划:时间均基于 kube-controller-manager 的时区。如果您的控制平面在 Pod 或裸容器中运行 kube-controller-manager,则为 kube-controller-manager 容器设置的时区将决定 cron 作业控制器使用的时区。 (4认同)
  • 虽然这在技术上并不能回答所提出的问题,但这是(IMO)迄今为止定期重新启动集群 Pod 的最佳选择! (3认同)
  • 更新:在 CronJob 中将 `batch/v1beta1` 更改为 `batch/v1` 以使其正常工作 (3认同)
  • 这个答案挽救了我们的生命,并帮助我们在调查和解决根本原因的同时克服了巨大的事件和金钱损失。谢谢你! (2认同)
  • 但请注意,对“ServiceAccount”的更改需要提升权限(集群管理员),而普通开发人员可以使用“livenessProbe”方法...... (2认同)

Dmi*_*try 14

我借用了 @Ryan Lowe的想法,但做了一些修改。它将重新启动超过 24 小时的 Pod

      livenessProbe:
        exec:
          command:
             - bin/sh
            - -c
            - "end=$(date -u +%s);start=$(stat -c %Z /proc/1 | awk '{print int($1)}'); test $(($end-$start)) -lt 86400"
Run Code Online (Sandbox Code Playgroud)

  • `/proc/1` 不是可靠的信息来源。时间戳可能与实际情况有很大不同。当可用且进程 ID 已知时(在我的例子中为“1”),我会使用“ps -p 1 -o etimes --no-headers”。 (3认同)

Rya*_*owe 7

Another quick and dirty option for a pod that has a restart policy of Always (which cron jobs are not supposed to handle - see creating a cron job spec pod template) is a livenessProbe that simply tests the time and restarts the pod on a specified schedule

ex. After startup, wait an hour, then check hour every minute, if hour is 3(AM) fail probe and restart, otherwise pass

livenessProbe:
  exec:
    command:
    - exit $(test $(date +%H) -eq 3 && echo 1 || echo 0)
  failureThreshold: 1
  initialDelaySeconds: 3600
  periodSeconds: 60
Run Code Online (Sandbox Code Playgroud)

Time granularity is up to how you return the date and test ;)

Of course this does not work if you are already utilizing the liveness probe as an actual liveness probe ¯\_(?)_/¯

  • 上面的liveness命令不能这样写在一行。您可以在三个单独的行上使用 `- bash`、`- -c` 和 `- exit $(test $(date +%H) -eq 3 &amp;&amp; echo 1 || echo 0)`。 (3认同)
  • 当然,这种方法会使它在指定的时间段(例如一整分钟)内持续重新启动。将精度精确到秒会潜在地导致一起错过支票。如果更新时间超过24小时,也许检查正常运行时间会更简单,更合适? (2认同)
  • 这种方法通过在启动后等待一个小时再次开始探测 (initialDelaySeconds) 来避免重启风暴,因此在 3:00 和 3:01 之间的任何地方它都会失败,然后一旦它重新启动,它就会等待一个小时再次开始检查时间(使用启动一个相当大的 vert.x 应用程序的时间 ~ 25 秒,第一次探测在 4:01 和 4:02 之间开始) (2认同)
  • @MassoodKhaari 你是对的,因为测试是在 pod 的 Docker 容器中运行的,所以 date/test/exit 命令完全依赖于容器的 shell (2认同)
  • 这种方法有一些停机时间。liveness探针失败后、容器重启前,pod无法接受流量。如果所有容器恰好同时重启,就会出现服务中断的情况。 (2认同)
  • @OhJeez 这绝对是真的,livenessProbe 将导致停机,因为该部署中的所有 Pod 将同时重新启动,您在下面描述的 cronjob 应该是生产中可接受的答案:) (2认同)

Nic*_*Ben 5

有一个特定的资源:CronJob

这里有一个例子:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: your-cron
spec:
  schedule: "*/20 8-19 * * 1-5"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: your-periodic-batch-job
        spec:
          containers:
          - name: my-image
            image: your-image
            imagePullPolicy: IfNotPresent
          restartPolicy: OnFailure
Run Code Online (Sandbox Code Playgroud)

如果要在启动新 Pod 时替换旧 Pod,请更改spec.concurrencyPolicyReplace。使用Forbid,如果旧 Pod 仍在运行,则新 Pod 的创建将被跳过。

  • 我不清楚这是如何工作的。它是否部署了一个新的 pod,因此 Kubernetes 会自动删除一个旧的 pod? (6认同)