Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
c65a16c
add shared crate with shared constants and client security enum
labrenbe Oct 13, 2026
41db2c7
add KafkaTopic CRD
labrenbe Oct 13, 2026
fe5203f
add necessary envs and volumes to agent pod
labrenbe Oct 14, 2026
9ba595d
reject zookeeper-mode when platformAccess is configured
labrenbe Oct 16, 2026
2c730ca
add config to agent: bootstrap servers from discovery cm, security mo…
labrenbe Oct 15, 2026
5463640
add stackable-kafka-adminto workspace dependencies
labrenbe Oct 16, 2026
6a8e1b9
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 16, 2026
e7d4248
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 16, 2026
c02eeb5
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 16, 2026
559fb04
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 16, 2026
248c918
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 20, 2026
e61fcdb
add kafka controller
labrenbe Oct 21, 2026
ccf2fff
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 21, 2026
81a49a1
wip: add kuttl tests
labrenbe Oct 23, 2026
ce1c926
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 23, 2026
bdc7e9f
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 26, 2026
f094a23
update the CRD to reflect operator-rs changes and the CRD decision
labrenbe Oct 26, 2026
d028aa2
rewrite the topic agent for the new KafkaTopic CRD
labrenbe Oct 26, 2026
bed3c7f
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 27, 2026
4994c9f
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 27, 2026
624bebd
add topic_controller to operator for cleaning up after agents
labrenbe Oct 27, 2026
6ae37ee
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 27, 2026
ac90b9f
read bootstrap servers from KAFKA_BOOTSTRAP_SERVERS in the agent and …
labrenbe Oct 27, 2026
3fb16de
skip planning while the KafkaTopic reconciliation is paused
labrenbe Oct 27, 2026
b3e247d
watch only the KafkaTopics of the agent's cluster via a field selector
labrenbe Oct 27, 2026
6b93004
reject topic names starting with __ (internal topics)
labrenbe Oct 27, 2026
57b853b
fix topic name immutability validation
labrenbe Oct 27, 2026
5941693
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 27, 2026
41f8b37
change controller and CRD to use status.config without source
labrenbe Oct 28, 2026
f1946f7
add grace period before operator takes over topic status
labrenbe Oct 28, 2026
8b8934c
add docs and changelog entry
labrenbe Oct 28, 2026
2e92a9e
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 28, 2026
3fab703
regenerate nix
labrenbe Oct 28, 2026
0c7956b
test correct namespace deletion
labrenbe Oct 28, 2026
0d1d0ac
add OPA to management access test
labrenbe Oct 28, 2026
e780967
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 28, 2026
7da2ba8
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 28, 2026
f539947
remove OPA from docs and test
labrenbe Oct 28, 2026
0f39003
write status if failing during finalizer reconciliation
labrenbe Oct 28, 2026
d4cb53a
improve docs on deletion
labrenbe Oct 28, 2026
c0f9338
report a stopped Kafka cluster as unavailable
labrenbe Oct 28, 2026
08c6a41
derive the topic configs from the applied changes
labrenbe Oct 28, 2026
b5be3c1
add pull secret to docs
labrenbe Oct 28, 2026
77eb95a
remove the unreachable throttle filter from the planned config changes
labrenbe Oct 28, 2026
af91710
clarify the test-support feature of the shared crate
labrenbe Oct 28, 2026
45b8a8c
document that the admin client serializes the Kafka requests
labrenbe Oct 28, 2026
2229bec
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 28, 2026
c4422a6
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 30, 2026
c475bdb
trim kuttl tests
labrenbe Oct 30, 2026
45d37f3
add keep environment util to topic test
labrenbe Oct 30, 2026
bdf8353
Merge branch 'feat/kafka-admin' into feat/kafka-topic
labrenbe Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file.
- Support for Kafka 4.3.1 ([#1022]).
- Add `/ready` endpoint to the operator Deployment, which reports the CRD installation status ([#1029]).
- Brokers now have a default affinity to the OPA Pods when OPA authorization is configured ([#1035]).
- Add management access via `spec.clusterConfig.managementAccess`. When enabled, the operator
deploys an agent per KafkaCluster, which authenticates anonymously or with a TLS client
certificate ([#1028]).
- Add the KafkaTopic CRD to manage topics declaratively. The agent creates and adopts topics,
replaces their configs with `configOverrides`, increases their partitions and optionally deletes
them. The operator removes the finalizers of KafkaTopics whose KafkaCluster is deleted ([#1050]).

### Changed

Expand Down Expand Up @@ -56,6 +62,9 @@ All notable changes to this project will be documented in this file.
- Support Vector 0.58.0 ([#1039], [#1044], [#1046]).
- test: Update OPA to 1.20.2 in integration tests and docs example ([#1042]).
- The operator Deployment runs with a restricted security context and a read-only root filesystem, so it can be deployed into namespaces that enforce the `restricted` Pod Security Standard ([#1049]).
- The `/ready` endpoint of the operator now also waits for the KafkaTopic CRD. If the CRDs are not
maintained by the operator (`maintenance.customResourceDefinitions.maintain: false`), install the
KafkaTopic CRD together with the KafkaCluster CRD ([#1050]).

### Fixed

Expand Down Expand Up @@ -92,6 +101,7 @@ All notable changes to this project will be documented in this file.
[#1021]: https://github.com/stackabletech/kafka-operator/pull/1021
[#1022]: https://github.com/stackabletech/kafka-operator/pull/1022
[#1024]: https://github.com/stackabletech/kafka-operator/pull/1024
[#1028]: https://github.com/stackabletech/kafka-operator/pull/1028
[#1029]: https://github.com/stackabletech/kafka-operator/pull/1029
[#1034]: https://github.com/stackabletech/kafka-operator/pull/1034
[#1035]: https://github.com/stackabletech/kafka-operator/pull/1035
Expand All @@ -103,6 +113,7 @@ All notable changes to this project will be documented in this file.
[#1046]: https://github.com/stackabletech/kafka-operator/pull/1046
[#1047]: https://github.com/stackabletech/kafka-operator/pull/1047
[#1049]: https://github.com/stackabletech/kafka-operator/pull/1049
[#1050]: https://github.com/stackabletech/kafka-operator/pull/1050

## [26.7.0] - 2026-07-21

Expand Down
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 59 additions & 1 deletion Cargo.nix

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ repository = "https://github.com/stackabletech/kafka-operator"

[workspace.dependencies]
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", branch = "feat/platform-access", features = ["agent", "crds", "webhook"] }
stackable-kafka-admin = { path = "rust/kafka-admin" }
stackable-kafka-shared = { path = "rust/shared" }

anyhow = "1.0"
Expand All @@ -22,6 +23,7 @@ const_format = "0.2"
futures = "0.3"
indoc = "2.0"
kafka-protocol = { version = "0.18", default-features = false, features = ["broker", "client"] }
regex = "1.13"
rstest = "0.26"
rustls = { version = "0.23", default-features = false, features = ["logging", "ring", "std", "tls12"] }
semver = "1.0"
Expand Down
5 changes: 5 additions & 0 deletions deploy/helm/kafka-operator/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ annotations:
name: kafkaclusters.kafka.stackable.tech
displayName: KafkaCluster
description: A Kafka cluster stacklet. This resource is managed by the Stackable operator for Apache Kafka.
- kind: KafkaTopic
version: v1alpha1
name: kafkatopics.kafka.stackable.tech
displayName: KafkaTopic
description: A Kafka topic, created and updated by the agent of the referenced Kafka cluster.
24 changes: 24 additions & 0 deletions deploy/helm/kafka-operator/templates/clusterrole-agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@ metadata:
labels:
{{- include "kafka-operator.labels" . | nindent 4 }}
rules:
# KafkaTopics of the agent's cluster: watched, and their finalizer added and removed.
- apiGroups:
- {{ include "kafka-operator.name" . }}.stackable.tech
resources:
- kafkatopics
verbs:
- get
- list
- watch
- patch
- apiGroups:
- {{ include "kafka-operator.name" . }}.stackable.tech
resources:
- kafkatopics/status
verbs:
- patch
# Required to report reconciliation errors as events on the KafkaTopic objects.
- apiGroups:
- events.k8s.io
resources:
- events
verbs:
- create
- patch
{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }}
# On OpenShift, the agent pod must be allowed to use the nonroot-v2 SCC
- apiGroups:
Expand Down
18 changes: 18 additions & 0 deletions deploy/helm/kafka-operator/templates/clusterrole-operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ rules:
- {{ include "kafka-operator.name" . }}clusters/status
verbs:
- patch
# KafkaTopics: watched to take over while no agent is available, and their finalizer removed
# once the KafkaCluster is gone.
- apiGroups:
- {{ include "kafka-operator.name" . }}.stackable.tech
resources:
- kafkatopics
verbs:
- get
- list
- watch
- patch
# Status subresource: conditions set while the agent is unavailable.
- apiGroups:
- {{ include "kafka-operator.name" . }}.stackable.tech
resources:
- kafkatopics/status
verbs:
- patch
# Read authentication class configuration referenced in the KafkaCluster spec.
- apiGroups:
- authentication.stackable.tech
Expand Down
2 changes: 2 additions & 0 deletions docs/modules/kafka/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:github: https://github.com/stackabletech/kafka-operator/
:crd: {crd-ref}{crd-ref-release}&operator=kafka-operator
:crd-kafkacluster: {crd-ref}/kafka.stackable.tech/v1alpha1/kafkacluster{crd-ref-release}
:crd-kafkatopic: {crd-ref}/kafka.stackable.tech/v1alpha1/kafkatopic{crd-ref-release}
:feature-tracker: https://features.stackable.tech/unified
:metadata-quorum: https://cwiki.apache.org/confluence/display/KAFKA/KIP-500%3A+Replace+ZooKeeper+with+a+Self-Managed+Metadata+Quorum
:pegelonline: https://www.pegelonline.wsv.de/webservice/ueberblick
Expand Down Expand Up @@ -75,3 +76,4 @@ include::partial$supported-versions.adoc[]
* The {github}[kafka-operator {external-link-icon}^] GitHub repository
* The operator feature overview in the {feature-tracker}[feature tracker {external-link-icon}^]
* The {crd-kafkacluster}[KafkaCluster {external-link-icon}^] CRD documentation
* The {crd-kafkatopic}[KafkaTopic {external-link-icon}^] CRD documentation
127 changes: 127 additions & 0 deletions docs/modules/kafka/pages/usage-guide/management-access.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
= Management access
:description: Let the Stackable Operator for Apache Kafka manage resources inside a Kafka cluster, such as topics, through a per-cluster agent.

Management access allows the Stackable Data Platform (SDP) to manage resources inside an Apache Kafka cluster, such as xref:usage-guide/topics.adoc[topics].

== Agents

The agent is an optional Deployment next to the Kafka cluster that manages resources inside Kafka, such as topics.
The operator deploys it when management access is enabled.

The agent runs the image of the operator, pulled with the pull secrets of the Kafka image in `spec.image.pullSecrets`.
If the operator image is not public, these pull secrets must grant access to its registry as well, or the Deployment of the agent gets its own pull secrets with <<agent-resources,object overrides>>.

== Limitations

Management access is not available for all clusters:

* Clusters that use ZooKeeper are not supported, only clusters in xref:usage-guide/kraft-controller.adoc[KRaft mode].
* Clusters with Kerberos authentication are not supported.

== Configuration

Enable management access with `spec.clusterConfig.managementAccess` and choose how the agent authenticates to Kafka:

[source,yaml]
----
apiVersion: kafka.stackable.tech/v1alpha1
kind: KafkaCluster
metadata:
name: simple-kafka
spec:
image:
productVersion: 4.3.1
clusterConfig:
metadataManager: KRaft
tls:
serverSecretClass: tls
authentication:
- authenticationClass: kafka-client-tls
managementAccess:
enabled: true # <1>
authentication:
userProvided:
tls:
secretClassName: kafka-client-auth-secret # <2>
controllers:
roleGroups:
default:
replicas: 3
brokers:
roleGroups:
default:
replicas: 3
----
<1> Deploys the agent. Setting it to `false` removes the agent again.
<2> The SecretClass that provisions the client certificate of the agent, here the same SecretClass that the brokers use to verify client certificates, see xref:usage-guide/security.adoc[Security].

The agent supports the following authentication methods:

`anonymous: {}`:: The agent connects without a client certificate.
This is only possible if the cluster does not require client authentication.
`tls.secretClassName`:: A client certificate provisioned by the xref:secret-operator:index.adoc[Secret Operator] from the given SecretClass.
`tls.secretName`:: A static Secret holding the client certificate in the keys `tls.crt` and `tls.key` (PEM), for example a Secret of type `kubernetes.io/tls`.

The agent verifies the brokers with the CA of the SecretClass used by the client listener, that is `spec.clusterConfig.tls.serverSecretClass` or the `clientCertSecretClass` of the TLS AuthenticationClass.

== Authorization

The principal of the agent must be allowed to manage topics in Kafka.
The principal is derived from the subject of the client certificate.
The agent needs the following permissions:

[cols="2,3", options="header"]
|===
| Kafka API | Operation

| Metadata | `DESCRIBE` on the topic
| CreateTopics | `CREATE` on the cluster or the topic, and `DESCRIBE_CONFIGS` on the topic
| CreatePartitions | `ALTER` on the topic
| DescribeConfigs | `DESCRIBE_CONFIGS` on the topic
| IncrementalAlterConfigs | `ALTER_CONFIGS` on the topic
| DeleteTopics | `DELETE` on the topic
| ListPartitionReassignments | `DESCRIBE` on the cluster
|===

NOTE: Without `DESCRIBE_CONFIGS`, Kafka still creates a topic, but the agent cannot observe it.
The KafkaTopic then reports `KafkaRejected`.

== Network

The agent connects to the headless Services of the broker role groups, which resolve to the broker Pods.
The traffic of the agent therefore stays within the Kubernetes cluster, regardless of the xref:usage-guide/listenerclass.adoc[ListenerClasses] of the cluster.

[[agent-resources]]
== Agent resources

The operator creates the following resources for the agent, named after the KafkaCluster:

* A Deployment `<cluster>-agent` with a single replica, limited to 500m CPU and 128Mi memory by default.
* A ServiceAccount `<cluster>-agent`.
* A RoleBinding `<cluster>-agent`, which binds the ClusterRole `kafka-agent-clusterrole` deployed by the Helm chart.

The Deployment can be adjusted with xref:concepts:overrides.adoc#object-overrides[object overrides], for example to change the resources of the agent:

[source,yaml]
----
spec:
objectOverrides:
- apiVersion: apps/v1
kind: Deployment
metadata:
name: simple-kafka-agent
spec:
template:
spec:
containers:
- name: agent
resources:
limits:
memory: 256Mi
----

== Disabling management access

Setting `enabled` to `false` or removing `managementAccess` removes the agent.
The KafkaTopics and the topics in Kafka stay as they are.
While no agent is available, the operator reports `AgentUnavailable` in the conditions of the KafkaTopics of the cluster, see xref:usage-guide/topics.adoc#deletion[Deletion] for the effect on deleted KafkaTopics.
Loading
Loading