This episode covers deploying NATS on Kubernetes: the nats Helm chart and nats-operator, StatefulSets for JetStream with PVC-backed persistence, then integration with the KEDA NATS JetStream scaler, Argo workflows, and service meshes.

Most production NATS deployments run on Kubernetes. Episode 17 guides you through deploying NATS on K8s the right way: Helm charts and operators for management, StatefulSets for JetStream state, PVCs for storage, then integration with the ecosystem like KEDA and Argo.
We'll assume you're already familiar with Kubernetes basics: pods, services, and namespaces.
The official NATS chart is available in the Helm repository:
helm repo add nats https://nats-io.github.io/k8s/helm/charts
helm install nats nats/nats --namespace nats --create-namespaceThe helm install nats nats/nats command deploys NATS into the nats namespace. The chart handles the StatefulSet, services, and basic configuration. Check the deployment status:
kubectl get pods -n nats
kubectl exec -n nats nats-0 -- nats-server -vkubectl exec -n nats nats-0 -- nats-server -v verifies the server version inside the pod. The first NATS pod in a StatefulSet is usually named nats-0.
Production needs are set through values:
config:
jetstream:
enabled: true
storeDir: /data/jetstream
maxMem: 1Gi
maxFile: 10Gi
cluster:
enabled: trueThe jetstream block enables JetStream inside the K8s cluster with clear resource limits. cluster.enabled makes three replicas connect as a NATS cluster.
Besides Helm, nats-operator manages NATS with Custom Resource Definitions:
apiVersion: nats.io/v1alpha2
kind: NatsCluster
metadata:
name: nats-prod
spec:
size: 3
version: "2.14"The NatsCluster manifest asks the operator to create a 3-node NATS cluster version 2.14. The operator handles pod, service, and monitoring creation automatically. Choose Helm for simplicity, the operator for full declarative control.
JetStream stores state, so it needs a StatefulSet, not a Deployment: each pod has a fixed identity and a separate PVC.
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: standard
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50GivolumeClaimTemplates creates a 50 GB data PVC for every replica. With a PVC, JetStream data survives even when a pod is rescheduled to another node. This is a hard requirement so streams aren't lost when a pod restarts.
Warning
Never use ephemeral storage for JetStream in K8s. A pod restart will wipe stream data. Always use a PVC backed by a storage class that supports ReadWriteOnce in your cluster.
KEDA enables event-driven autoscaling:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-worker
spec:
scaleTargetRef:
name: order-worker-deployment
triggers:
- type: nats-jetstream
metadata:
natsURL: nats://nats:4222
stream: ORDERS
consumer: WORKER
lagThreshold: "100"The nats-jetstream block makes KEDA monitor the pending messages of the WORKER consumer; when the lag exceeds 100 messages, workers scale up automatically. This is event-driven autoscaling that matches capacity to real load.
NATS fits naturally as the event source for Argo Events:
NATS (event) --> EventSource --> Sensor --> Argo WorkflowThe NATS (event) -> EventSource flow shows an event from a NATS stream triggering an Argo workflow. This is a popular pattern for automated pipelines: a file upload triggers a job, an incoming order triggers a process.
NATS coexists with service meshes like Istio or Linkerd. The service mesh handles observability and mTLS between pods, while NATS handles messaging between services. They don't replace each other:
pod A --> (mesh mTLS) --> pod B
pod A --> (NATS) --> stream --> pod CThe pod A -> (NATS) -> stream scheme shows NATS for async communication and the service mesh for synchronous communication and network security. Use both according to their respective roles.
Episode 17 brought NATS to Kubernetes: deploying with the Helm chart or nats-operator, StatefulSets with PVCs for JetStream persistence that survives pod restarts, plus KEDA integration for event-driven autoscaling, Argo for automated workflows, and service meshes for network security.
Key takeaways:
nats/nats Helm chart deploys NATS quickly; the operator gives declarative control.In episode 18 next, we'll discuss monitoring & observability — the /varz, /connz, /jsz, and /subsz endpoints, Prometheus metrics via nats_exporter, Grafana dashboards, consumer latency metrics, $SYS account events, and log rotation. Your NATS is now clearly visible from the outside.