Starting with OpenMetadata 1.12, you can run ingestion pipelines directly using native Kubernetes,
eliminating the need for Apache Airflow. This is ideal for organizations that:
Already run workloads on Kubernetes and prefer native solutions
Uses custom Kubernetes CRDs (OMJob and CronOMJob) managed by the OpenMetadata operator.
Resource
Description
CronOMJob
Scheduled pipelines - runs on a cron schedule
OMJob
On-demand pipelines - one-off execution when triggered
Recommended for production. The OMJob Operator provides guaranteed exit handler execution and failure diagnostics.
Advantages:
Exit Handler Guarantee: Even if the ingestion pod crashes (OOMKilled, node failure, etc.), the operator ensures pipeline status is always reported back to OpenMetadata
Failure Diagnostics: Automatically collects detailed error context from pod logs and events when pipelines fail
Pod Lifecycle Monitoring: The operator watches pod events and updates pipeline status in real-time
Requirements:
Elevated permissions to install Custom Resource Definitions (CRDs)
The OMJob Operator deployment running in your cluster
Always pin ingestionImage to the same version as your OpenMetadata server — never use :latest. The :latest tag moves whenever a new release is published; any Kubernetes node without the previous image cached will silently pull the newer version on the next scheduled job, causing a server/client version mismatch. The ingestion major version must match the server major version (for example, a 1.12.x server requires a 1.12.x ingestion image).
# Enable the OMJob OperatoromjobOperator: enabled: true image: repository: docker.getcollate.io/openmetadata/omjob-operator tag: "1.12.0" pullPolicy: IfNotPresent resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "256Mi"openmetadata: config: pipelineServiceClientConfig: enabled: true type: "k8s" metadataApiEndpoint: http://openmetadata:8585/api k8s: # Use the OMJob Operator useOMJobOperator: true # Container image for ingestion jobs ingestionImage: "docker.getcollate.io/openmetadata/ingestion-base:1.12.0" imagePullPolicy: "IfNotPresent" imagePullSecrets: "" # Service account for ingestion jobs serviceAccountName: "openmetadata-ingestion" # Job lifecycle settings ttlSecondsAfterFinished: 86400 # Keep completed jobs for 24 hours activeDeadlineSeconds: 7200 # Max 2 hour runtime backoffLimit: 3 # Retry up to 3 times # Job history successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 # Pod security context securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 runAsNonRoot: true # Resource limits resources: limits: cpu: "2" memory: "4Gi" requests: cpu: "500m" memory: "1Gi" # Enable failure diagnostics (only works with OMJob Operator) enableFailureDiagnostics: true # RBAC - set to false if managed externally rbac: enabled: true
Always pin ingestionImage to the same version as your OpenMetadata server — never use :latest. The :latest tag moves whenever a new release is published; any Kubernetes node without the previous image cached will silently pull the newer version on the next scheduled job, causing a server/client version mismatch. The ingestion major version must match the server major version (for example, a 1.12.x server requires a 1.12.x ingestion image).
openmetadata: config: pipelineServiceClientConfig: enabled: true type: "k8s" metadataApiEndpoint: http://openmetadata:8585/api k8s: # Do NOT use the OMJob Operator (default) useOMJobOperator: false # Container image for ingestion jobs ingestionImage: "docker.getcollate.io/openmetadata/ingestion-base:1.12.0" imagePullPolicy: "IfNotPresent" imagePullSecrets: "" # Service account for ingestion jobs serviceAccountName: "openmetadata-ingestion" # Job lifecycle settings ttlSecondsAfterFinished: 86400 activeDeadlineSeconds: 7200 backoffLimit: 3 # Job history successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 # Pod security context securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 runAsNonRoot: true # Resource limits resources: limits: cpu: "2" memory: "4Gi" requests: cpu: "500m" memory: "1Gi" # RBAC - set to false if managed externally rbac: enabled: true