Set up the entire DevOps cycle for an expense tracking Web Application using acquired best practices.
Expensy is a full-stack expense tracking application consisting of multiple services built with different languages and technologies, simulating real-world scenarios where various components interact within a microservices architecture. The application includes:
Component | Description |
---|---|
Frontend | Built with Next.js – web interface |
Backend | Built with Node.js/Express – API logic |
MongoDB | Persistent data storage |
Redis | In-memory cache for speed |
- Apply DevOps practices to build and manage a full-stack application in a production-grade environment
- Design and implement a CI/CD pipeline using GitHub Actions to automate application delivery
- Containerize frontend and backend services using Docker
- Deploy and orchestrate containerized applications using Kubernetes on Azure Kubernetes Service (AKS) or EKS.
- Configure NGINX Ingress for routing external HTTPS traffic to internal microservices, secured with TLS certificates.
- Set up real-time monitoring and dashboards using Prometheus and Grafana
- Version control project Architecture diagrams (optional)
Here is a simplified deployment architecture with one replica for each microservice for presentation purpose.
- Node.js & npm installed
- MongoDB & Redis running (local or containers)
- Docker installed
- Account on the DockerHub registry. This account will be used to host docker images
- Account with any cloud platform of your choice (AWS, Azure or Hybrid), a free-trial or an account with enough credit
npm install
npm run build
docker run --name redis -d -p 6379:6379 redis:latest redis-server --requirepass someredispassword
docker run --name mongo -d -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=example mongo:latest
npm install
npm run dev
- Frontend: use
NEXT_PUBLIC_*
for variables that need to be exposed to the browser. - Backend: store secrets like
DATABASE_URI
,REDIS_PASSWORD
, etc. in a.env
file or in your CI/CD pipeline secret store.
Remember that environment variables set in your server take precedence (priority) over the .env
files.
Containerized the backend and frontend services using Docker. Each Dockerfile defines the build process and runtime for the respective services. To manage and run all services (frontend,backend, redis, and mongodb) together (for single-machine deployments), create a docker-compose.yml file in root directory of the Microservices project. It sets up networks and volumes, ensuring seamless communication between containers.
docker compose up -d --build
This will:
Start Redis and Mongodb Build and run frontend and backend.
Access the Application: Visit http://localhost:3000 to see the expensy app running in a Dockerized setup.
Automated AKS Cluster deployment via bicep configs:
- Create-rg.bicep
Deploy this at the subscription level:
az deployment sub create \
--location uaenorth \
--template-file create-rg.bicep
- Create aks-cluster.bicep
Deploy it at the resource group level:
az deployment group create \
--resource-group expensyAksRG \
--template-file aks-cluster.bicep \
--parameters sshPublicKey="$(cat ~/.ssh/id_rsa.pub)"
If necessary:
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
- Connect to the AKS cluster
az aks get-credentials --resource-group expensyAksRG --name expensyAksCluster
Infrastructure files can be found under /k8s/infra/
.
Create Deployment and Service manifests for each microservice and Statefulsets for MongoDB and Redis.
Container images are referenced from Docker Hub and environment variables are passed via Secrets.
Kubernetes manifests can be found under k8s/
.
GitHub Actions workflow is defined at:
.github/workflows/CI-pipeline.yaml .github/workflows/CD-pipeline.yaml
This project uses GitHub Actions to automate Docker image build, push and deployment to Kubernetes cluster for both frontend and backend.
Once the CI-CD pipelines runs successfully, confirm:
All Deployments and Pods are running:
kubectl get deployments -n expensy
kubectl get pods,svc -n expensy
For stateulsets, check if PV is bound:
kubectl get pvc -n expensy
The NGINX Ingress provides an external IP or DNS address (if domain is purchased and linked):
kubectl get ingress -n expensy
Access the app: http://<INGRESS_IP> or http://
Test the flow: Add expense and see if the expense data is stored.
Configured Prometheus to scrape infrastructure and App metrics.
- Used Prometheus's node-exporter to scrape system level metrics.
- Used ServiceMonitor to scrap metrics exposed by backend.
Garafana dashboards to visualize infrastructure and App metrics are created and can be found under /monitoring/
Alerts are set up based on business, technical as well as resource usage to proactively respond to issues. Prometheus is configured with alerting rules to define the conditions under which alerts should be fired and linked to Grafana dashboards.
Cluster nodes and Container logs are available in Azure Monitor (AKS).
- Secrets are managed via Kubernetes Secrets
- IAM roles used for cloud services access following principle of least privilege (PoLP)
- CI/CD uses Github secrets to store sensitive information
- The deployed project is accessible over HTTPS using a trusted SSL certificate issued via Certbot and renewed automatically using scheduled Cron jobs.
See
SECURITY.md
for details.