OpenMCF logoOpenMCF

Loading...

Kubernetes NATS

Deploys a NATS messaging cluster on Kubernetes using the official NATS Helm chart, with optional JetStream persistence, authentication (bearer-token or basic-auth), TLS encryption, external ingress via LoadBalancer, and declarative stream/consumer management through the NACK JetStream controller.

What Gets Created

When you deploy a KubernetesNats resource, OpenMCF provisions:

  • Namespace — created only when createNamespace is true
  • Helm Release (NATS) — deploys a NATS server cluster via the official NATS Helm chart with configurable replicas, JetStream file storage, resource limits, and disk size
  • Auth Secret — a Kubernetes Secret storing a randomly generated bearer token or basic-auth credentials, created when authentication is enabled
  • No-Auth User Secret — an additional Kubernetes Secret for the unauthenticated user, created when basic-auth is enabled with noAuthUser.enabled set to true
  • TLS Secret — a self-signed certificate (RSA 2048-bit, 5-year validity) stored as a kubernetes.io/tls Secret, created when tlsEnabled is true
  • LoadBalancer Service — created when ingress.enabled is true, exposes NATS on port 4222 with an external-dns.alpha.kubernetes.io/hostname annotation for automatic DNS record creation
  • NACK CRDs — JetStream custom resource definitions fetched from the official NACK GitHub release, deployed when the NACK controller is enabled
  • NACK Controller Helm Release — deploys the NATS Controllers for Kubernetes operator, which reconciles JetStream Stream and Consumer CRDs to the NATS server
  • JetStream Stream CRs — Kubernetes custom resources representing JetStream streams, each with configurable subjects, storage, retention, and limits
  • JetStream Consumer CRs — Kubernetes custom resources representing JetStream consumers attached to streams, with configurable delivery, acknowledgment, and replay policies

Prerequisites

  • Kubernetes credentials configured via environment variables or OpenMCF provider config
  • A Kubernetes namespace that already exists, or set createNamespace to true
  • A StorageClass available in the cluster if JetStream persistence is enabled (most managed Kubernetes clusters provide a default)
  • external-dns running in the cluster if enabling ingress with a hostname

Quick Start

Create a file nats.yaml:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesNats
metadata:
  name: my-nats
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.KubernetesNats.my-nats
spec:
  namespace: messaging
  createNamespace: true

Deploy:

openmcf apply -f nats.yaml

This creates a single-replica NATS server with JetStream enabled, a 10Gi PersistentVolumeClaim, default resource limits (1000m CPU, 2Gi memory), and the nats-box utility pod for debugging.

Configuration Reference

Required Fields

FieldTypeDescriptionValidation
namespacestringKubernetes namespace for the NATS deployment. Can reference a KubernetesNamespace resource via valueFrom.Required

Optional Fields

FieldTypeDefaultDescription
targetCluster.clusterKindenum—Kubernetes cluster kind. Valid values: AwsEksCluster, GcpGkeCluster, AzureAksCluster, DigitalOceanKubernetesCluster, CivoKubernetesCluster.
targetCluster.clusterNamestring—Name of the target Kubernetes cluster in the same environment.
createNamespaceboolfalseWhen true, creates the namespace before deploying resources.
serverContainer.replicasint321Number of NATS server replicas. Use an odd value for quorum in clustered mode. Must be greater than 0.
serverContainer.resources.limits.cpustring1000mMaximum CPU allocation for each NATS pod.
serverContainer.resources.limits.memorystring2GiMaximum memory allocation for each NATS pod.
serverContainer.resources.requests.cpustring100mMinimum guaranteed CPU for each NATS pod.
serverContainer.resources.requests.memorystring256MiMinimum guaranteed memory for each NATS pod.
serverContainer.diskSizestring10GiPVC size for JetStream file storage. Must be a valid Kubernetes quantity (e.g., 1Gi, 10Gi). Recommended default: 1Gi.
disableJetStreamboolfalseWhen true, disables JetStream persistence entirely. No file store PVC is created.
auth.enabledboolfalseEnables authentication for the NATS cluster.
auth.schemeenum—Authentication scheme. Valid values: bearer_token, basic_auth.
auth.noAuthUser.enabledboolfalseEnables an unauthenticated user alongside authenticated users. Only applies when auth.scheme is basic_auth.
auth.noAuthUser.publishSubjectsstring[]—Subjects the unauthenticated user may publish to. At least one subject must be specified when noAuthUser.enabled is true.
tlsEnabledboolfalseGenerates a self-signed TLS certificate and configures NATS to use it.
ingress.enabledboolfalseCreates a LoadBalancer Service exposing NATS on port 4222 with external-dns annotations.
ingress.hostnamestring—Hostname for external access (e.g., nats.example.com). Configured automatically via external-dns. Required when ingress.enabled is true.
disableNatsBoxboolfalseWhen true, skips deployment of the nats-box utility pod.
nackController.enabledboolfalseDeploys the NACK JetStream controller for managing streams and consumers via Kubernetes CRDs.
nackController.enableControlLoopboolfalseEnables control-loop mode for the NACK controller. Required for KeyValue and ObjectStore support.
nackController.helmChartVersionstring0.31.1NACK Helm chart version.
nackController.appVersionstring0.21.1NACK app version (GitHub release tag). Used for fetching CRDs. Differs from chart version.
streams[].namestring—Unique stream name. 1-255 characters, alphanumeric with -, _, . allowed.
streams[].subjectsstring[]—Subjects the stream captures. Supports wildcards (e.g., orders.*, events.>). At least one required.
streams[].storageenummemoryStorage backend: file (persistent) or memory (ephemeral).
streams[].replicasint32—Number of stream replicas (1-5). Odd values recommended for quorum.
streams[].retentionenumlimitsRetention policy: limits, interest, or workqueue.
streams[].maxAgestring—Maximum message age (e.g., 24h, 7d). Empty for unlimited.
streams[].maxBytesint64—Maximum stream size in bytes. -1 for unlimited.
streams[].maxMsgsint64—Maximum number of messages. -1 for unlimited.
streams[].maxMsgSizeint32—Maximum message size in bytes. -1 for unlimited.
streams[].maxConsumersint32—Maximum number of consumers. -1 for unlimited.
streams[].discardenumoldDiscard policy when limits are reached: old or new_msgs.
streams[].descriptionstring—Description of the stream.
streams[].consumers[].durableNamestring—Durable consumer name. Must be unique within the stream. 1-255 characters.
streams[].consumers[].deliverPolicyenumallDelivery policy: all, last, or new_msgs.
streams[].consumers[].ackPolicyenumnoneAcknowledgment policy: none, all, or explicit.
streams[].consumers[].filterSubjectstring—Subject filter with wildcard support. Only matching messages are delivered.
streams[].consumers[].deliverSubjectstring—Deliver subject for push-based consumers. Omit for pull-based.
streams[].consumers[].deliverGroupstring—Queue group name for load balancing across multiple consumer instances.
streams[].consumers[].maxAckPendingint32—Maximum number of unacknowledged messages.
streams[].consumers[].maxDeliverint32—Maximum delivery attempts. -1 for unlimited.
streams[].consumers[].ackWaitstring—Time to wait for acknowledgment (e.g., 30s, 1m).
streams[].consumers[].replayPolicyenuminstantReplay policy: original (original rate) or instant (as fast as possible).
streams[].consumers[].descriptionstring—Description of the consumer.
natsHelmChartVersionstring2.12.3NATS Helm chart version. Available versions: helm search repo nats/nats --versions.

Examples

Development NATS with Defaults

A single-replica NATS server for development with JetStream enabled and default settings:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesNats
metadata:
  name: dev-nats
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.KubernetesNats.dev-nats
spec:
  namespace: dev
  createNamespace: true
  serverContainer:
    replicas: 1
    resources:
      limits:
        cpu: "500m"
        memory: "512Mi"
      requests:
        cpu: "50m"
        memory: "128Mi"
    diskSize: "1Gi"

Production Cluster with Authentication and TLS

A three-node NATS cluster with basic-auth, TLS encryption, and external access:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesNats
metadata:
  name: prod-nats
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.KubernetesNats.prod-nats
spec:
  namespace: messaging
  serverContainer:
    replicas: 3
    resources:
      limits:
        cpu: "2000m"
        memory: "4Gi"
      requests:
        cpu: "500m"
        memory: "1Gi"
    diskSize: "50Gi"
  auth:
    enabled: true
    scheme: basic_auth
  tlsEnabled: true
  ingress:
    enabled: true
    hostname: nats.example.com

Event-Driven Architecture with Streams and Consumers

A NATS cluster with the NACK controller managing JetStream streams and consumers declaratively:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesNats
metadata:
  name: event-bus
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.KubernetesNats.event-bus
spec:
  namespace: events
  createNamespace: true
  serverContainer:
    replicas: 3
    resources:
      limits:
        cpu: "2000m"
        memory: "4Gi"
      requests:
        cpu: "500m"
        memory: "1Gi"
    diskSize: "100Gi"
  auth:
    enabled: true
    scheme: basic_auth
  nackController:
    enabled: true
    enableControlLoop: true
  streams:
    - name: ORDERS
      subjects:
        - "orders.>"
      storage: file
      replicas: 3
      retention: limits
      maxAge: "7d"
      maxBytes: -1
      discard: old
      consumers:
        - durableName: order-processor
          deliverPolicy: all
          ackPolicy: explicit
          filterSubject: "orders.created"
          maxAckPending: 1000
          maxDeliver: 5
          ackWait: "30s"
        - durableName: order-analytics
          deliverPolicy: all
          ackPolicy: none
          description: "Analytics consumer, no ack required"
    - name: NOTIFICATIONS
      subjects:
        - "notify.*"
      storage: memory
      replicas: 1
      retention: interest
      consumers:
        - durableName: email-sender
          deliverPolicy: new_msgs
          ackPolicy: explicit
          filterSubject: "notify.email"
          ackWait: "1m"
          maxDeliver: 3

Using Foreign Key References

Reference an OpenMCF-managed namespace instead of hardcoding the name:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesNats
metadata:
  name: my-nats
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.KubernetesNats.my-nats
spec:
  namespace:
    valueFrom:
      kind: KubernetesNamespace
      name: app-namespace
      field: spec.name
  serverContainer:
    replicas: 3
    diskSize: "20Gi"
  auth:
    enabled: true
    scheme: bearer_token

Stack Outputs

After deployment, the following outputs are available in status.outputs:

OutputTypeDescription
namespacestringKubernetes namespace where NATS is deployed
clientUrlInternalstringCluster-internal NATS URL (e.g., nats://my-nats.messaging.svc.cluster.local:4222)
clientUrlExternalstringExternal NATS URL, only set when ingress is enabled
authTokenSecret.namestringName of the Kubernetes Secret storing the auth credentials
authTokenSecret.keystringKey within the auth Secret (token for bearer-token, password for basic-auth)
jetStreamDomainstringJetStream domain configured for the cluster, blank when JetStream is disabled
metricsEndpointstringPrometheus metrics endpoint (e.g., http://nats-prom.messaging.svc.cluster.local:7777/metrics)
tlsSecret.namestringName of the Kubernetes Secret containing the TLS certificate and key, blank when TLS is disabled
tlsSecret.keystringKey within the TLS Secret (tls.crt), blank when TLS is disabled

Related Components

  • KubernetesNamespace — provides the target namespace via valueFrom reference
  • KubernetesDeployment — application deployments that connect to NATS as a messaging backend
  • KubernetesRedis — often deployed alongside NATS for caching in event-driven architectures
  • KubernetesPostgres — persistent storage for applications consuming NATS events

Next article

Kubernetes Neo4j

Kubernetes Neo4j Deploys a single-node Neo4j Community instance on Kubernetes using the official Neo4j Helm chart, with automatic admin password generation, optional persistent storage via PersistentVolumeClaims, configurable heap and page-cache memory settings, and optional external access through a LoadBalancer Service with external-dns integration. What Gets Created When you deploy a KubernetesNeo4j resource, OpenMCF provisions: Namespace — created only when createNamespace is true Helm...
Read next article
Presets
2 ready-to-deploy configurationsView presets →