Kubernetes
Deploy a Danube messaging cluster on Kubernetes and verify it with a producer and consumer. This guide uses a local Kind cluster for simplicity, but the same Helm charts work on any Kubernetes cluster (EKS, GKE, AKS, etc.).
Overview
Section titled “Overview”A Danube deployment consists of two Helm charts:
| Chart | What it deploys |
|---|---|
| danube-envoy | An Envoy gRPC proxy that routes client requests to the correct broker |
| danube-core | Danube brokers (StatefulSet) with embedded Raft consensus, and Prometheus for metrics |
The proxy is installed first because the brokers need to know its external address at startup. This address is called the connectUrl, it tells clients how to reach the cluster from outside Kubernetes.
Prerequisites
Section titled “Prerequisites”- Docker
- Kind (for local testing)
- kubectl
- Helm 3.0+
- danube-cli (for testing)
Deploy Danube
Section titled “Deploy Danube”-
Create a Kubernetes cluster (skip if you already have one)
Create Kind cluster kind create clusterkubectl cluster-info --context kind-kind -
Add the Danube Helm repository
Terminal window helm repo add danube https://danube-messaging.github.io/danube_helmhelm repo updateThis makes two charts available:
danube/danube-envoyanddanube/danube-core. -
Install the Envoy proxy
The Envoy proxy is the single entry point for all client traffic. It handles gRPC routing so that each request reaches the broker that owns the target topic.
Terminal window kubectl create namespace danubehelm install danube-envoy danube/danube-envoy -n danubeWait for the proxy pod to be ready:
Terminal window kubectl get pods -n danube -w -
Discover the proxy address
The proxy service is exposed as a Kubernetes NodePort:
Get proxy address PROXY_PORT=$(kubectl get svc danube-envoy -n danube \-o jsonpath='{.spec.ports[?(@.name=="grpc")].nodePort}')NODE_IP=$(kubectl get nodes \-o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')echo "Proxy address: ${NODE_IP}:${PROXY_PORT}"Save this address for the next step and for connecting clients.
-
Install Danube core
Create a ConfigMap from the broker config, then install the chart with the proxy address:
Create ConfigMap kubectl create configmap danube-broker-config \--from-file=danube_broker.yml=danube_broker.yml \-n danubeInstall Danube core helm install danube-core danube/danube-core -n danube \-f values-minimal.yaml \--set broker.externalAccess.connectUrl="${NODE_IP}:${PROXY_PORT}"This deploys:
- 3 broker pods (StatefulSet) with persistent storage and embedded Raft consensus
- 1 Prometheus pod for metrics collection
Wait for all pods to be ready:
Terminal window kubectl get pods -n danube -wExpected output:
Expected pods NAME READY STATUS AGEdanube-core-broker-0 1/1 Running 2mdanube-core-broker-1 1/1 Running 2mdanube-core-broker-2 1/1 Running 2mdanube-core-prometheus-xxxxxxxxx 1/1 Running 3mdanube-envoy-xxxxxxxxx 1/1 Running 5m -
Verify the deployment
Check that the brokers registered in proxy mode:
Terminal window kubectl logs danube-core-broker-0 -n danube | grep "broker registered"You should see each broker reporting a unique
broker_url(its internal DNS name) and a sharedconnect_url(the Envoy proxy address).
Produce and Consume Messages
Section titled “Produce and Consume Messages”Use danube-cli to send messages through the proxy:
danube-cli produce \ -s http://${NODE_IP}:${PROXY_PORT} \ -t /default/test_topic \ -m "Hello from Danube" -c 5danube-cli consume \ -s http://${NODE_IP}:${PROXY_PORT} \ -t /default/test_topic \ -m test_subNow produce more messages in Terminal 1, the consumer receives them in real time.
How Proxy Mode Works
Section titled “How Proxy Mode Works”In a multi-broker cluster, each topic is owned by a specific broker. When a client connects, it needs to reach the right broker for its topic.
-
The client connects to the Envoy proxy (the
connectUrl) -
It sends a topic lookup request, which Envoy round-robins to any broker
-
The broker responds with its internal address (
broker_url) for that topic -
On subsequent requests, the client includes an
x-danube-broker-urlgRPC metadata header with the target broker’s internal address -
Envoy’s Dynamic Forward Proxy reads this header, resolves the broker’s internal DNS name, and routes the request directly to the correct pod
This means clients only need a single external address (the proxy) regardless of how many brokers are in the cluster.
Inspect Cluster State
Section titled “Inspect Cluster State”# Port-forward the admin API of any brokerkubectl port-forward danube-core-broker-0 50051:50051 -n danube
# In another terminaldanube-admin cluster statusdanube-admin brokers listAccess Prometheus
Section titled “Access Prometheus”kubectl port-forward svc/danube-core-prometheus 9090:9090 -n danubeOpen http://localhost:9090 in your browser to query Danube metrics.
Cleanup
Section titled “Cleanup”helm uninstall danube-core -n danubehelm uninstall danube-envoy -n danubekubectl delete namespace danubekind delete clusterThis removes all Kubernetes resources including PersistentVolumeClaims (since the namespace is deleted).