zkt26/z2
2026-04-29 11:35:30 +02:00
..
api Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
db Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
frontend Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
configmap-secret.yaml Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
deployment.yaml Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
namespace.yaml Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
prepare-app.sh Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
README.md Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
remove-app.sh Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
service.yaml Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
start-app.sh Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
statefulset.yaml Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00
stop-app.sh Add completed Kubernetes deployment for Task Manager (z2) 2026-04-29 11:35:30 +02:00

Task Manager — Kubernetes Deployment

A full-stack task management web application deployed on Kubernetes, extending the Docker Compose version (z1) with Kubernetes-native orchestration, scaling, and persistent storage.

Table of Contents


Description

Task Manager is a full-stack web application for creating, managing, and tracking tasks. Users can:

  • Create tasks with a title and optional description
  • Mark tasks as completed or reopen them
  • Delete tasks they no longer need
  • Filter tasks by status (All / Active / Completed)
  • View statistics including total, active, and completed task counts
  • Manage the database via Adminer web interface

The application consists of a dark-themed Nginx frontend, a Node.js/Express REST API backend, PostgreSQL for persistent task storage, and Redis for API response caching — all orchestrated by Kubernetes.


Prerequisites

Software Minimum Version Purpose
Linux Any modern distribution Host OS
Docker 20.10+ Build container images
kubectl 1.25+ Kubernetes CLI
Minikube or kind Latest Local Kubernetes cluster
bash 4.0+ Running management scripts

Verify installation:

docker --version
kubectl version --client
minikube version   # or: kind version

Start a local cluster (if not already running):

minikube start
# or
kind create cluster

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Namespace: taskmanager                    │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Kubernetes Cluster DNS                  │   │
│  │                                                     │   │
│  │  NodePort :30080          NodePort :30081           │   │
│  │       │                        │                   │   │
│  │  ┌────▼──────────┐    ┌────────▼──────────┐        │   │
│  │  │   Service     │    │     Service        │        │   │
│  │  │  (frontend)   │    │    (adminer)       │        │   │
│  │  └────┬──────────┘    └────────┬──────────┘        │   │
│  │       │                        │                   │   │
│  │  ┌────▼──────────┐    ┌────────▼──────────┐        │   │
│  │  │  Deployment   │    │    Deployment      │        │   │
│  │  │  (Nginx ×1)   │    │   (Adminer ×1)     │        │   │
│  │  └────┬──────────┘    └────────┬──────────┘        │   │
│  │       │ /api/ proxy             │                   │   │
│  │  ┌────▼──────────┐             │                   │   │
│  │  │   Service     │             │                   │   │
│  │  │  (api:3000)   │             │                   │   │
│  │  └────┬──────────┘             │                   │   │
│  │       │                        │                   │   │
│  │  ┌────▼──────────┐    ┌────────▼──────────┐        │   │
│  │  │  Deployment   │    │    StatefulSet     │        │   │
│  │  │  (API ×2)     │    │   (Postgres ×1)   │        │   │
│  │  └───┬───────────┘    └────────┬──────────┘        │   │
│  │      │                         │ PVC → PV           │   │
│  │  ┌───▼──────────┐              │ /mnt/.../postgres  │   │
│  │  │  StatefulSet │              │                   │   │
│  │  │  (Redis ×1)  │─────────────►│                   │   │
│  │  └──────────────┘              │                   │   │
│  │   PVC → PV                     │                   │   │
│  │   /mnt/.../redis               │                   │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Kubernetes Objects

Object Name File Description
Namespace taskmanager namespace.yaml Isolates all objects from other cluster workloads
Secret postgres-secret configmap-secret.yaml Stores base64-encoded DB username and password
ConfigMap postgres-init configmap-secret.yaml Contains init.sql to create the tasks table on first run
PersistentVolume postgres-pv statefulset.yaml 1 Gi host-path volume for PostgreSQL data
PersistentVolumeClaim postgres-pvc statefulset.yaml Claims postgres-pv for the postgres StatefulSet
PersistentVolume redis-pv statefulset.yaml 500 Mi host-path volume for Redis AOF data
PersistentVolumeClaim redis-pvc statefulset.yaml Claims redis-pv for the redis StatefulSet
StatefulSet postgres statefulset.yaml Manages the PostgreSQL 16 database pod with stable identity
StatefulSet redis statefulset.yaml Manages the Redis 7 cache pod with stable identity
Deployment taskmanager-api deployment.yaml Runs 2 replicas of the Node.js REST API
Deployment taskmanager-frontend deployment.yaml Runs 1 replica of the Nginx frontend
Deployment taskmanager-adminer deployment.yaml Runs 1 replica of Adminer (DB web UI)
Service postgres service.yaml ClusterIP — internal access to PostgreSQL on port 5432
Service redis service.yaml ClusterIP — internal access to Redis on port 6379
Service taskmanager-api service.yaml ClusterIP — internal access to API on port 3000
Service taskmanager-frontend service.yaml NodePort — exposes UI at port 30080
Service taskmanager-adminer service.yaml NodePort — exposes Adminer at port 30081

Containers Used

1. taskmanager-frontend (Custom — Nginx)

  • Image: Built from frontend/Dockerfile using nginx:alpine
  • Role: Serves the static HTML/CSS/JS UI and reverse-proxies /api/ requests to taskmanager-api:3000 using Kubernetes DNS resolution
  • Port: 80 (internal), exposed at NodePort 30080

2. taskmanager-api (Custom — Node.js)

  • Image: Built from api/Dockerfile using node:20-alpine
  • Role: REST API providing full CRUD operations for tasks. Uses PostgreSQL for data and Redis for caching (30 s TTL). 2 replicas for availability
  • Port: 3000 (ClusterIP)

3. postgres (Official — postgres:16-alpine)

  • Role: Primary relational database. The init.sql ConfigMap is mounted into /docker-entrypoint-initdb.d/ so the schema and sample data are created automatically the first time
  • Port: 5432 (ClusterIP)

4. redis (Official — redis:7-alpine)

  • Role: In-memory cache for task list API responses. Configured with append-only persistence (--appendonly yes) so the cache survives pod restarts
  • Port: 6379 (ClusterIP)

5. adminer (Official — adminer:latest)

  • Role: Web-based database management interface for browsing, querying, and managing the PostgreSQL database directly in a browser
  • Port: 8080 (internal), exposed at NodePort 30081

Networking

Kubernetes uses a flat cluster network — every pod can reach every other pod by its Service DNS name inside the same namespace.

Service Name Type Port Accessible From
postgres ClusterIP 5432 API pods only (internal)
redis ClusterIP 6379 API pods only (internal)
taskmanager-api ClusterIP 3000 Frontend pods (Nginx proxy)
taskmanager-frontend NodePort 80 → 30080 External (browser)
taskmanager-adminer NodePort 8080 → 30081 External (browser)

DNS resolution example: Inside the cluster, Nginx resolves taskmanager-api to the API Service IP automatically through Kubernetes DNS (kube-dns). The database and cache are not reachable from outside the cluster.


Persistent Volumes

Volume Name Type Capacity Mount Path Purpose
postgres-pv hostPath 1 Gi /mnt/taskmanager/postgres PostgreSQL data directory
redis-pv hostPath 500 Mi /mnt/taskmanager/redis Redis append-only file

Data persistence: Stopping the application by scaling to zero (./stop-app.sh) or restarting pods does not delete the host directories or PVs. Only ./remove-app.sh deletes them.


Container Configuration

All containers are configured using environment variables, Secrets, and ConfigMaps:

  • Secrets: postgres-secret provides the database username and password to both the postgres StatefulSet and taskmanager-api Deployment, avoiding plain-text credentials in YAML files
  • ConfigMap: postgres-init provides the init.sql script mounted as a file into the postgres container
  • Resource limits: Every container has requests and limits defined to prevent resource starvation
  • Readiness/liveness probes: All containers have health checks so Kubernetes only routes traffic to healthy pods and automatically restarts crashed pods
  • Restart policy: Kubernetes restarts failed pods by default (managed by the Deployment/StatefulSet controllers)
  • StatefulSets are used for PostgreSQL and Redis because they need a stable network identity and persistent storage. The API and frontend use Deployments because they are stateless and benefit from rolling updates

Quick Start

# 1. Start a local Kubernetes cluster (if not already running)
minikube start

# 2. Prepare — build Docker images and create host directories
./prepare-app.sh

# 3. Deploy to Kubernetes
./start-app.sh

# 4. Open the app in your browser
#    Task Manager: http://<NODE_IP>:30080
#    Adminer:      http://<NODE_IP>:30081

For Minikube, get the node IP with:

minikube ip

Usage Instructions

Preparing the application

./prepare-app.sh

Builds the custom Docker images (taskmanager-api:latest, taskmanager-frontend:latest), creates the host-path directories used by the PersistentVolumes, and automatically loads the images into Minikube if it detects a running Minikube cluster (preventing ImagePullBackOff errors).

Starting the application

./start-app.sh

Applies all Kubernetes manifests in the correct dependency order and waits for StatefulSets and Deployments to be ready. Prints the access URLs at the end.

Stopping and removing the application

./stop-app.sh

Deletes all Kubernetes objects (Deployments, StatefulSets, Services, PVCs, Secrets, ConfigMap, Namespace) and the PersistentVolumes and host directories. ⚠️ All task data will be lost. Run ./prepare-app.sh then ./start-app.sh to start fresh.

Pausing without data loss

# Scale all workloads to 0 — objects and PVs remain, data is preserved
kubectl scale deployment --all --replicas=0 -n taskmanager
kubectl scale statefulset --all --replicas=0 -n taskmanager

# Resume
./start-app.sh

Viewing the Application

Task Manager (Main UI)

  • URL: http://<NODE_IP>:30080
  • For Minikube: http://$(minikube ip):30080
  • Features: Create, complete, delete, and filter tasks

Adminer (Database Management)

  • URL: http://<NODE_IP>:30081
  • Login credentials:
    • System: PostgreSQL
    • Server: postgres
    • Username: taskuser
    • Password: taskpass
    • Database: taskmanager

Example Workflow

# Start a Minikube cluster
$ minikube start

# Prepare images and host directories
$ ./prepare-app.sh
=============================================
  Preparing Task Manager for Kubernetes...
=============================================
[1/2] Building Docker images...
      ✓ taskmanager-api:latest built
      ✓ taskmanager-frontend:latest built
[2/2] Creating host directories for PersistentVolumes...
      ✓ /mnt/taskmanager/postgres created
      ✓ /mnt/taskmanager/redis created
=============================================
  ✓ Preparation complete!
  Run ./start-app.sh to deploy to Kubernetes
=============================================

# Deploy the application
$ ./start-app.sh
=============================================
  Starting Task Manager on Kubernetes...
=============================================
[1/6] Creating Namespace...
[2/6] Applying Secrets and ConfigMaps...
[3/6] Applying PersistentVolumes, PVCs and StatefulSets...
[4/6] Waiting for postgres StatefulSet to be Ready...
      Waiting for redis StatefulSet to be Ready...
[5/6] Applying Deployments...
[6/6] Applying Services...
Waiting for API deployment to be ready...
=============================================
  ✓ Task Manager is running!

  🌐 Task Manager:  http://192.168.49.2:30080
  🗄️  Adminer (DB):  http://192.168.49.2:30081
=============================================

# Stop (data preserved)
$ ./stop-app.sh
  ✓ Application stopped. Data is preserved in PersistentVolumes.

# Start again — all tasks still there
$ ./start-app.sh

# Remove everything
$ ./remove-app.sh
  ✓ Application completely removed.

File Structure

z2/
├── namespace.yaml          # Namespace: taskmanager
├── configmap-secret.yaml   # Secret (DB credentials) + ConfigMap (init.sql)
├── statefulset.yaml        # PV, PVC, StatefulSet for postgres and redis
├── deployment.yaml         # Deployments for API, frontend, adminer
├── service.yaml            # Services (ClusterIP + NodePort)
├── prepare-app.sh          # Build images, create host directories
├── start-app.sh            # Deploy all Kubernetes objects
├── stop-app.sh             # Scale to zero (pause)
├── remove-app.sh           # Delete everything
├── README.md               # This documentation
├── api/
│   ├── Dockerfile          # Node.js 20 Alpine image
│   ├── package.json        # Node dependencies
│   ├── server.js           # Express REST API
│   └── db.js               # PostgreSQL connection pool
├── frontend/
│   ├── Dockerfile          # Nginx Alpine image
│   ├── nginx.conf          # Nginx config (proxies /api/ → taskmanager-api)
│   └── public/
│       ├── index.html      # Task Manager SPA
│       ├── style.css       # Dark theme CSS
│       └── app.js          # Frontend JavaScript
└── db/
    └── init.sql            # Database schema + sample data

Sources

  1. Kubernetes Documentationhttps://kubernetes.io/docs/
  2. kubectl Referencehttps://kubernetes.io/docs/reference/kubectl/
  3. Kubernetes: StatefulSetshttps://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
  4. Kubernetes: Persistent Volumeshttps://kubernetes.io/docs/concepts/storage/persistent-volumes/
  5. Kubernetes: Secretshttps://kubernetes.io/docs/concepts/configuration/secret/
  6. Minikube Documentationhttps://minikube.sigs.k8s.io/docs/
  7. PostgreSQL Docker Imagehttps://hub.docker.com/_/postgres
  8. Redis Docker Imagehttps://hub.docker.com/_/redis
  9. Adminer Docker Imagehttps://hub.docker.com/_/adminer
  10. Node.js Docker Imagehttps://hub.docker.com/_/node
  11. Nginx Docker Imagehttps://hub.docker.com/_/nginx
  12. Express.js Documentationhttps://expressjs.com/

Use of Artificial Intelligence

Artificial intelligence tools such as ChatGPT and Claude were used as a support tool during development for understanding Kubernetes concepts, writing YAML manifests, and debugging configuration issues. All implementation, testing, and integration were performed independently.