TopicList icon
OutputValues icon
Loop icon
TopicDescribe icon
Log icon
If icon
SlackIncomingWebhook icon
TopicUpdate icon
Fail icon
Schedule icon

Kafka Topic Config Drift Guard

Detect Kafka topic config drift against a policy, alert Slack, remediate with TopicUpdate behind dry-run gates, and re-describe to verify.

Categories
DataInfrastructure

Kafka topic configs drift. Someone sets retention.ms=-1 on a topic to debug an incident and never puts it back, so the disk fills months later. A compacted topic is recreated with the default cleanup.policy=delete and silently starts losing keys. A topic the platform team expects is never created. None of this throws an error. It shows up as an outage or as lost data.

This blueprint describes every topic in a declared policy with the Kafka AdminClient and compares only the keys you care about. It alerts Slack on any drifted key or missing topic, and can set the drifted keys back with TopicUpdate, behind two gates. After a change it describes the topics again, so the run only reports success when the broker really holds the policy value.

This blueprint was created by zkasuran.

How it works

  1. list_topics (io.kestra.plugin.kafka.TopicList) lists the topics on the cluster. present splits the policy into topics that exist and topics that are missing, so a missing topic is reported instead of failing the describe.
  2. describe_topics (io.kestra.plugin.core.flow.Loop over io.kestra.plugin.kafka.TopicDescribe) reads the live configs of every policy topic, read-only.
  3. drift lists every policy key whose live value differs, with the live and the desired value. Keys not in the policy are never looked at.
  4. summary logs the result every run.
  5. route (io.kestra.plugin.core.flow.If):
    • compliant: logs it.
    • drift or missing topics: alert posts to Slack, saying whether a change will be applied.
      • remediate_gate runs only when auto_remediate is true and dry_run is false.
      • remediate sends one TopicUpdate per drifted topic with only its drifted keys.
      • verify describes those topics again, and verify_result fails the run if any key still differs.
      • Missing topics are logged as a warning and never created.
  6. errors alerts Slack when the flow itself fails, for example on an unreachable broker. A failed check must not read as a compliant cluster.

Safety

  • Read-only by default: auto_remediate: false, dry_run: true. The hourly trigger is shipped disabled and always runs in safe mode.
  • Only keys listed in the policy are ever changed, and only to the policy value.
  • Topics are never created, deleted or repartitioned.
  • No message is consumed or produced.

What you get

  • A check of only the topic configs you declare, on every topic in the policy, with the live and the desired value of every drifted key.
  • Missing topics reported, never created.
  • Fixes limited to the drifted keys, behind two gates, verified by a second describe.

Who it's for

  • Platform teams running Kafka clusters shared by many services.
  • Data engineering teams whose retention and compaction settings are part of their data contracts.
  • Teams evaluating the Kafka plugin who want an example of TopicDescribe and TopicUpdate with gates around them.

Why orchestrate this with Kestra

kafka-configs.sh --describe shows a config at one moment. Kestra runs the comparison on a schedule, keeps the policy next to the flow, turns drift into a Slack alert, applies TopicUpdate only behind auto_remediate and dry_run, and keeps an execution history showing when each key drifted and when it was put back.

Tested end to end

On Kestra 2.0.5 OSS against Apache Kafka 3.9.1 (KRaft, one broker), with a local HTTP sink standing in for Slack.

Run Inputs Result
1 defaults 2 drifted keys found: payments retention.ms=-1 (policy 30 days) and customers-compacted cleanup.policy=delete (policy compact). invoices reported missing. Slack alert sent, nothing changed
2 auto_remediate: true, dry_run: true Same report, the alert says no change was applied. kafka-configs.sh still shows retention.ms=-1
3 auto_remediate: true, dry_run: false 2 TopicUpdate calls, re-describe confirms both keys. kafka-configs.sh shows retention.ms=2592000000 and cleanup.policy=compact
4 policy without invoices Compliant, no alert
5 unreachable broker AdminClient timeout, the errors alert is sent

Prerequisites

  • A Kafka cluster reachable from the Kestra worker, and a principal allowed to describe topics, plus AlterConfigs if remediation will be used.
  • Local testing: docker run -d --name kafka -p 9092:9092 apache/kafka:3.9.1. Then create a few topics with kafka-topics.sh and change a config with kafka-configs.sh --alter to see the drift.

Secrets

  • SLACK_WEBHOOK_URL: Slack incoming webhook used by alert and the errors block. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.

Inputs

Input Default Purpose
bootstrap_servers localhost:9092 Brokers
policy 5 example topics Desired configs per topic
auto_remediate false Allow TopicUpdate
dry_run true Must be false for a change to apply

For a secured cluster, add security.protocol, sasl.mechanism and sasl.jaas.config to each task's properties, read from secrets.

Quick start

  1. Add the SLACK_WEBHOOK_URL secret.
  2. Import the flow, set bootstrap_servers, and replace policy with your topics and keys.
  3. Run it once and read the drifted keys and missing topics.
  4. Run it with auto_remediate: true and dry_run: false to put the keys back.
  5. Enable the hourly trigger, which always runs in safe mode.

How to extend

  • Load the policy from a Git repository or a namespace file, so topic configs are reviewed like code.
  • Create the missing topics from the policy, with partition count and replication factor, behind an approval Pause.
  • Check several clusters by looping over a list of bootstrap servers.
  • Also compare partition counts and replication factor with TopicDescribe's other outputs.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.