# Kubernetes (Helm) (/configure/kubernetes)



<Callout type="info">
  **Install KubeMQ first** → [Helm install](/deploy/kubernetes-helm).
  This page covers how to *configure* a KubeMQ cluster.
</Callout>

On Kubernetes, KubeMQ runs through the **operator**. You describe the server with a
`KubemqCluster` custom resource, the operator reconciles it into a StatefulSet, Services,
and configuration, and the **Helm charts** render that resource from your `values.yaml`.
Because the chart writes values straight into the CR, a Helm value path equals the
`KubemqCluster` `spec.*` path with the leading `spec.` removed (`spec.grpc.port` →
`grpc.port`).

This guide is the single source of truth for **complete, runnable** Helm and CRD
configurations. The [Configuration overview](/configure) and the
[reference pages](/configure/reference) show minimal single-setting snippets and
link here.

## Configure with values.yaml [#configure-with-valuesyaml]

For anything beyond the license key, supply a `values.yaml` file. Each value maps **1:1**
to a `KubemqCluster` `spec.*` field — the chart renders your values verbatim into the CR
spec, so there is no separate Helm schema to learn. A complete `values.yaml`:

```yaml title="values.yaml"
# Replace with your license key
key: YOUR_LICENSE_KEY

# High availability: 3 replicas (set standalone: true for a single node)
replicas: 3
standalone: false

# Persistent store
volume:
  size: 20Gi
  storageClass: fast-ssd

# Interfaces — .port moves the listener + Service port together
grpc:
  port: 50000
  expose: LoadBalancer

# REST is on by default; MCP / A2A / CloudEvents ride the REST HTTP port
# (disabled: false is the default — shown here only to be explicit)
rest:
  disabled: false
  port: 9090
  expose: ClusterIP

api:
  port: 8080
  expose: LoadBalancer

# Store limits and retention — enforced on the `legacy` engine only (see callout below)
store:
  messagesRetentionMinutes: 1440
  maxChannels: 0

# Pod resources
resources:
  requestsCpu: "2"
  requestsMemory: 4Gi
  limitsCpu: "4"
  limitsMemory: 8Gi
```

<Callout type="warn">
  **`store.messagesRetentionMinutes` and the other `store.max*` limits are enforced by the
  `legacy` engine only — and a new cluster on a clean store comes up on `next`.** So the
  `1440` above does nothing on a default install: native Events Store and Queues channels
  have no age, size, or count cap and grow until the disk does. Size by `spec.volume.size`,
  or use Kafka topic channels where age eviction matters. See
  [Native retention scope](/configure/reference/storage-engines#native-retention-scope).
</Callout>

Install (or upgrade) the cluster with the file:

```bash title="Terminal"
helm install --wait -n kubemq kubemq-cluster kubemq-charts/kubemq-cluster -f values.yaml
```

The same configuration as a `KubemqCluster` CR — apply it directly with `kubectl apply -f`
if you manage the resource yourself rather than through Helm:

```yaml title="kubemqcluster.yaml"
apiVersion: core.k8s.kubemq.io/v1beta1
kind: KubemqCluster
metadata:
  name: kubemq-cluster
  namespace: kubemq
spec:
  key: YOUR_LICENSE_KEY
  replicas: 3
  standalone: false
  volume:
    size: 20Gi
    storageClass: fast-ssd
  grpc:
    port: 50000
    expose: LoadBalancer
  rest:
    disabled: false
    port: 9090
    expose: ClusterIP
  api:
    port: 8080
    expose: LoadBalancer
  store:
    messagesRetentionMinutes: 1440
    maxChannels: 0
  resources:
    requestsCpu: "2"
    requestsMemory: 4Gi
    limitsCpu: "4"
    limitsMemory: 8Gi
```

<Callout type="warn">
  **REST is enabled by default on the chart.** The cluster chart ships `rest.disabled: false`
  (`spec.rest.disabled: false`), so REST — and the MCP, A2A, and CloudEvents connectors that
  ride the **REST HTTP port** — are reachable out of the box. `disabled` is an **opt-out**
  boolean: omit the key entirely to leave REST on; set `rest.disabled: true` only to turn REST
  off, which also takes MCP, A2A, and CloudEvents offline.
</Callout>

<Callout type="warn">
  **Version floor.** The first-class `spec.telemetry.*`, `spec.audit.*`, and `spec.http.*`
  fields, and the aligned `spec.authentication.*` fields, are present throughout the current
  GA chart line — `kubemq-crds` and `kubemq-cluster` **3.x** (latest **3.2.0**) with
  `kubemq-controller` **2.x** (operator **v2.3.0**). Anything older than the 3.0.0 / 2.0.0 GA
  release predates this reference and will **reject** these fields: upgrade to the current
  line rather than trying to work out which pre-GA build carried which field.
</Callout>

<Callout type="warn">
  **On Kubernetes, `.port` moves everything together.** For `grpc`, `rest`, and `api`, setting
  `spec.<iface>.port` makes the operator emit the matching listener env var
  (`CONNECTORS_GRPC_PORT` / `CONNECTORS_REST_PORT` / `API_PORT`) **and** set the Kubernetes
  `Service` `port`/`targetPort` **and** the container port — the in-pod listener and the
  `Service` port move as one. This matches Docker, where the same `*_PORT` setting moves the
  actual listener (which you then publish with `-p`) — see the
  [Docker guide](/configure/docker).
</Callout>

## Single-node vs HA [#single-node-vs-ha]

The same chart runs both topologies — the difference is `replicas`.

<Tabs items="[&#x22;Single-node&#x22;, &#x22;High availability&#x22;]">
  <Tab value="Single-node">
    ```yaml title="values.yaml"
    key: YOUR_LICENSE_KEY
    replicas: 1
    standalone: true
    ```
  </Tab>

  <Tab value="High availability">
    ```yaml title="values.yaml"
    key: YOUR_LICENSE_KEY
    replicas: 3
    standalone: false
    ```
  </Tab>
</Tabs>

A single replica (or `standalone: true`) runs one non-clustered node — the equivalent of
one Docker container. Three or more replicas give you high availability; the operator wires
up clustering across the pods. For the full deployment and HA reference, see
[Deployment & HA](/configure/reference/deployment).

## Expose interfaces [#expose-interfaces]

Each interface (`grpc`, `rest`, `api`) is fronted by its own Kubernetes `Service`. Control
the `Service` type with `expose` and the published node port with `nodePort`:

```yaml title="values.yaml"
grpc:
  expose: LoadBalancer    # ClusterIP | NodePort | LoadBalancer
api:
  expose: NodePort
  nodePort: 32080         # only used with NodePort
```

* **`ClusterIP`** — reachable only inside the cluster (the default for internal-only
  interfaces).
* **`NodePort`** — published on every node at `nodePort`; useful for direct access without a
  cloud load balancer.
* **`LoadBalancer`** — provisions an external load balancer (cloud environments).

`nodePort` applies only when `expose: NodePort`. On Docker there is no `Service` — publish
ports with `-p` instead (see the [Docker guide](/configure/docker)).

## Zero-config Kafka [#zero-config-kafka]

On a **fresh** cluster, enabling the Kafka connector is the whole story — no separate
engine setting to manage:

```yaml title="values.yaml"
key: YOUR_LICENSE_KEY
replicas: 3
standalone: false

kafka:
  enabled: true
```

With the store empty and `store.engine` left unset, the operator auto-selects the `next`
persistence engine at first boot — see
[Storage Engines → Zero-config engine selection](/configure/reference/storage-engines#zero-config-engine-selection)
for the full selection rules.

<Callout type="warn">
  **The default `replicas: 3` means Kafka producers should use `acks>=1` for durable
  writes.** The `next` engine acknowledges a publish only after it's quorum-replicated
  across raft peers, so an `acks=0` producer won't see a stalled or leaderless partition.
</Callout>

External reachability needs `spec.kafka.expose` plus an advertised host/port pair — see
[Connectors → Kafka](/configure/reference/connectors#kafka) for the full
listener/TLS/SAN details.

## Configure by domain [#configure-by-domain]

Every server setting — with its type, default, valid values, and both per-target columns —
lives in the domain reference pages.

<Cards>
  <Card title="Core & Licensing" href="/configure/reference/core" description="License key, log level, and host/server identity." />

  <Card title="Interfaces" href="/configure/reference/interfaces" description="gRPC, REST/WebSocket, the management API, and the shared HTTP server with CORS." />

  <Card title="Connectors" href="/configure/reference/connectors" description="MCP, A2A (agents), CloudEvents, MQTT, AMQP 0.9.1, AMQP 1.0, STOMP, Kafka, AWS, and GCP Pub/Sub." />

  <Card title="Storage & Queues" href="/configure/reference/storage-queues" description="Persistent store limits and retention plus queue delivery defaults and ceilings." />

  <Card title="Storage Engines" href="/configure/reference/storage-engines" description="The two persistence engines — legacy and next — durability, mode isolation, compaction, and next-engine clustering." />

  <Card title="Security" href="/configure/reference/security" description="JWT and OIDC authentication, policy-based authorization, and TLS/mTLS." />

  <Card title="Observability" href="/configure/reference/observability" description="OpenTelemetry traces and metrics, audit logging, and notifications." />

  <Card title="Deployment & High Availability" href="/configure/reference/deployment" description="Kubernetes packaging — image, volume, resources, health, scheduling, Service exposure — plus replicas and standalone mode." />

  <Card title="Advanced" href="/configure/reference/advanced" description="Message-broker engine, runtime tuning, and routing — config.yaml-only advanced knobs." />
</Cards>

## Verify [#verify]

Confirm the operator has reconciled the cluster and the pods are ready.

Check the `KubemqCluster` resource and its status:

```bash title="Terminal"
kubectl get kubemqcluster -n kubemq
```

Inspect the full status, including the reconcile phase and any conditions:

```bash title="Terminal"
kubectl describe kubemqcluster kubemq-cluster -n kubemq
```

Confirm the server pods are running:

```bash title="Terminal"
kubectl get pods -n kubemq
```

To reach the dashboard, port-forward the API service and open
`http://localhost:8080`:

```bash title="Terminal"
kubectl port-forward -n kubemq svc/kubemq-cluster 8080:8080
```

## Related [#related]

* [Configuration overview](/configure) — the two targets and the config model.
* [Docker (single-node)](/configure/docker) — the local / dev target.
* [Deployment & HA reference](/configure/reference/deployment) — packaging, replicas, and exposure in full.
* [Install with Helm](/deploy/kubernetes-helm) — the step-by-step install guide.
