Solución:
Use un cronjob, pero no para ejecutar sus pods, sino para programar un comando de la API de Kubernetes que reiniciará la implementación todos los días (kubectl rollout restart
). De esa manera, si algo sale mal, las cápsulas viejas no se quitarán ni se quitarán.
Los despliegues crean nuevos ReplicaSets y esperan a que estén activos antes de eliminar los pods antiguos y redirigir el tráfico. El servicio continuará ininterrumpidamente.
Debe configurar RBAC, de modo que el cliente de Kubernetes que se ejecuta desde el interior del clúster tenga los permisos necesarios para realizar las llamadas necesarias a la API de Kubernetes.
---
# 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>
Y la propia especificación 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>'
Opcionalmente, si desea que el cronjob espere a que se implemente la implementación, cambie el comando cronjob a:
command:
- bash
- -c
- >-
kubectl rollout restart deployment/<YOUR DEPLOYMENT NAME> &&
kubectl rollout status deployment/<YOUR DEPLOYMENT NAME>
Otra opción rápida y sucia para un pod que tiene una política de reinicio de Siempre (que se supone que los trabajos cron no deben manejar; consulte cómo crear una plantilla de pod de especificaciones de trabajo cron) es un livenessProbe que simplemente prueba la hora y reinicia el pod en un horario específico
ex. Después del inicio, espere una hora, luego verifique la hora cada minuto, si la hora es 3 (AM) falla la sonda y reinicia, de lo contrario pasa
livenessProbe:
exec:
command:
- exit $(test $(date +%H) -eq 3 && echo 1 || echo 0)
failureThreshold: 1
initialDelaySeconds: 3600
periodSeconds: 60
La granularidad del tiempo depende de cómo devuelva la fecha y la prueba 😉
Por supuesto, esto no funciona si ya está utilizando la sonda de vida como un real sonda de vivacidad ¯ _ (ツ) _ / ¯
Hay un recurso específico para eso: CronJob
Aquí un ejemplo:
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
cambio spec.concurrencyPolicy
para Replace
si desea reemplazar el módulo anterior al iniciar un módulo nuevo. Utilizando Forbid
, la nueva creación de pod se omitirá si el antiguo pod todavía se está ejecutando.