场景:NestJs 的存储库正在执行 cron 作业,根据 cron 表达式向订阅者发送消息。当只有一个实例运行时,场景运行良好。
问题:当 K8 集群中运行多个实例(pod)时,订阅者收到多封电子邮件。
寻找解决方案:在没有数据库或分离服务的情况下,我们可以使用“K8s”做一些事情yaml,以便在给定的时间点只有一个 pod 正在执行 cron 作业。
您可以在 kubernetes 集群上尝试
cronjob中的
concurrencyPolicy
选项。此选项有助于一次仅运行一项任务。即使一个作业请求多个触发器,它也会跳过触发器,直到当前任务执行完成。
在您的情况下,您需要将该选项设置为
Forbid
,如下所示,以便确保一次仅执行请求。
apiVersion: batch/v1
kind: CronJob
metadata:
name: demo
spec:
schedule: "* * * * *"
concurrencyPolicy: Forbid #Enabling the concurrencyPolicy
jobTemplate:
spec:
template:
spec:
containers:
- name: demo
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
注意: 使用
concurrencyPolicy
字段限制 Pod 数量可能会影响作业的性能,因为这可能会导致执行时间更长。
您还可以使用作业中的
parallelism
字段来限制 pod 的创建数量。有关更多信息,请参阅此并行性。
有关更多详细信息,请参阅此官方 k8 文档