定时工作流¶
v2.5及更高版本
CronWorkflows 是按计划运行的workflow。
它们的设计目的是封装一个workflowSpec并模拟Kubernetes CronJobs的选项。
本质上,CronWorkflow = Workflow + 一些特定的定时选项。
CronWorkflow 规范¶
以下是一个CronWorkflow的示例:
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: test-cron-wf
spec:
schedule: "* * * * *"
concurrencyPolicy: "Replace"
startingDeadlineSeconds: 0
workflowSpec:
entrypoint: date
templates:
- name: date
container:
image: alpine:3.6
command: [sh, -c]
args: ["date; sleep 90"]
workflowSpec 和 workflowMetadata¶
CronWorkflow.spec.workflowSpec 与 Workflow.spec 类型相同。
它是从中创建的 Workflow 对象的模板。
Workflow名称是基于CronWorkflow名称生成的。
在上面的示例中,它类似于test-cron-wf-tj6fe。
您可以使用CronWorkflow.spec.workflowMetadata来添加labels和annotations。
CronWorkflow 选项¶
| 选项名称 | 默认值 | 描述 |
|---|---|---|
schedule |
None | Cron schedule to run Workflows. Example: 5 4 * * *. Deprecated, use schedules. |
schedules |
None | v3.6 and after: List of Cron schedules to run Workflows. Example: 5 4 * * *, 0 1 * * *. Either schedule or schedules must be provided. |
timezone |
Machine timezone | IANA Timezone to run Workflows. Example: America/Los_Angeles |
suspend |
false |
If true Workflow scheduling will not occur. Can be set from the CLI, GitOps, or directly |
concurrencyPolicy |
Allow |
What to do if multiple Workflows are scheduled at the same time. Allow: allow all, Replace: remove all old before scheduling new, Forbid: do not allow any new while there are old |
startingDeadlineSeconds |
0 |
Seconds after the last scheduled time during which a missed Workflow will still be run. |
successfulJobsHistoryLimit |
3 |
Number of successful Workflows to persist |
failedJobsHistoryLimit |
1 |
Number of failed Workflows to persist |
stopStrategy.expression |
nil |
v3.6 and after: defines if the CronWorkflow should stop scheduling based on an expression, which if present must evaluate to false for the workflow to be created |
when |
None | v3.6 and after: An optional expression which will be evaluated on each cron schedule hit and the workflow will only run if it evaluates to true |
Cron 定时语法¶
cron调度器采用标准cron语法。其实现方式与CronJobs相同,使用robfig/cron库。
崩溃恢复¶
如果控制器崩溃,您可以确保任何错过的调度仍会运行。
通过设置startingDeadlineSeconds,您可以指定一个最大宽限期,即使超过最后一次计划执行时间,工作流仍会运行。
例如,如果一个每分钟运行的CronWorkflow最后一次执行是在12:05:00,而控制器在12:05:55到12:06:05之间崩溃,那么预期的12:06:00执行时间将被错过。
但如果将startingDeadlineSeconds设置为大于5的值(即从计划执行时间12:06:00到当前时间12:06:05之间的时间差),那么CronWorkflow的一个实例将在12:06:05准时执行。
目前由于设置了startingDeadlineSeconds,只会执行单个实例。
此设置还可以与concurrencyPolicy配合配置,以实现更精细的控制。
夏令时¶
使用timezone时,会考虑夏令时(DST)因素。
根据预定工作流的本地时间,当时钟向前或向后调整时,工作流可能运行一次、两次或完全不运行。
例如,使用 timezone: America/Los_Angeles:
-
2020-03-08 02:00:00 增加1小时(夏令时开始):
注意:由于时钟向前调整,3月8日02:00至02:59之间的计划被跳过:
cron 序列 工作流执行时间 59 1 ** * 1 2020-03-08 01:59:00 -0800 PST 2 2020-03-09 01:59:00 -0700 PDT 3 2020-03-10 01:59:00 -0700 PDT 0 2 ** * 1 2020-03-09 02:00:00 -0700 PDT 2 2020-03-10 02:00:00 -0700 PDT 3 2020-03-11 02:00:00 -0700 PDT 1 2 ** * 1 2020-03-09 02:01:00 -0700 PDT 2 2020-03-10 02:01:00 -0700 PDT 3 2020-03-11 02:01:00 -0700 PDT -
2020年11月1日02:00:00夏令时结束前1小时:
注意:由于时钟回拨,11月1日凌晨01:00至01:59之间的计划任务被触发了两次:
cron表达式 序列号 工作流执行时间 59 1 ** * 1 2020-11-01 01:59:00 -0700 PDT 2 2020-11-01 01:59:00 -0800 PST 3 2020-11-02 01:59:00 -0800 PST 0 2 ** * 1 2020-11-01 02:00:00 -0800 PST 2 2020-11-02 02:00:00 -0800 PST 3 2020-11-03 02:00:00 -0800 PST 1 2 ** * 1 2020-11-01 02:01:00 -0800 PST 2 2020-11-02 02:01:00 -0800 PST 3 2020-11-03 02:01:00 -0800 PST
跳过前进(缺失计划)¶
您可以使用when来每天仅调度一次,即使您希望的时间处于夏令时向前跳过的时段(这种情况下通常会调度两次)。
一个示例时间表 02:30:00
schedules:
- 30 2 * * *
- 0 3 * * *
when: "{{= cronworkflow.lastScheduledTime == nil || (now() - cronworkflow.lastScheduledTime).Seconds() > 3600 }}"
该计划每天3:00的运行不会在全年每天都执行,除了时钟向前跳过2:30的那天。
when表达式防止此工作流每小时运行超过一次。
在这种情况下,3:00的运行将会执行,因为2:30被跳过了。
可以在3:00运行
如果您在期望时间和3:00之间创建这个CronWorkflow,它将在3:00运行,就像之前从未运行过一样。
向后跳过(重复)¶
你可以使用when来安排每天执行一次,即使你希望的时间处于夏令时回拨期间(这种情况下通常不会被调度)。
一个示例时间表 01:30:00
schedules:
- 30 1 * * *
when: "{{= cronworkflow.lastScheduledTime == nil || (now() - cronworkflow.lastScheduledTime).Seconds() > 7200 }}"
这将在第一次01:30时安排一个向后跳过的变更。
由于when表达式的限制,第二个将不会运行,该表达式阻止此工作流运行频率超过每2小时一次。
自动停止CronWorkflow¶
v3.6 及更高版本
您可以配置CronWorkflow,使其基于表达式通过stopStrategy.expression自动停止。
您可以使用变量cronworkflow.failed和cronworkflow.succeeded。
例如,如果您希望在成功运行一次后停止调度新的工作流:
stopStrategy:
expression: "cronworkflow.succeeded >= 1"
你也可以在三次失败后停止调度新的工作流:
stopStrategy:
expression: "cronworkflow.failed >= 3"
调度与完成情况
根据工作流调度和运行所需的时间,完成次数可能会超过配置的最大值。
例如,如果您将CronWorkflow配置为每分钟调度一次(* * * * *),并在成功一次后停止(cronworkflow.succeeded >= 1)。
如果Workflow需要90秒运行,CronWorkflow实际上会在两次完成后停止。
这是因为当达到停止条件时,已经有另一个Workflow在运行。
因此,建议使用类似cronworkflow.succeeded >= 1的条件,而不是cronworkflow.succeeded == 1。
管理 CronWorkflow¶
命令行界面¶
您可以通过CLI创建CronWorkflows:
$ argo cron create cron.yaml
Name: test-cron-wf
Namespace: argo
Created: Mon Nov 18 10:17:06 -0800 (now)
Schedules: * * * * *
Suspended: false
StartingDeadlineSeconds: 0
ConcurrencyPolicy: Forbid
$ argo cron list
NAME AGE LAST RUN SCHEDULES SUSPENDED
test-cron-wf 49s N/A * * * * * false
# some time passes
$ argo cron list
NAME AGE LAST RUN SCHEDULES SUSPENDED
test-cron-wf 56s 2s * * * * * false
$ argo cron get test-cron-wf
Name: test-cron-wf
Namespace: argo
Created: Wed Oct 28 07:19:02 -0600 (23 hours ago)
Schedules: * * * * *
Suspended: false
StartingDeadlineSeconds: 0
ConcurrencyPolicy: Replace
LastScheduledTime: Thu Oct 29 06:51:00 -0600 (11 minutes ago)
NextScheduledTime: Thu Oct 29 13:03:00 +0000 (32 seconds from now)
Active Workflows: test-cron-wf-rt4nf
注意: NextScheduledRun 假设控制器使用UTC作为其时区
kubectl¶
你可以使用 kubectl apply -f 和 kubectl get cwf
回填天数¶
参见 cron回填。
通过Argo CD实现GitOps¶
您可以通过使用Argo CD来用GitOps管理CronWorkflow资源
用户界面¶
您也可以在用户界面中管理CronWorkflow资源