Kubernetes Handbook

    Deploying a Stateful Applications in Kubernetes

    Ready to tackle stateful apps like a Kubernetes pro? If you’ve been with us, you know StatefulSets are the magic behind apps that need to remember data, like a database holding your Swiggy orders. In this blog, we’ll deploy a StatefulSet for Swiggy’s order database, step by step, using examples so clear you’ll be running stateful apps in no time. Picture yourself setting up a system to keep Swiggy’s order history safe—it’s hands-on time! Let’s dive in! 😊

    What’s a StatefulSet? A Quick Refresher#

    Let’s set the stage. A StatefulSet is a Kubernetes resource for stateful apps, like Swiggy’s PostgreSQL database, where pods need unique names, persistent storage, and orderly scaling. Unlike Deployments, which handle stateless apps (like Swiggy’s restaurant search), StatefulSets ensure pods have consistent identities (e.g., swiggy-db-0) and dedicated storage. This is perfect for apps that store data, like your Swiggy order history.

    Why Use a StatefulSet?

    • Unique Pod Names: Pods get predictable names, like swiggy-db-0, swiggy-db-1.
    • Persistent Storage: Each pod has storage that survives crashes.
    • Orderly Scaling: Pods scale or update in a specific sequence to keep data safe.

    I’ll be real—my first StatefulSet deployment felt like assembling IKEA furniture without instructions. 😅 But once I got it, it was a total game-changer. Let’s make this smooth for you!

    The Plan: Deploying Swiggy’s Order Database#

    We’re going to deploy a StatefulSet for Swiggy’s PostgreSQL database, which stores your past orders (like that butter chicken from last week). Our setup will include:

    1. Headless Service: To give pods stable network identities.
    2. StatefulSet YAML: To define the pods and their storage.
    3. Persistent Volume Claims (PVCs): To ensure each pod’s data persists.

    Our goal is to create two pods (swiggy-db-0 as the primary, swiggy-db-1 as the replica) to handle order data, with the specific scenario you provided: Swiggy’s order database stores your past orders. The StatefulSet ensures swiggy-db-0 (primary) and swiggy-db-1 (replica) have unique names and dedicated storage. If swiggy-db-0 crashes, Kubernetes recreates it with the same name and reattaches its storage, keeping your order history safe. So that when the request comes to store orders data of users it goes through swiggy-db-0.

    Step 1: Creating a Headless Service#

    A StatefulSet needs a Headless Service to assign unique DNS names to pods (e.g., swiggy-db-0.swiggy-db.default.svc.cluster.local). This lets Swiggy’s app connect to specific pods, like swiggy-db-0 for writes.

    Here’s the YAML:

    apiVersion: v1 kind: Service metadata: name: swiggy-db namespace: default spec: ports: - port: 5432 targetPort: 5432 clusterIP: None selector: app: swiggy-db

    YAML Breakdown#

    YAML is just Kubernetes’ way of taking notes. Here’s what each part does:

    • apiVersion: v1: Uses the standard Service API.
    • kind: Service: Says, “I’m creating a Service.”
    • metadata: Names the Service.
      • name: swiggy-db: The Service’s name, linked to the StatefulSet.
      • namespace: default: Keeps it in the default namespace.
    • spec: Defines the Service’s behavior.
      • ports: Opens port 5432 for PostgreSQL.
      • clusterIP: None: Makes it a Headless Service, giving each pod its own DNS name.
      • selector: app: swiggy-db: Targets pods with the app: swiggy-db label.

    Save this as swiggy-db-service.yaml and apply it:

    kubectl apply -f swiggy-db-service.yaml

    Output:

    service/swiggy-db created

    This sets up the network so Swiggy’s app can talk to swiggy-db-0 and swiggy-db-1 directly. Think of it as giving each pod its own email address for order data.

    Real-World Scenario#

    Swiggy’s app needs to store a new order (say, a masala dosa). It sends the request to swiggy-db-0.swiggy-db.default.svc.cluster.local:5432, the primary pod, ensuring data is written consistently. The Headless Service makes this possible by giving swiggy-db-0 a stable DNS name.

    Step 2: Deploying the StatefulSet#

    Now, let’s create the StatefulSet for Swiggy’s PostgreSQL database. This will set up swiggy-db-0 (primary) and swiggy-db-1 (replica) with persistent storage.

    Here’s the YAML:

    apiVersion: apps/v1 kind: StatefulSet metadata: name: swiggy-db namespace: default spec: serviceName: swiggy-db replicas: 2 selector: matchLabels: app: swiggy-db template: metadata: labels: app: swiggy-db spec: containers: - name: postgres image: postgres:13 env: - name: POSTGRES_PASSWORD value: swiggy_secure_password ports: - containerPort: 5432 volumeMounts: - name: data mountPath: /var/lib/postgresql/data volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi

    YAML Breakdown#

    Think of this YAML as a recipe for Swiggy’s database. Here’s each ingredient:

    • apiVersion: apps/v1: Uses the StatefulSet API.
    • kind: StatefulSet: Says, “I’m creating a StatefulSet.”
    • metadata: Names the StatefulSet.
      • name: swiggy-db: The StatefulSet’s name.
      • namespace: default: Keeps it in the default namespace.
    • spec: The plan for our pods.
      • serviceName: swiggy-db: Links to the Headless Service.
      • replicas: 2: Creates two pods (swiggy-db-0, swiggy-db-1).
      • selector: Targets pods with app: swiggy-db.
      • template: Defines the pods.
        • metadata.labels: Labels pods with app: swiggy-db.
        • spec.containers: Sets up the PostgreSQL container.
          • name: postgres: Names the container.
          • image: postgres:13: Uses PostgreSQL 13.
          • env: Sets the database password.
          • ports: Opens port 5432.
          • volumeMounts: Attaches storage at /var/lib/postgresql/data.
      • volumeClaimTemplates: Creates a PVC for each pod.
        • metadata.name: data: Names the PVC.
        • spec.accessModes: Ensures exclusive access (ReadWriteOnce).
        • spec.resources.requests.storage: Gives each pod 1GB.

    Save this as swiggy-db-statefulset.yaml and apply it:

    kubectl apply -f swiggy-db-statefulset.yaml

    Output:

    statefulset.apps/swiggy-db created

    Kubernetes spins up swiggy-db-0 first, then swiggy-db-1, each with its own PVC. Check the pods:

    kubectl get pods

    Output:

    NAME READY STATUS RESTARTS AGE swiggy-db-0 1/1 Running 0 3m swiggy-db-1 1/1 Running 0 2m
    Swiggy Stateful Apps

    Real-World Scenario: Swiggy’s order database stores your past orders. The StatefulSet ensures swiggy-db-0 (primary) and swiggy-db-1 (replica) have unique names and dedicated storage. If swiggy-db-0 crashes, Kubernetes recreates it with the same name and reattaches its storage, keeping your order history safe. So that when the request comes to store the previous orders data of user, it goes through swiggy-db-0only, and to retrieve order it will go to replica swiggy-db-1

    Step 3: Verifying the Setup#

    Let’s confirm everything’s running smoothly. Check the PVCs:

    kubectl get pvc

    Output:

    NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE data-swiggy-db-0 Bound pvc-123 1Gi RWO standard 3m data-swiggy-db-1 Bound pvc-901 1Gi RWO standard 2m

    Each pod has its own PVC, ensuring data persists. Test the database:

    kubectl exec -it swiggy-db-0 -- psql -U postgres -c "CREATE TABLE orders (id SERIAL PRIMARY KEY, item VARCHAR); INSERT INTO orders (item) VALUES ('Masala Dosa'); SELECT * FROM orders;"

    Output:

    id | item ----+------------- 1 | Masala Dosa (1 row)

    This confirms swiggy-db-0 is handling writes, simulating Swiggy storing a new order. You can connect Swiggy’s app to swiggy-db-0.swiggy-db.default.svc.cluster.local:5432 for writes and swiggy-db-1 for reads.

    Real-World Scenario: Swiggy’s backend team queries order data for analytics. They use swiggy-db-0 to save new orders (e.g., a paneer tikka roll) and swiggy-db-1 to read order history, leveraging the StatefulSet’s stable pod names for reliable connections.

    Avoiding Beginner Mistakes#

    You might stumble the first time, and that’s no biggie! Here are common pitfalls:

    • Wrong Service Name: The serviceName in the StatefulSet must match the Headless Service’s name (swiggy-db).
    • Missing StorageClass: Ensure your cluster has a StorageClass for dynamic PVCs, or your pods won’t start.
    • Skipping the Headless Service: Without it, pods won’t get stable DNS names.

    Pro Tip: Run kubectl describe statefulset swiggy-db to inspect pods, PVCs, and the Service.

    Example: Fixing a Pod Issue#

    If swiggy-db-1 isn’t running, check its status:

    kubectl describe pod swiggy-db-1

    Output (shortened):

    Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 2m default-scheduler 0/1 nodes are available: 1 Insufficient storage.

    This points to a storage issue. Verify your StorageClass, fix it, and reapply the YAML. You’re good to go!

    Why StatefulSets for Swiggy’s Database?#

    Swiggy’s stateless services (like restaurant listings) use Deployments, but the order database needs a StatefulSet because:

    • Stable Identities: swiggy-db-0 is always the primary, making writes predictable.
    • Persistent Data: PVCs keep order history safe across pod restarts.
    • Orderly Scaling: Pods are added or removed in sequence, avoiding data conflicts.

    Personal Story: I once thought I could skip StatefulSets for a database, using a Deployment instead. Random pod names and lost data taught me the hard way. Switching to a StatefulSet was like finding the perfect tadka for my dal—everything clicked! 😎

    Conclusion#

    In this blog, you mastered deploying a StatefulSet in Kubernetes with beginner-friendly Swiggy examples. We created a Headless Service, deployed a StatefulSet for Swiggy’s PostgreSQL database, verified it, and debugged issues, with clear YAML breakdowns and your requested real-world scenario. You’re now ready to run stateful apps with confidence!

    Last updated on May 06, 2025