content/v2.1/operations/cronoperation.md
A CronOperation creates [Operations]({{<ref "operation">}}) on a schedule,
like Kubernetes CronJobs. Use CronOperations for recurring operational tasks
such as database backups, certificate rotation, or periodic maintenance.
CronOperations contain a template for an Operation and create new Operations based on a cron schedule. Each scheduled run creates a new Operation that executes once to completion.
apiVersion: ops.crossplane.io/v1alpha1
kind: CronOperation
metadata:
name: daily-backup
spec:
schedule: "0 2 * * *" # Daily at 2 AM
concurrencyPolicy: Forbid
successfulHistoryLimit: 5
failedHistoryLimit: 3
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: backup
functionRef:
name: function-database-backup
input:
apiVersion: fn.crossplane.io/v1beta1
kind: DatabaseBackupInput
retentionDays: 7
{{<hint "important">}}
CronOperations are an alpha feature. You must enable Operations by adding
--enable-operations to Crossplane's arguments.
{{</hint>}}
CronOperations use standard cron syntax:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
│ │ │ │ │
* * * * *
Common schedule examples:
"0 2 * * *" - Every day at 2:00 AM"0 0 * * 0" - Every Sunday at midnight"0 0 1 * *" - Every month on the first at midnight"*/15 * * * *" - Every 15 minutesCronOperations support three concurrency policies:
Control the number of completed Operations to keep:
spec:
successfulHistoryLimit: 5 # Keep 5 successful operations
failedHistoryLimit: 3 # Keep 3 failed operations for debugging
This helps balance debugging capabilities with resource usage.
{{<hint "note">}} The following examples use hypothetical functions for illustration. At launch, only function-python supports operations. {{</hint>}}
apiVersion: ops.crossplane.io/v1alpha1
kind: CronOperation
metadata:
name: postgres-backup
spec:
schedule: "0 3 * * *" # Daily at 3 AM
concurrencyPolicy: Forbid # Don't allow overlapping backups
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: backup
functionRef:
name: function-postgres-backup
input:
apiVersion: fn.crossplane.io/v1beta1
kind: PostgresBackupInput
instance: production-db
s3Bucket: db-backups
apiVersion: ops.crossplane.io/v1alpha1
kind: CronOperation
metadata:
name: weekly-maintenance
spec:
schedule: "0 3 * * 0" # Weekly on Sunday at 3 AM
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: cleanup-logs
functionRef:
name: function-log-cleanup
input:
apiVersion: fn.crossplane.io/v1beta1
kind: LogCleanupInput
retentionDays: 30
- step: update-certificates
functionRef:
name: function-cert-renewal
apiVersion: ops.crossplane.io/v1alpha1
kind: CronOperation
metadata:
name: health-check
spec:
schedule: "*/30 * * * *" # Every 30 minutes
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: check-cluster-health
functionRef:
name: function-health-check
input:
apiVersion: fn.crossplane.io/v1beta1
kind: HealthCheckInput
alertThreshold: 80
Advanced cron schedule examples for specific use cases:
# Weekdays only at 9 AM (Monday-Friday)
schedule: "0 9 * * 1-5"
# Every 4 hours during business days
schedule: "0 8,12,16 * * 1-5"
# First and last day of each month
schedule: "0 2 1,L * *"
# Every quarter (1st of Jan, Apr, Jul, Oct)
schedule: "0 2 1 1,4,7,10 *"
# Business hours only, every 2 hours
schedule: "0 9-17/2 * * 1-5"
CronOperations support a startingDeadlineSeconds field that controls how
long to wait after the scheduled time before considering it too late to
create the Operation:
apiVersion: ops.crossplane.io/v1alpha1
kind: CronOperation
metadata:
name: deadline-example
spec:
schedule: "0 9 * * 1-5" # Weekdays at 9 AM
startingDeadlineSeconds: 900 # 15 minutes
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: morning-tasks
functionRef:
name: function-morning-tasks
If the Operation can't start in 15 minutes of 9 AM (due to controller downtime, resource constraints, etc.), the scheduled run is skipped.
Skip operations for:
{{<hint "important">}} CronOperations use the cluster's local time zone, same as Kubernetes CronJobs. To ensure consistent scheduling across different environments, consider:
CronOperations provide status information about scheduling:
status:
conditions:
- type: Synced
status: "True"
reason: ReconcileSuccess
- type: Scheduling
status: "True"
reason: ScheduleActive
lastScheduleTime: "2024-01-15T10:00:00Z"
lastSuccessfulTime: "2024-01-15T10:02:30Z"
runningOperationRefs:
- name: daily-backup-1705305600
Key status fields:
True when the CronOperation is actively scheduling operations, False when paused or has incorrect schedule syntaxlastScheduleTime: When the CronOperation last created an OperationlastSuccessfulTime: When an Operation last completed successfullyrunningOperationRefs: Running OperationsCronOperations emit events for important activities:
CreateOperation (Warning) - Scheduled operation creation failuresGarbageCollectOperations (Warning) - Garbage collection failuresReplaceRunningOperation (Warning) - Running operation deletion failuresInvalidSchedule (Warning) - Cron schedule parsing errorsMonitor CronOperations using:
<!-- vale write-good.TooWordy = YES --># Check CronOperation status
kubectl get cronoperation my-cronop
# View recent Operations created by the CronOperation
kubectl get operations -l crossplane.io/cronoperation=my-cronop
# Check events
kubectl get events --field-selector involvedObject.name=my-cronop
For general Operations best practices including function development and operational considerations, see [Operation best practices]({{<ref "operation#best-practices">}}).
Synced=True conditionoperation