Monedula
monedula-gitops docs menu

Drift and reconciliation modes

What monedula-gitops counts as drift, how verify reports it, and how the reconciliation modes change what apply and the operator do.

Concepts 3 of 6

2 min read

Updated 5 October 2026

Markdown

On this page

Drift is a difference between what your manifests declare and what the cluster has, for example a topic setting someone changed by hand. Each resource’s reconciliation mode decides whether monedula-gitops corrects it or only reports it.

What counts as drift

Live state is compared only with what your manifests declare, and only the kinds they declare are read (CLI overview):

  • A topic, user or quota entity that no manifest names is not drift.
  • Only the topic config keys in spec.config are compared. Live keys you do not list are never touched or reported.
  • An ACL counts when it matches a principal and resource pattern that your manifests reference. An in-scope ACL that no manifest declares any more is a prune candidate, and verify counts it as drift until it is pruned or declared again.
  • spec.limits is authoritative for its quota entity, so a limit set live but missing from the manifest is drift.
  • For a KafkaUser, the username, the declared mechanism and an explicitly set iteration count are compared, never the password (Provision SCRAM users).

A KafkaTopic can leave fields to another owner with spec.drift.ignoreFields (partitions, replicationFactor or config.<key>). verify, diff and apply all skip an ignored field; Detect and fix drift has an example.

How drift is reported

verify runs the same comparison as diff, names each drifted field and exits 1 on drift, which diff never does. Both accept -o yaml or -o json.

The operator checks for drift on every reconcile and on every resync, so out-of-band changes are caught without a Git change. Drift appears in the resource status and in metrics such as monedula_kafka_topic_drift_detected (1 or 0 per resource).

Reconciliation modes

spec.reconciliation.mode (on KafkaTopic, KafkaAccessPolicy, KafkaQuota and KafkaRoleBinding) works the same in both runtimes:

Mode apply verify on drift Operator
Enforce (default) runs the operations exits 1 applies the diff
DetectOnly reports the operations, never runs them exits 1 reports drift in status and metrics, on drift with the phase Drifted and Ready=False; never changes Kafka
ObserveOnly reports the operations, never runs them, not even a create shows the drift, exits 0 reports drift in status and metrics and stays Ready; never changes Kafka

Report-only operations never fail apply.

Enforce fits resources that your pipeline or operator owns. DetectOnly fits resources where drift should fail CI or raise an alert, but a person decides how to correct it. ObserveOnly never blocks CI, which suits auditing topics another team owns. Because an ObserveOnly manifest never creates anything, its topic must already exist.