Notes App — Kubernetes Assignment
What the application does
A simple Notes web application where users can create, view, and delete short text notes. Notes are stored persistently in a PostgreSQL database. The app is accessible via a web browser.
Containers used
| Container |
Image |
Description |
frontend |
custom (Nginx 1.27-alpine) |
Serves the static HTML/JS frontend and proxies /api/ requests to the backend |
backend |
custom (Python 3.12-slim / Flask) |
REST API for CRUD operations on notes |
db |
postgres:16-alpine |
Relational database storing notes persistently |
adminer |
adminer:4 |
Web UI for browsing and managing the PostgreSQL database |
Kubernetes objects
| File |
Object |
Kind |
Description |
k8s/namespace.yaml |
notes-app |
Namespace |
Isolates all app objects in one namespace |
k8s/statefulset.yaml |
db |
StatefulSet |
Runs the PostgreSQL pod with stable identity |
k8s/statefulset.yaml |
postgres-pv |
PersistentVolume |
Host-path volume providing 1Gi of storage |
k8s/statefulset.yaml |
postgres-pvc |
PersistentVolumeClaim |
Claims the PV for use by the StatefulSet |
k8s/deployment.yaml |
backend |
Deployment |
Runs the Flask API pod |
k8s/deployment.yaml |
frontend |
Deployment |
Runs the Nginx frontend pod |
k8s/deployment.yaml |
adminer |
Deployment |
Runs the Adminer pod |
k8s/service.yaml |
db |
Service (ClusterIP/Headless) |
Internal DNS for the database (db:5432) |
k8s/service.yaml |
backend |
Service (ClusterIP) |
Internal DNS for the API (backend:5000) |
k8s/service.yaml |
frontend |
Service (NodePort 30080) |
Exposes the frontend to the host |
k8s/service.yaml |
adminer |
Service (NodePort 30081) |
Exposes Adminer to the host |
k8s/configmap.yaml |
db-init |
ConfigMap |
Holds init.sql mounted into the DB container |
Networking and volumes
- All objects live in the
notes-app namespace.
- Pods communicate via Kubernetes internal DNS (service names).
- The
db service is headless (clusterIP: None) — required for StatefulSets.
- The
frontend and adminer services use NodePort to be reachable from the host.
postgres-pv is a hostPath PersistentVolume at /data/notes-postgres on the node.
postgres-pvc binds to postgres-pv and is mounted into the db pod.
Container configuration
- db: configured via env vars (
POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD). The db-init ConfigMap is mounted into /docker-entrypoint-initdb.d/ and runs once on first startup.
- backend: receives
DATABASE_URL pointing to the db service.
- frontend: Nginx proxies
/api/ to http://backend:5000 and serves index.html for all other paths.
- adminer: no extra configuration, exposed on NodePort 30081.
Instructions
Prepare (build and load images)
chmod +x prepare-app.sh start-app.sh stop-app.sh remove-app.sh
./prepare-app.sh
Start
./start-app.sh
Stop (data is preserved)
./stop-app.sh
Remove everything
./remove-app.sh
Viewing the application
If using minikube, replace localhost with the output of minikube ip.
Use of artificial intelligence
This project was created with the assistance of Kiro AI (kiro-cli chat agent). The AI generated the Kubernetes manifests, shell scripts, and documentation. All generated files were reviewed and understood by the author.