3.6 KiB
3.6 KiB
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-appnamespace. - Pods communicate via Kubernetes internal DNS (service names).
- The
dbservice is headless (clusterIP: None) — required for StatefulSets. - The
frontendandadminerservices useNodePortto be reachable from the host. postgres-pvis ahostPathPersistentVolume at/data/notes-postgreson the node.postgres-pvcbinds topostgres-pvand is mounted into thedbpod.
Container configuration
- db: configured via env vars (
POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD). Thedb-initConfigMap is mounted into/docker-entrypoint-initdb.d/and runs once on first startup. - backend: receives
DATABASE_URLpointing to thedbservice. - frontend: Nginx proxies
/api/tohttp://backend:5000and servesindex.htmlfor 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
| URL | Description |
|---|---|
| http://localhost:30080 | Notes web application |
| http://localhost:30081 | Adminer — Server: db, User: appuser, Password: apppassword, Database: appdb |
If using minikube, replace
localhostwith the output ofminikube 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.