Course project — DevOps demonstration repository
This repo contains the DevOps layer of a full-stack Java/Kotlin application:
CI/CD pipeline (.gitlab-ci.yml), Kubernetes manifests (k8s/), Helm charts (helm/), Helmfile orchestration, and Dockerfiles.
The application source code (backend/src/, frontend/.../src/) is kept in a separate private repository and is not included here.
- Backend
- Frontend
- CI/CD pipeline
- Helm charts
- Helmfile deployment
- Monitoring
- Kubernetes manifests (legacy)
Spring Boot (Java 8) REST API, backed by PostgreSQL.
Build scripts: backend/build.gradle
Docker image: backend/Dockerfile
API spec: backend/conf/swagger/devscool-app.yaml
Prerequisites: PostgreSQL 13, Gradle 6.7.1, Java 8.
psql postgres
CREATE ROLE postgres WITH LOGIN PASSWORD 'postgres';
ALTER ROLE postgres CREATEDB;
CREATE DATABASE devschool;cd backend
./gradlew build
java -jar build/libs/dev-school-app-1.0-SNAPSHOT.jarSwagger UI available at http://localhost:8080/swagger-ui.html.
Kotlin/Ktor server serving a React (JS) single-page application.
Build scripts: frontend/build.gradle
Docker image: frontend/Dockerfile
Prerequisites: Node.js 14.15.0, Yarn 1.22.11, Gradle 6.7.1, Java 8.
cd frontend
./gradlew jar
java -jar devschool-front-app-server/build/libs/devschool-front-app-server-1.0.0.jar \
-port=<port> \
-P:ktor.backend.port=<port> \
-P:ktor.backend.host=<host> \
-P:ktor.backend.schema=<schema>Start page: ./dev-ops-school/index.html
Defined in .gitlab-ci.yml with shared job templates in ci_devschool/.
| Stage | Job | Description |
|---|---|---|
| build | build-backend |
Gradle build → JAR artifact |
| build | build-frontend |
Gradle build → JAR artifact |
| test | test-job |
Manual gate |
| dockerization | kaniko-backend |
Builds & pushes backend Docker image via Kaniko |
| dockerization | kaniko-frontend |
Builds & pushes frontend Docker image via Kaniko |
| publish-charts | publish-backend-chart |
Packages and pushes backend Helm chart to GitLab OCI registry |
| publish-charts | publish-frontend-chart |
Packages and pushes frontend Helm chart to GitLab OCI registry |
| publish-charts | publish-database-chart |
Packages and pushes database Helm chart to GitLab OCI registry |
| deploy | deploy_dev |
helmfile -e dev sync → devschool-dev namespace |
| deploy | deploy_prod |
helmfile -e prod sync → devschool-prod namespace (manual, master branch only) |
Required CI/CD variables:
| Variable | Description |
|---|---|
AWS_ACCESS_KEY_ID |
AWS credentials for EKS access |
AWS_SECRET_ACCESS_KEY |
AWS credentials for EKS access |
AWS_DEFAULT_REGION |
AWS region |
KUBECONFIG_BASE64 |
Base64-encoded kubeconfig |
PG_USER |
PostgreSQL username |
PG_PASS |
PostgreSQL password |
PG_DB |
PostgreSQL database name |
Three application charts live in helm/, each published to the GitLab project's OCI Helm registry during the publish-charts stage.
| Chart | Templates |
|---|---|
helm/backend/ |
Deployment, Service, Ingress |
helm/frontend/ |
Deployment, Service, Ingress |
helm/database/ |
StatefulSet, Service, PVC |
helm/monitoring-rbac/ |
Role, RoleBinding (for Prometheus pod discovery) |
Key values per chart (values.yaml):
image:
repository: <registry>/<image>
tag: latest
replicaCount: 1
ingress:
host: your-domain.examplehelmfile.yaml orchestrates all releases across two named environments.
database ──► backend ──► frontend
monitoring-rbac ──► prometheus
Environment files:
| File | Namespace | Replicas (FE/BE) |
|---|---|---|
environments/dev.yaml |
devschool-dev |
1 |
environments/prod.yaml |
devschool-prod |
2 |
Deploy manually:
# Dev
helmfile -e dev \
--state-values-set imageTag=<tag> \
--state-values-set helmRegistry=registry.gitlab.com/<group>/<project>/charts \
--state-values-set imageRegistry=registry.gitlab.com/<group>/<project> \
sync
# Prod
helmfile -e prod --state-values-set imageTag=<tag> ... syncUpdate helmRegistry and imageRegistry in environments/dev.yaml and environments/prod.yaml to match your GitLab project path.
Prometheus is deployed into the application namespace (same as the app) with minimal resource usage.
Configuration: helm/prometheus/values.yaml.gotmpl
Resource footprint: 50m CPU / 128Mi RAM requests. Alertmanager, node-exporter, kube-state-metrics and pushgateway are all disabled.
Scrape targets:
| Job | Service | Path |
|---|---|---|
backend |
backend-service:8080 |
/ |
frontend |
frontend-service:8081 |
/index.html |
Alerting rules:
| Alert | Expression | Severity |
|---|---|---|
BackendDown |
up{job="backend"} == 0 for 30s |
critical |
FrontendDown |
up{job="frontend"} == 0 for 30s |
critical |
BackendLowReplicas |
fewer than 2 healthy backend pods for 30s | warning |
FrontendLowReplicas |
fewer than 2 healthy frontend pods for 30s | warning |
Access Prometheus UI (port-forward):
kubectl port-forward svc/prometheus-server 9091:80 -n devschool-dev
# open http://localhost:9091Raw manifests in k8s/ are retained for reference. Active deployments use Helm charts via Helmfile (see above).
| File | Resource |
|---|---|
backend-deployment.yaml |
Backend Deployment |
frontend-deployment.yaml |
Frontend Deployment |
postgres-statefulset.yaml |
PostgreSQL StatefulSet with PVC |
services.yaml |
ClusterIP services for all three |
frontend-ingress.yaml |
Nginx Ingress for frontend |
secret.yaml |
DB credentials template (used with envsubst) |