Overview
Apache Kafka is a distributed event streaming platform for high-throughput, fault-tolerant publish-subscribe messaging. This template deploys a Kafka cluster in KRaft mode (no ZooKeeper): every broker is also a KRaft controller, the client listener authenticates with SASL/PLAIN, Kafka ACLs are enforced, and each broker keeps its logs on persistent volumes with daily snapshots. A health sidecar and two Prometheus exporters run beside every broker. Kafbat UI (a web console), a Confluent REST Proxy and a Kafka CLI client workload are on by default; Kafka Connect workers and a public listener for clients outside the GVC are opt-in.--gvc. It does not create, provision or manage a GVC, and uninstalling the release never deletes one.What Gets Created
Prerequisites
Create the Kafbat UI configuration secret
ADMIN_PASSWORD with the value you will pass as kafka.listeners.client.sasl.admin.password, and UI_PASSWORD with the login you want for the console. The full file format is in the Kafbat configuration reference.kafka-kafbat-ui-config is the default value of kafbat_ui.configuration_secret; if you pick another name, set that value to match. If you do not want the console, install with --set kafbat_ui.enabled=false instead and skip this step.Choose the cluster credentials
kafka.secrets.inter_broker_password, kafka.secrets.controller_password, kafka.listeners.client.sasl.admin.password and kafka.listeners.client.sasl.passwords. The your-… defaults in values.yaml are placeholders that work as literal passwords, so never leave them in place. The cluster ID is written into the log volumes at first start and cannot be changed afterwards without a new cluster.Public listener (optional)
Installation
Install into an existing GVC, supplying the credentials from the prerequisites:kafka-dev with the default password. Either put kafka_rest_proxy.properties.bootstrap.servers, kafka_rest_proxy.jaas_conf and kafka_rest_proxy.password_properties in a values file (-f values.yaml) as shown under Kafka REST Proxy, or add --set kafka_rest_proxy.enabled=false.UI
CLI
Terraform
Pulumi
Configuration
Each block below shows the shipped defaults for one area ofvalues.yaml. Only the keys you change need to go in your values file.
Kafka Cluster
Storage
customEncryption enabled, finish the setup after installing: open each RELEASE_NAME-logs-N volume set in the console, go to its spec and follow the AWS Custom Encryption Instructions shown there. Existing volumes cannot be re-encrypted.Firewall
Listeners
Every entry underkafka.listeners becomes a broker listener. The chart ships one, client; a second entry is how you add external access. Ports 9091, 9093 and 9094 are reserved for the controller and inter-broker listeners.
Client Listener
Public Listener
Add a second listener to reach the brokers from outside the GVC. TLS is terminated at the load balancer, so external clients connect withsecurity.protocol=SASL_SSL. Only one listener may carry a public address.
Direct replica routing (recommended). One domain with a DNS01 certificate challenge; each broker is advertised at <replica>-<location>.<publicAddress>:<containerPort> (for release kafka in aws-us-east-1: kafka-cluster-0-aws-us-east-1.kafka.example.com:9095, kafka-cluster-1-aws-us-east-1.kafka.example.com:9095, …). Create a CNAME for each broker hostname plus the _acme-challenge record as the domain reference describes.
kafka.example.com:3000, :3001, :3002). Do not set containerPort here. Not recommended for multi-zone clusters, because traffic is not routed zone-aware.
ACL and Cluster Secrets
Extra Configurations
Keys underkafka.extra_configurations are appended to server.properties and override the chart’s defaults. The chart derives default.replication.factor as the smaller of 3 and kafka.replicas, and min.insync.replicas as one less than that; set them here only to override.
Health Sidecar and Exporters
All three run as sidecar containers onRELEASE_NAME-cluster. The health sidecar gates broker readiness on real cluster health (broker registration, controller election, under-replicated partitions, log directories); the exporters publish Prometheus metrics that the platform scrapes automatically.
Kafbat UI
Kafka REST Proxy
The proxy connects to the brokers as theKafkaClient principal in jaas_conf, and authenticates HTTP callers with BASIC auth against the users in password_properties. Both must be set for your release: bootstrap.servers must name your cluster workload and the KafkaClient password must equal kafka.listeners.client.sasl.admin.password. Without password_properties the BASIC realm has no users and every request is refused.
Kafka Connect
kafka_connectors is a list; each entry deploys a Kafka Connect worker cluster named RELEASE_NAME-connect- plus the entry’s name, with a volume set for plugins and a plugins-downloader container that fetches plugin artifacts into plugins_folder (see Kafka Connect Plugins). Connectors listed under plugins are created or updated through the Connect REST API when the worker starts; an entry with enabled: false is removed. The shipped values.yaml carries complete, commented examples for MirrorMaker 2, a Camel S3 sink, a ClickHouse sink and a Snowflake sink.
Kafka Connect Plugins
Every Kafka Connect replica runs two containers:kafka-connect and plugins-downloader. The downloader fetches every artifact of each plugin that has enabled: true onto the plugins volume set. Kafka Connect scans its plugins folder only once per start, so it waits until every artifact is in place before it starts. Each artifact is downloaded to a staging area on the volume, verified, and only then moved into its own directory (<plugins_folder>/<plugin>/<key>/), so in a normal start Kafka Connect never sees a half-written file. An artifact that is already installed and unchanged is not downloaded again, so a restart does not repeat the downloads.
enabled: trueis required for a download. A plugin without the key is not downloaded, but its connector is still created; use that for a plugin you placed in the plugins folder yourself. Withenabled: falsethe connector is deleted, and the artifacts the chart downloaded for it are removed.- Set
sha256on every artifact. The downloader does not verify TLS certificates, so the checksum is the integrity check. On a mismatch the artifact is not installed and the download is retried. Withoutsha256, ajaror archive is still checked to be a valid file before it is installed. - Each artifact gets its own directory, so a plugin with several
jarartifacts keeps all of them, and they load in one classloader. - Files you placed on the volume yourself are never deleted. The chart removes only artifacts it downloaded, only after a download pass succeeds, and nothing while any artifact has a configuration error (an unsupported type, a missing URL). The downloader lists the files it leaves alone at each start (
left untouched (not downloaded by this chart)). - Changing an artifact’s
urlorsha256downloads that artifact again; the old copy is removed once the pass succeeds. Size the volume for every installed artifact plus room to download and unpack the largest one. plugins_wait_timeout_secondsandplugins_wait_timeout_actiondecide what happens when a download is still missing at the timeout:startstarts Kafka Connect without it and logs aWARNINGnaming it;restartexits so the container restarts and waits again. See Troubleshooting.plugins_redownload_tokenforces a fresh download of every plugin: set it to a new value and upgrade the release.downloader_cpudefaults to80m. Raise it to250mwhen an artifact is 50 MB or larger, so the download finishes well inside the wait timeout.- Credentials in an artifact URL (a
user:password@prefix on the host name) are sent only to that URL’s host; a redirect to another host, such as a presigned storage URL, is followed without them. They are redacted in the logs, but they are stored in theRELEASE_NAME-connect-<name>-downloadsecret and in the Helm release. Percent-encode/,?,#and@inside the user name or password. - The Kafka Connect workload reports ready while it waits for plugins. Read the
kafka-connectlog forWaiting for plugin downloadsto see that it is still waiting.
Kafka Client
Connecting
PLAINTEXT client listener, drop the --command-config, --producer.config and --consumer.config flags. Topics are created on first use because auto.create.topics.enable is true.
To check the REST Proxy from a workload in the same GVC, list the clusters it sees (the v3 API) with one of the BASIC-auth users you configured:
Operations
Backing Up
Kafka’s first line of defence is replication: with the default three brokers, every topic is replicated three times and a write is acknowledged only once two replicas have it. On top of that, each broker volume set takes a snapshot daily at 00:00 UTC, keeps it for seven days and takes a final snapshot when the volume set is deleted (kafka.volumes.logs.snapshots). Take an extra snapshot before risky changes, once per log-directory volume set:
Restoring a Backup
Restoring a volume snapshot onto a running broker has not been verified for this template; a broker whose log directories are replaced underneath it, or whose KRaft metadata no longer matches its peers, is not something this page can promise will rejoin cleanly. Treat snapshots as a last resort and rely on replication for broker loss. What the chart does support is mounting volume sets that were restored or renamed outside the chart: list them, inkafka.logDirs order, and the chart stops creating its own and mounts yours instead, leaving their data and settings untouched. Use "" for any entry the chart should keep managing.
kafka.logDirs path, or rendering fails with an error naming both counts.
Upgrading from 2.x
Since 3.0.0 the chart only supports Apache Kafka images. A values file that still sets a Bitnami image fails to render withError: This chart does not support Bitnami images, please use Apache Kafka images instead. Set kafka.image to an apache/kafka tag. Moving the data of a 2.x Bitnami-based release onto 3.x or later has not been verified; plan for a new release and re-mirror topics (the kafka_connectors MirrorMaker 2 example in values.yaml is one way).
Upgrading from 3.x
- 4.0.0 added the
kafka-orchestratorreadiness sidecar (setkafka_orchestrator: nullto opt out), raised the graceful shutdown window tokafka.terminationGracePeriodSeconds: 600, and started derivingdefault.replication.factorandmin.insync.replicasfromkafka.replicas. Adefault.replication.factoryou carried over inkafka.extra_configurationsstill wins; remove it unless you need a non-default value. - 4.0.2 commented out the sample REST Proxy user. If you relied on the default
userBASIC-auth account, setkafka_rest_proxy.password_propertiesexplicitly. - 4.1.0 added
kafka.rackAwareness,kafka.volumes.logs.externalVolumeSetsand per-connectortags; all off by default, nothing to change. - 4.2.0 stops the brokers writing a duplicate
server.logto the container filesystem onapache/kafka:3.ximages by settingKAFKA_LOG4J_ROOT_LOGLEVEL=INFO; the broker log is incpln logs. The upgrade restarts the brokers.
Upgrading from 4.2.x
4.3.0 changes only how Kafka Connect gets its plugins: 4.2.x slept a fixed 60 seconds before starting, so a slow download could leave a connector missing orFAILED; 4.3.0 waits for the downloads to finish (see Kafka Connect Plugins). Nothing in your values has to change.
- The upgrade restarts every Kafka Connect replica, one at a time, and the brokers.
- The first start after the upgrade downloads every plugin again, once per replica, into the new layout, and Kafka Connect waits for it. Expect each replica’s connectors to be down for about one full download. Later restarts reuse the installed plugins.
-
The chart’s old
<plugin>/<plugin>.jarfiles, for plugins that still have ajarartifact, are moved to.cpln-downloads/retired/in the plugins folder. A file you placed at exactly that path is moved too, and can be moved back. -
Directories that earlier versions extracted from
zip,tarortgzartifacts stay in place, and Kafka Connect still loads them beside the new copy. Once your connectors areRUNNING, remove them on each replica (RELEASE_NAME-connect-<name>-0,-1, …), then redeploy. The candidates are the entries the downloader lists at start asleft untouched (not downloaded by this chart), minus any you placed yourself; directories named after a plugin’sname,.cpln-downloadsandlost+foundare never candidates. The commands below are for a connector entry namedcluster; in a GVC with more than one location, add--location LOCATIONto eachexec: - 4.2.x printed artifact URLs, including any credentials in them, in the downloader log; 4.3.0 redacts them. Consider rotating any credential that was part of an artifact URL.
-
Rolling back to 4.2.x works and the connectors keep running, but 4.2.x writes its
<plugin>/<plugin>.jarfiles again beside the 4.3.0 directories (both load in one classloader) and its 60-second startup race returns. Upgrading to 4.3.0 again retires those files.
Scaling and Availability
kafka.replicasaccepts 1, 3, 4 or 5. Rendering fails withInvalid value for kafka.replicas. It must be less than or equal to 5 and not equal to 2.otherwise. Every broker is also a KRaft controller, so never shrink a running cluster below the number of controllers it was formed with — the quorum is lost and the cluster stops.- A single-broker cluster replicates nothing; use it for development only.
kafka.multiZone: truespreads the brokers across availability zones. On AWS, addkafka.rackAwareness.enabled: trueand setclient.rackon consumers to their zone ID (workloads on AWS locations receive it in theAWS_ZONE_IDenvironment variable) so they fetch from a same-zone replica; producers and replication are unaffected.- Broker volumes grow automatically up to
kafka.volumes.logs.autoscaling.maxCapacitywhen free space drops belowminFreePercentage. - Kafbat UI, the REST Proxy and each Kafka Connect worker scale with their own
replicasvalue.
Troubleshooting
Broker output is incpln logs; filter server-side:
Kafbat UI never becomes ready and cpln logs shows nothing
Kafbat UI never becomes ready and cpln logs shows nothing
kafbat_ui.configuration_secret did not exist when the workload was created. The container never starts, so there is no log output.Fix: read status.versions[].message from cpln workload get-deployments RELEASE_NAME-kafbat-ui --gvc GVC_NAME -o yaml to see which secret is missing, create it as shown in Prerequisites, then wait a few minutes or run cpln workload force-redeployment RELEASE_NAME-kafbat-ui --gvc GVC_NAME.Install fails with Invalid value for kafka.replicas
Install fails with Invalid value for kafka.replicas
kafka.replicas is 2 or more than 5. Two controllers cannot form a quorum, and the chart caps the cluster at five.Fix: set kafka.replicas to 1, 3, 4 or 5.Install fails with This chart does not support Bitnami images
Install fails with This chart does not support Bitnami images
kafka.image, kafka_client.image or a connector image references a Bitnami image, which the chart stopped supporting in 3.0.0.Fix: use an apache/kafka tag such as apache/kafka:3.9.1.Install fails with containerPort cannot be 9091, 9093, or 9094 for listener
Install fails with containerPort cannot be 9091, 9093, or 9094 for listener
containerPort (or directReplicaRouting.containerPort) uses one of the ports reserved for the controller and inter-broker listeners.Fix: pick another port, for example 9092 for the client listener and 9095 for a public one.Install fails with kafka.volumes.logs.externalVolumeSets has N entries but kafka.logDirs defines M log dirs
Install fails with kafka.volumes.logs.externalVolumeSets has N entries but kafka.logDirs defines M log dirs
externalVolumeSets is set but its length does not match the number of comma-separated paths in kafka.logDirs. The chart refuses a partial list so it never mounts an empty new volume set beside imported ones.Fix: provide exactly one entry per log directory, in the same order, using "" for any directory the chart should keep managing.REST Proxy requests fail and its log mentions kafka-dev-cluster
REST Proxy requests fail and its log mentions kafka-dev-cluster
kafka_rest_proxy.properties.bootstrap.servers still has the shipped default SASL_PLAINTEXT://kafka-dev-cluster:9092, which only resolves for a release named kafka-dev, or the KafkaClient password in kafka_rest_proxy.jaas_conf does not match kafka.listeners.client.sasl.admin.password.Fix: set bootstrap.servers to SASL_PLAINTEXT://RELEASE_NAME-cluster.GVC_NAME.cpln.local:9092, align the KafkaClient password, add at least one user under kafka_rest_proxy.password_properties, and upgrade the release.A changed Kafbat UI configuration is not picked up
A changed Kafbat UI configuration is not picked up
cpln workload force-redeployment RELEASE_NAME-kafbat-ui --gvc GVC_NAME after changing the secret.Kafka Connect started before its plugins were ready
Kafka Connect started before its plugins were ready
plugins_wait_timeout_seconds ran out: a large or slow download, a dead URL or a sha256 mismatch. With the default plugins_wait_timeout_action: start, the kafka-connect log shows WARNING: connector plugins not ready after 900s; starting Kafka Connect WITHOUT: followed by the missing artifacts, and connectors that need them fail. With restart it shows FATAL: connector plugins not ready after 900s; exiting so the container restarts and waits again. and the container restarts. Read the log (for a connector entry named cluster):ERROR download failed or ERROR sha256 mismatch line. For large artifacts, raise downloader_cpu to 250m or raise plugins_wait_timeout_seconds; use plugins_wait_timeout_action: restart if Kafka Connect must never run without a plugin. Once the download succeeds, the downloader logs all artifacts are now installed; Kafka Connect started without some of them, so restart the worker (cpln workload force-redeployment) to load them. Then run cpln workload force-redeployment RELEASE_NAME-connect-cluster --gvc GVC_NAME. Restarting only the kafka-connect container does not wait again and does not clean up; a redeployment does both.A connector is FAILED with Failed to find any class
A connector is FAILED with Failed to find any class
cpln workload force-redeployment RELEASE_NAME-connect-cluster --gvc GVC_NAME.Force a plugin re-download
Force a plugin re-download
plugins_redownload_token on the connector entry to a new value (any string) and upgrade the release. Every plugin of that entry is downloaded again and the old copies are removed once the download pass succeeds.Important Notes
- Replace every
your-…placeholder (kafka.secrets.*,kafka.listeners.client.sasl.*) before installing; they are accepted as literal passwords. They are plain template values and therefore land in the Helm release. kafka.secrets.kraft_cluster_idis fixed once the brokers have started; changing it later means a new cluster.kafka.replicasmust be 1, 3, 4 or 5. Never shrink a running cluster below its controller count.- Kafbat UI and the REST Proxy are open to the internet by default (
external_inboundAllowCIDR: 0.0.0.0/0); set a strong console login and BASIC-auth users, or narrow the CIDR. - The REST Proxy defaults only work for a release named
kafka-dev: setkafka_rest_proxy.properties.bootstrap.servers,kafka_rest_proxy.jaas_confandkafka_rest_proxy.password_propertiesfor your release, or disable it. ghcr.io/kafbat/kafka-ui,confluentinc/cp-kafka-rest:latestand the JMX exporter image are not pinned, so a redeploy may pick up a newer build; pin a tag in your values if that matters.- Uninstalling deletes the volume sets and every topic’s data; a final snapshot is kept for
retentionDurationbecausecreateFinalSnapshotistrue. - Only set
KAFKA_LOG4J_ROOT_LOGLEVELinkafka.envonapache/kafka:3.ximages; on a 4.x image it removes every output from the root logger, includingcpln logs. kafka_ui(Provectus Kafka UI) is deprecated and off by default; usekafbat_ui.- Changing broker values restarts the brokers; schedule upgrades accordingly.
- Set
sha256on every Kafka Connect plugin artifact: the plugin downloader does not verify TLS certificates.