K8s StatefulSet Generator

Kubernetes StatefulSet & Headless Service YAML Builder

Build production-grade Kubernetes StatefulSet manifests, companion Headless Services, volumeClaimTemplates, and secure container security contexts with zero server dependencies.

Presets
StatefulSet & Service Configuration
Pods with ordinal >= partition will be updated (Canary)
Number of pods unavailable during rollout
:
:
# ============================================================================
# Kubernetes StatefulSet: postgres-ha
# Generated via ToolsAA - 100% Client-Side Stateful Workload Builder
# Headless Network Domain: postgres-ha-headless.database.svc.cluster.local
# Pod Stable FQDN: postgres-ha-[0..2].postgres-ha-headless.database.svc.cluster.local
# ============================================================================
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres-ha
  namespace: database
  labels:
    app: "postgres-ha"
    tier: "database"
    app.kubernetes.io/managed-by: toolsaa
  annotations:
    cluster.toolsaa.com/role: "primary-replica"
spec:
  serviceName: "postgres-ha-headless"
  replicas: 3
  podManagementPolicy: OrderedReady
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0
      maxUnavailable: 1
  revisionHistoryLimit: 10
  minReadySeconds: 10
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Retain
    whenScaled: Retain
  selector:
    matchLabels:
      app: "postgres-ha"
  template:
    metadata:
      labels:
        app: "postgres-ha"
        tier: "database"
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9187"
    spec:
      serviceAccountName: postgres-sa
      terminationGracePeriodSeconds: 120
      securityContext:
        runAsNonRoot: true
        runAsUser: 999
        runAsGroup: 999
        fsGroup: 999
        fsGroupChangePolicy: "OnRootMismatch"
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values: ["postgres-ha"]
              topologyKey: "kubernetes.io/hostname"
      nodeSelector:
        node-role.kubernetes.io/database: "true"
      containers:
      - name: postgres
        image: postgres:16-alpine
        imagePullPolicy: IfNotPresent
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
        ports:
        - name: postgresql
          containerPort: 5432
          protocol: TCP
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: POSTGRES_DB
          value: "app_production"
        - name: POSTGRES_USER
          value: "postgres"
        - name: PGDATA
          value: "/var/lib/postgresql/data/pgdata"
        resources:
          requests:
            cpu: "500m"
            memory: "1Gi"
          limits:
            cpu: "2000m"
            memory: "4Gi"
        volumeMounts:
        - name: pgdata
          mountPath: "/var/lib/postgresql/data"
        livenessProbe:
          exec:
            command:
            - "pg_isready"
            - "-U"
            - "postgres"
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        readinessProbe:
          exec:
            command:
            - "pg_isready"
            - "-U"
            - "postgres"
            - "-h"
            - "127.0.0.1"
          initialDelaySeconds: 15
          periodSeconds: 5
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 3
        startupProbe:
          exec:
            command:
            - "pg_isready"
            - "-U"
            - "postgres"
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 15
  volumeClaimTemplates:
  - metadata:
      name: pgdata
      labels:
        app: "postgres-ha"
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "gp3"
      resources:
        requests:
          storage: 50Gi
Stateful ReplicasOrderedReady
3 Stateful Pods

Partition: 0 | Strategy: RollingUpdate

Volume Claim Templatesgp3
50Gi / pod (1 templates)

Retention: Retain | fsGroup:: 999

Hardening PostureSecurity Grade A+
100 / 100 Readiness

Probes: 3/3 active

100% Client-Side Manifest Synthesis

Zero server transmissions or external logging. All Kubernetes StatefulSet manifests, headless services, and PVC templates are synthesized entirely in browser memory.

Ordered Lifecycle & Headless DNS Identity

Maintains unique ordinal identities, predictable network DNS addressing via Headless Services, OrderedReady lifecycle sequencing, and persistent volume claim templates.

CIS Hardening & Multi-Format Export

Enforces non-root securityContexts, dropped capabilities, and produces production-ready outputs for Helm charts, Kustomize manifests, and kubectl CLI commands.

Technical Reference & Architecture Guide

Kubernetes StatefulSet & Headless Service YAML Builder — Reference Guide

Generate production-grade Kubernetes StatefulSet manifests with companion Headless Service, persistent volumeClaimTemplates, replicas, and podManagementPolicy.

Key Parameters & Controls

spec.serviceNamestring

Name of the companion Headless Service (clusterIP: None) governing network identity and DNS SRV routing for pod ordinals.

Default: Required
spec.replicasinteger

Desired number of stateful pod ordinals (0 to N-1) created sequentially in ascending order.

Default: 3
spec.podManagementPolicyenum (OrderedReady | Parallel)

Pod ordering lifecycle policy. 'OrderedReady' launches pods one-by-one waiting for readiness; 'Parallel' provisions or terminates all pods concurrently.

Default: OrderedReady
spec.volumeClaimTemplatesarray of objects

PersistentVolumeClaim templates dynamically provisioning dedicated, persistent storage volumes for each ordinal pod index.

Default: Required
spec.updateStrategyobject

Automated rolling update strategy configuration with optional canary 'partition' integer or manual 'OnDelete'.

Default: RollingUpdate

Pro Tips & Best Practices

A StatefulSet requires a companion

A StatefulSet requires a companion Service with 'clusterIP: None'. Kubernetes CoreDNS automatically registers stable A/AAAA and SRV records formatted as '<pod-name>.<service-name>.<namespace>.svc.cluster.local', critical for master-replica databases and Raft quorums.

Set

Set 'spec.updateStrategy.rollingUpdate.partition: <N>' where N equals replicas - 1 to canary-test new image versions on only the highest ordinal pod (e.g. statefulset-2) before promoting across the entire cluster.

Kubernetes purposefully does not delete

Kubernetes purposefully does not delete PVCs created by volumeClaimTemplates when scaling down or deleting a StatefulSet. In Kubernetes 1.27+, enable persistentVolumeClaimRetentionPolicy to declare 'whenDeleted: Retain' or 'whenScaled: Delete'.

Stateful systems like ZooKeeper

Stateful systems like ZooKeeper, Kafka, and Cassandra require a quorum to operate. Always bind a PodDisruptionBudget with 'minAvailable: 2' or 'maxUnavailable: 1' to block node drains from causing unrecoverable split-brain scenarios.

Common Gotchas & Troubleshooting

Pod remains stuck in Pending state with '0/N nodes available: persistentvolumeclaim unbound'

Inspect storage provisioner logs and check 'kubectl describe pvc <claim-name>'. Verify the configured storageClassName exists in the cluster and matches accessModes (ReadWriteOnce), and ensure the storage provisioner supports dynamic volume creation.

StatefulSet update or scale-up stalls indefinitely on a specific ordinal pod

Under 'OrderedReady' policy, Kubernetes halts rolling updates and scaling if the preceding ordinal pod fails its readinessProbe. Inspect pod events via 'kubectl describe pod <name>' and verify application health check endpoints before proceeding.

Pod-to-pod peer discovery fails with 'NXDOMAIN' on Headless Service hostname

Ensure 'spec.serviceName' in the StatefulSet matches the exact 'metadata.name' of the companion Service. Verify that the Headless Service has 'clusterIP: None' and that both resources share the identical 'spec.selector' labels.

Frequently Asked Questions

What is the key difference between a Kubernetes Deployment and a StatefulSet?▼

A Deployment manages identical, stateless pods with random hashes and shared or ephemeral storage. A StatefulSet provides stable, unique ordinal identifiers (app-0, app-1), deterministic startup/shutdown ordering, dedicated persistent storage per replica, and predictable DNS network identities via a Headless Service.

Why does a StatefulSet require a Headless Service ('clusterIP: None')?▼

Standard Kubernetes Services assign a single virtual VIP that load-balances traffic randomly among ready pods. Stateful systems like distributed databases require direct peer-to-peer addressing to specific instances (e.g., primary vs secondary). A Headless Service bypasses the VIP, creating individual DNS A-records pointing directly to each pod's IP address.

What happens to PersistentVolumeClaims (PVCs) when a StatefulSet is scaled down or deleted?▼

By default, Kubernetes never deletes PVCs created by volumeClaimTemplates upon scale down or StatefulSet deletion to prevent accidental data destruction. If you scale back up, the newly created pods reattach to their existing ordinal volumes. To purge data, PVCs must be deleted manually with 'kubectl delete pvc'.

When should you use 'podManagementPolicy: Parallel' instead of 'OrderedReady'?▼

Use 'Parallel' for stateful applications that handle cluster discovery and consensus independently at the software layer and do not need sequential bootstrap ordering, or when you need fast parallel scaling/rolling updates without waiting for pods to pass readiness sequentially.

How does the 'updateStrategy.rollingUpdate.partition' parameter work?▼

The partition parameter sets an ordinal threshold. Kubernetes updates only pods with an ordinal greater than or equal to the partition value. When you update the pod template image and set partition to N-1, only the last replica updates, serving as a stateful canary test. Decreasing partition to 0 rolls the change out cluster-wide.

Related Tools & Utilities

All Tools →