New to Kestra?
Use blueprints to kickstart your first workflows.
Measure Kafka topic disk usage with DescribeLogDirs, flag topics over budget, cap them with per-partition retention.bytes and verify the reclaim.
Kafka brokers usually run out of disk because of one topic, not the total. Typical causes:
retention.ms=-1 "for now";Time-based retention does not help when the volume per day changes, and nothing warns before the disk alarm.
This blueprint reads the on-disk size of every topic with the AdminClient and compares it with a budget. It alerts Slack, and can cap the topics over budget with retention.bytes, then describe them again to verify. Optionally it waits until the broker has deleted the old segments and the space is back.
This blueprint was created by zkasuran.
default_budget_mb applies to every topic, and budgets_mb overrides it per topic. Internal topics (__consumer_offsets...) are skipped.DescribeLogDirs.retention.bytes is enforced per partition replica, so the value set is budget / (partitions × replication factor). A 20 MB budget on a 4-partition topic sets retention.bytes=5242880.log_dirs (io.kestra.plugin.kafka.DescribeLogDirs, read-only) returns the size of every topic. over keeps those above their budget.describe_over (io.kestra.plugin.core.flow.Loop over io.kestra.plugin.kafka.TopicDescribe) reads the partition count, replication factor and retention configs of each one.plan computes the per-partition retention.bytes, flags unbounded topics (retention.ms and retention.bytes both -1), and marks compacted ones as report only. summary logs it.route (io.kestra.plugin.core.flow.If):alert posts to Slack.remediate_gate runs only when auto_remediate is true and dry_run is false.remediate sets retention.bytes with TopicUpdate, then verify and verify_result describe the topics again and fail on any other value.wait_for_reclaim, wait_reclaim (io.kestra.plugin.core.flow.LoopUntil) polls DescribeLogDirs every 15 seconds until each topic is within 125% of its budget, then reclaimed logs the sizes before and after.errors alerts Slack when the flow fails, for example on an unreachable broker.retention.bytes arithmetic done for you, per partition and replica.DescribeLogDirs driving TopicUpdate.kafka-log-dirs.sh prints raw JSON per partition. Kestra sums it per topic on a schedule and compares it with budgets kept next to the flow. It turns overruns into a Slack alert, applies the cap only behind auto_remediate and dry_run, waits for the broker with LoopUntil, and keeps an execution history of every topic's size over time.
On Kestra 2.0.5 OSS against Apache Kafka 3.9.1 (KRaft, log.retention.check.interval.ms=10000, 1 MB segments), with a local HTTP sink standing in for Slack. Topics:
clickstream: 4 partitions, 58 MB, retention.ms=-1;orders: 4 MB, with a 50 MB budget;customers: compacted, 1.8 MB.| Run | Inputs | Result |
|---|---|---|
| 1 | defaults (20 MB) | clickstream over budget with no limit, target retention.bytes=5242880. Alert sent |
| 2 | default_budget_mb: 1 |
Adds customers, reported as compacted, never capped. orders within its 50 MB override |
| 3 | auto_remediate: true, dry_run: true |
Same report. kafka-configs.sh shows no retention.bytes on clickstream |
| 4 | auto_remediate: true, dry_run: false, wait_for_reclaim: true |
retention.bytes=5242880 set and verified. kafka-configs.sh shows the same. clickstream went from 57 MB to 22.3 MB on disk |
| 5 | defaults again | Nothing to do: clickstream is capped, the 2.3 MB above budget is the active segments |
| 6 | unreachable broker | errors alert sent |
docker run -d --name kafka -p 9092:9092 apache/kafka:3.9.1;--config retention.ms=-1 --config segment.bytes=1048576;kafka-producer-perf-test.sh.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Default | Purpose |
|---|---|---|
bootstrap_servers |
localhost:9092 |
Brokers |
default_budget_mb |
20 |
Budget per topic |
budgets_mb |
{"orders": 50} |
Per-topic overrides |
wait_for_reclaim |
false |
Wait for the space to come back |
auto_remediate |
false |
Allow TopicUpdate |
dry_run |
true |
Must be false for a change to apply |
SLACK_WEBHOOK_URL secret.bootstrap_servers, default_budget_mb and budgets_mb for your largest topics.auto_remediate: true and dry_run: false.hourly trigger, which always runs in safe mode.Pause before capping topics that hold more than a day of data.retention.bytes): https://kafka.apache.org/documentation/#topicconfigs_retention.bytes