Skip to content

Latest commit

Β 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

☸️ Student Registration App β€” Three-Tier Architecture on Kubernetes

Kubernetes Docker Spring Boot React Vite MariaDB

Three-tier Student Registration app (React + Vite / Spring Boot / MariaDB) fully orchestrated on Kubernetes β€” StatefulSet, Deployments, HPA, Secrets, PVC, and Ingress


πŸ“Œ Overview

A three-tier Student Registration CRUD Application deployed on Kubernetes. The stack β€” React (Vite) frontend, Spring Boot backend, and MariaDB database β€” is containerized and fully orchestrated using production-grade Kubernetes patterns: StatefulSet for the database, HPA for auto-scaling, Secrets for credentials, PVC for persistent storage, and Ingress for routing.


πŸ—οΈ Architecture

  Browser
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Kubernetes Cluster                   β”‚
β”‚                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Ingress Controller                            β”‚  β”‚
β”‚  β”‚  Routes external traffic β†’ frontend service   β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                          β”‚                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Tier 1 β€” Frontend                             β”‚  β”‚
β”‚  β”‚  React + Vite   Deployment   NodePort Service  β”‚  β”‚
β”‚  β”‚  HPA: auto-scales on CPU                       β”‚  β”‚
β”‚  β”‚  VITE_API_URL β†’ backend NodePort               β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                          β”‚ ClusterIP :8080            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Tier 2 β€” Backend                              β”‚  β”‚
β”‚  β”‚  Spring Boot   Deployment   ClusterIP Service  β”‚  β”‚
β”‚  β”‚  HPA: auto-scales on CPU                       β”‚  β”‚
β”‚  β”‚  spring.datasource.url β†’ db StatefulSet ClusterIPβ”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                          β”‚ ClusterIP :3306            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Tier 3 β€” Database                             β”‚  β”‚
β”‚  β”‚  MariaDB   StatefulSet   ClusterIP Service     β”‚  β”‚
β”‚  β”‚  Secret β†’ credentials    PVC β†’ persistent data β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“ Repository Structure

student-app-kubernetes/
β”‚
β”œβ”€β”€ frontend/                       # React + Vite source + Dockerfile
β”‚   β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ .env                        # VITE_API_URL=http://<backend-ip>:<nodeport>/api
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── package.json
β”‚
β”œβ”€β”€ backend/                        # Spring Boot source + Dockerfile
β”‚   β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ application.properties      # DB connection via MariaDB ClusterIP
β”‚   └── Dockerfile
β”‚
β”œβ”€β”€ database-yaml/                  # Kubernetes manifests β€” database tier
β”‚   β”œβ”€β”€ statefulset.yaml
β”‚   β”œβ”€β”€ service.yaml
β”‚   β”œβ”€β”€ secret.yaml
β”‚   └── pv-pvc.yaml
β”‚
β”œβ”€β”€ simple-deploy/                  # Simplified starter manifests
β”‚   β”œβ”€β”€ deployment.yaml
β”‚   └── service.yaml
β”‚
β”œβ”€β”€ docker-compose.yml              # Local development stack
β”œβ”€β”€ init.sql                        # Database schema initialisation
└── README.md

☸️ Kubernetes Resources

Tier Resource Purpose
Database StatefulSet Stable pod identity + ordered startup for MariaDB
Database Service (ClusterIP) Internal access on port 3306
Database Secret Store MariaDB credentials (base64 encoded)
Database PersistentVolume + PVC Persistent storage β€” data survives pod restarts
Backend Deployment Manage Spring Boot pods
Backend Service (ClusterIP) Internal access on port 8080
Backend HPA Auto-scale pods based on CPU utilisation
Frontend Deployment Manage React/Vite pods
Frontend Service (NodePort) Expose frontend externally
Frontend HPA Auto-scale pods based on CPU utilisation
Frontend Ingress Route external HTTP traffic to frontend service

πŸš€ Deployment Guide

Prerequisites

  • Kubernetes cluster (Minikube / EKS / k3s)
  • kubectl configured and connected to the cluster
  • Docker + DockerHub account (for building and pushing images)

Step 1 β€” Build and Push Docker Images

Backend image:

cd backend/

# Edit application.properties β€” set the DB connection to the K8s service name
# spring.datasource.url=jdbc:mariadb://db-service:3306/student_db

docker build -t <your-dockerhub-username>/student-backend:latest .
docker login
docker push <your-dockerhub-username>/student-backend:latest

Frontend image:

cd ../frontend/

# Edit .env β€” point to backend NodePort
# VITE_API_URL=http://<cluster-node-ip>:<backend-nodeport>/api

docker build -t <your-dockerhub-username>/student-frontend:latest .
docker push <your-dockerhub-username>/student-frontend:latest

Step 2 β€” Create Kubernetes Secret for Database Credentials

# Encode your credentials in base64
echo -n 'root'         | base64   # β†’ cm9vdA==
echo -n 'your_password' | base64  # β†’ replace with your encoded value

Edit database-yaml/secret.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
  namespace: student-app
type: Opaque
data:
  db-username: cm9vdA==               # base64 of 'root'
  db-password: <base64-encoded-pass>  # never commit real passwords

Step 3 β€” Deploy All Tiers

# Deploy database tier first (StatefulSet must be ready before backend starts)
kubectl apply -f database-yaml/

# Wait for the database pod to be Running
kubectl get pods -n student-app -w

# Deploy backend and frontend
kubectl apply -f backend-yaml/
kubectl apply -f frontend-yaml/

Step 4 β€” Verify Everything is Running

# Check all resources
kubectl get all -n student-app

# Check HPA status
kubectl get hpa -n student-app

# Check Ingress
kubectl get ingress -n student-app

# List all services across namespaces
kubectl get svc -A

Step 5 β€” Access the Application

# For Minikube
minikube service frontend-service -n student-app

# For NodePort on any cluster
http://<cluster-node-ip>:<frontend-nodeport>

# For Ingress
http://<ingress-external-ip>

βš™οΈ Backend application.properties

server.port=8080
spring.datasource.url=jdbc:mariadb://<db-statefulset-clusterip>:3306/student_db
spring.datasource.username=root
spring.datasource.password=<injected-via-k8s-secret>
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

In production, inject spring.datasource.password from the Kubernetes Secret using valueFrom.secretKeyRef in the Deployment manifest β€” never hardcode it in application.properties.


πŸ“‹ Sample HPA β€” Backend

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: backend-hpa
  namespace: student-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: backend
  minReplicas: 2
  maxReplicas: 8
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

πŸ’» Local Development with Docker Compose

To run the full stack locally without Kubernetes:

docker compose up -d

# Frontend: http://localhost:3000
# Backend:  http://localhost:8080
# Database: localhost:3306

πŸ” Useful kubectl Commands

# Watch pod status live
kubectl get pods -n student-app -w

# Stream backend logs
kubectl logs -f deployment/backend -n student-app

# Describe a pod for debugging
kubectl describe pod <pod-name> -n student-app

# Scale backend manually
kubectl scale deployment backend --replicas=4 -n student-app

# Execute into the database pod
kubectl exec -it <db-pod-name> -n student-app -- mariadb -u root -p

⚠️ Security Notes

Issue Location Fix
Hardcoded DB password in application.properties backend/application.properties Inject via secretKeyRef in the backend Deployment manifest
Hardcoded backend IP in frontend .env frontend/.env Use Ingress hostname or ClusterIP service name resolved at runtime
Hardcoded credentials in README.md Repo root README.md Use placeholder values only β€” never commit real passwords to Git

πŸ”— Related Projects

Repo Description
student-app-docker-compose Same app running locally with Docker Compose
crud-app-aws-ec2-rds Same app deployed on AWS EC2 + RDS
jenkins-cicd-pipelines CI/CD pipeline that builds and pushes the Docker images
terraform-aws-iac Terraform to provision the EKS cluster this runs on

πŸ‘¨β€πŸ’» Author

Sanket Ajay Chopade β€” DevOps Engineer

LinkedIn GitHub

About

Three-tier student registration app (React + Spring Boot + MariaDB) deployed on Kubernetes with Deployments, Services, Secrets, PVC, and HPA manifests.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages