recipes / manifests

Kubernetes manifests for a Node.js app

The plain YAML baseline: a Deployment and a Service with probes, resources, security context and a named port. Kustomize and Helm build on it.

This is the complete baseline in plain YAML. Every other recipe adjusts one part of it, and the Kustomize and Helm recipes below package the same files for more than one environment.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
  labels:
    app.kubernetes.io/name: app
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: app
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app
    spec:
      terminationGracePeriodSeconds: 30
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: app
          image: ghcr.io/you/app:1.0.0
          ports:
            - name: http
              containerPort: 3000
          env:
            - name: PORT
              value: "3000"
            - name: NODE_ENV
              value: production
          resources:
            requests:
              cpu: "1"
              memory: 256Mi
            limits:
              memory: 256Mi
          startupProbe:
            httpGet: { path: /healthz, port: http }
            failureThreshold: 30
            periodSeconds: 2
          livenessProbe:
            httpGet: { path: /healthz, port: http }
            periodSeconds: 10
          readinessProbe:
            httpGet: { path: /readyz, port: http }
            periodSeconds: 5
          lifecycle:
            preStop:
              sleep:
                seconds: 5
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
---
apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  selector:
    app.kubernetes.io/name: app
  ports:
    - name: http
      port: 80
      targetPort: http

Notes

  • Name the port and reference it by name in probes and the Service. Change the number in one place.
  • readOnlyRootFilesystem: true works with Node.js as long as you do not write to disk. Mount an emptyDir at /tmp if a library needs it.
  • Memory limit equals memory request. See memory and CPU for why.
  • One full CPU requested, no CPU limit. Less than that throttles Node.js under load; see memory and CPU.
  • Expose through an Ingress or an HTTPRoute; see networking. The Service is all the app needs to know about.

In this section

  1. Kustomize base and overlays - One base with the manifests, one overlay per environment that changes only the image tag, replicas and config.
  2. A minimal Helm chart - A chart with one Deployment, one Service, a PDB and a values file with only the knobs you actually turn.

See it applied

Updated 2026-09-10 · tags: kubernetes, deployment, service, manifests · edit on GitHub