Command Palette

Search for a command to run...

Hectal
← All projects

Project 5 of 12 · project brief

Deploy the Complete App to Kubernetes

The Project 3 stack as Kubernetes manifests: Deployments, StatefulSets, Services, Ingress, ConfigMaps, Secrets, probes, resources, and autoscaling.

Intermediate 3–4 days 4 milestones

The scenario

Compose runs on one machine. ShopLite now needs self-healing, rolling updates, and scaling across nodes. Your brief: run the whole application on a local Kubernetes cluster (kind or k3d) with production-style manifests, so moving to EKS later is just a change of cluster.

Before you start

Stack

kind / k3dkubectlDeploymentsStatefulSetsServicesIngress (or Gateway API)ConfigMaps/SecretsHPAmetrics-server

Target architecture

Project 5 architecturediagram
Rendering diagram…

Deliverables and requirements

You will hand in

  • A k8s/ folder of manifests (or Kustomize base), one directory per component
  • Probes, resource requests/limits, PDBs, and an HPA for the API
  • Config in ConfigMaps, credentials in Secrets (not in Git: created from a sealed/secret manager or a local script)
  • A troubleshooting log: at least three problems you hit and how you diagnosed them

Functional

  • The whole app works through one Ingress host (e.g. shop.local)
  • Killing any API pod causes no failed requests (readiness + multiple replicas)
  • Database data survives pod deletion

Non-functional

  • Every container has requests/limits and readiness/liveness probes
  • API scales on CPU with an HPA
  • NetworkPolicy: only the API may reach Postgres and Redis

Milestones

  1. 1

    Cluster and stateful services

    Done when: Postgres, Redis, and Kafka running as StatefulSets with persistent volumes.

    • Create a 3-node kind cluster with an ingress-ready control plane
    • Postgres StatefulSet + headless Service + PVC template; init credentials from a Secret
    • Redis and Kafka (or the Strimzi operator for Kafka, Stateful course Unit 2.3)

    Prove it works

    terminal
    $ kubectl -n shoplite get sts,pvc
    ── expected output ──
    NAME READY AGE
    statefulset.apps/postgres 1/1 3m
    statefulset.apps/redis 1/1 3m
    ...
    persistentvolumeclaim/data-postgres-0 Bound ...
  2. 2

    API, worker, and frontend

    Done when: Stateless services as Deployments with config, probes, and resources.

    • ConfigMap for non-secret config; Secret for DB password
    • Readiness on /actuator/health/readiness, liveness on /actuator/health/liveness
    • Requests/limits sized from observed usage
    • Services for each
    Stuck? Hints
    • Liveness should never depend on the database: if Postgres is down, restarting every API pod makes it worse.

    Prove it works

    terminal
    $ kubectl -n shoplite rollout status deploy/api && kubectl -n shoplite get endpoints api
    ── expected output ──
    deployment "api" successfully rolled out
    NAME ENDPOINTS AGE
    api 10.244.1.7:8080,10.244.2.5:8080,10.244.3.4:8080 2m
  3. 3

    Ingress, scaling, and resilience

    Done when: External access, autoscaling, and disruption safety.

    • Install an ingress controller (or Gateway API implementation) and route / and /api
    • Install metrics-server; HPA on the API at 70% CPU
    • PDB minAvailable: 2 for the API; run a load test and watch it scale (Stateful course, k6)

    Prove it works

    terminal
    $ kubectl -n shoplite get hpa api -w
    ── expected output ──
    NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
    api Deployment/api cpu: 142%/70% 3 10 3
    api Deployment/api cpu: 88%/70% 3 10 6
  4. 4

    Network policy and a zero-downtime rollout

    Done when: Least-privilege networking and a rolling update with no errors.

    • Default-deny ingress in the namespace; allow ingress→frontend/api, api→postgres/redis/kafka
    • Change the API image tag and roll out while a load test runs; confirm zero 5xx
    • Practise kubectl rollout undo

    Prove it works

    terminal
    $ kubectl -n shoplite run tmp --rm -it --image=busybox:1.37 -- nc -zv -w 2 postgres 5432
    ── expected output ──
    nc: postgres (10.96.44.12:5432): Connection timed out
    # blocked: only pods labelled app=api may connect (good)

Would you run this in production?

  • ☐Probes separated correctly (readiness gates traffic; liveness only for deadlocks)
  • ☐Requests/limits on everything; PDBs on multi-replica services
  • ☐Secrets not committed; RBAC least privilege; pods non-root
  • ☐NetworkPolicies default-deny
  • ☐Graceful shutdown (preStop + terminationGracePeriodSeconds) so rollouts don't drop requests

Stretch goals

  • Replace Ingress with Gateway API (Platform course, Mission 0.2)
  • Use the CloudNativePG operator for Postgres with automated backups
  • Add topology spread constraints and simulate a node failure

Show it off

Résumé bullet

Migrated a 6-service application to Kubernetes with StatefulSets for data services, health probes, HPA autoscaling, PDBs, and default-deny network policies; achieved zero-error rolling deployments under load.

Demo script

  • Delete an API pod during a load test: zero errors
  • Show the HPA scaling out
  • Show a NetworkPolicy blocking an unauthorised pod

Interview questions about this project

01

Readiness vs liveness probes?

02

How do you achieve zero-downtime deployments on Kubernetes?