Freshers' guide for deploying a three-tier Application on GKE

Rajarshi MandalRajarshi Mandal
5 min read

Overview:

In this project, we guide you to create an automated CI/CD pipeline for deploying a multi-tier application. This ensures good deployment frequency, reduced Lead Time, minimal fail percentage, and negligible failed deployment recovery time by using vendor-provided monitoring and alert systems, conforming to DORA standards.

Assumption:

You have :

  1. Docker on your machine. If not, follow the Docker official guide.

  2. Jenkins account. If not, follow the Jenkins official guide.

  3. GCP account. If not, follow the GCP official guide.

  4. SonarQube. If not, follow the SonarQube official guide.

  5. NeuVector. If not, follow the NeuVector official guide.

Technologies used:

Git and Git Hub: Used for version control.

Docker: Used for Containerize the application.

Jenkins: Automating the CI/CD pipeline with maven.

Google Artifact Registory: To store Docker images (you can have docker hub as well).

GKE: It is used for deploying Containerized application.

Sonar & NeuVector: Security

Base Image: Frontend: React; Backend: Java; Detabase: Postgres

Workflow:

Local Testing:

  1. Before containerizing an application, it is necessary to check whether it works locally.

  2. To run this application locally, clone the repository and execute these commands.

git clone git@github.com:rajarshigit2441139/track_your_money.git
cd track_your_money/raj_tym_infra
chmod 755 localrun.sh
./local_run.sh

  • After local testing, execute the following command to stop the DB container.
docker rm -f postgres

Container Testing:

  • For containerization, we will use Docker.

  • For each tier, create a Dockerfile.

  • A Docker compose is created to run the whole application.

Frontend Dockerfile:

cd ../raj_tym_fe
docker build -t fe_docker_local .
docker run -p 5173:5173 -d fe_docker_local

Backend Dockerfile:

cd ../raj_tym_api
docker run --name postgres -e POSTGRES_USER=tym_user -e POSTGRES_PASSWORD=app_password -e POSTGRES_DB=track_your_money -p 5432:5432 -d postgres
docker build -t be_docker_local .
docker run -p 8080:8080 -d be_docker_local

Docker compose (docker-compose.yml):

Be aware:

  1. Frontend is running on port 5173(Vite default port).

  2. API handles the backend process for the frontend, so it is dependent on it(Line 26).

  3. Line 10: It will call the API on localhost:8080 (Java backend running on this port).

  4. API (backend) will run on port 8080 (spring-boot default port).

  5. From lines 21 to 25, the backend configuration for the database.

  6. Lines 31 to 41 are database configuration.

  7. You may optionally use - postgres_data:/var/lib/postgresql/data it as a volume. If you use it, data will be retained on your machine.

  8. Line 43 is a Docker network, providing connectivity between tiers.

# run docker compose
cd ../raj_tym_infra
docker compose up

  • After checking, follow this command to stop the application.
docker compose down

Jenkins:

CI / CD:

  1. My mentor provides a comprehensive Jenkins setup, enabling me to focus on deploying the application.

  2. Line 15: authenticating Artifact Registry.

  3. Line 16: Build Docker Image and use git branch name as tag. “env.GIT_BRANCH” is a variable that picks up the git branch (from which code is pushed) name as a value.

  4. Line 17: push the same image to the Google Artifact registry.

  5. I use minimal stages to complete the deployment. This is a shift-left approach where all checks are done before publishing to the git/artifact repositories.

  6. I use us-central1-docker.pkg.dev/devops-353009/devops-docker/raj_tym_api as a name.

  7. us-central1-docker.pkg.dev/devops-353009/devops-docker Is my Google Artifact Registry (Docker) address. Change it with your Artifact/domain/dockerhub address.

  8. GKE pulls the Image from this address.

Another important fact is the use of Google Artifact Registry instead of a Docker repository. The reason being, the less we connect with third-party services, the less our cost will be (Egress/Ingress).

Shift-Left approach:

  1. Lines 53 to 83: Jacoco and Sonar are added as plugins to the pom.xml to perform SAST scan.

  2. If test cases fail, the application will not be built.

Deployment on K8s:

  • All deployment-related Kubernetes manifests are stored in the raj_tym_infra repository.
cd ../raj_tym_infra

ingress.yaml:

  1. We will use Nginx Ingress Controller. It will perform the routing for the application.

  2. Lines 9 to 12: This tls: section is provisioning of HTTPS certificates for the host tym.rajarshi.agileguru.org.

  3. Lines 13 to 30: for routing.

  4. - pathType: Prefix : indicates the base path is after the hostname.

  5. The path is unique to ensure routing to associated services.

service.yaml:

  1. Kubernetes automatically creates an internal DNS record named tymfe.default.svc.cluster.local (namespace = default)

  2. Pods inside the cluster will connect to this Service using the name tymfe.default.svc.cluster.local

  3. If a request comes to “/“, it will be forwarded to the frontend pod port on 5173

  4. If a request comes to “/api“, it will be forwarded to the backend pod on port 8080.

deployment.yaml:

  1. This deployment is a multi-container pod hosting the frontend and backend for simplicity.

  2. lines 19 and 20: environment value enables frontend (browser) access to the API using AJAX requests to the path on the same host https://tym.rajarshi.agileguru.org.

  3. Line 22: Frontend is running on port 5173 (Vite application default port) and context-path “/”

  4. Inside side backend container from line 23 to 34, the database is configured for the backend.

  5. Change each env value as per your configuration.

  6. Line 36: backend running on port 8080 and context-path “/api”(spring-boot default port).

Deployment procedure:

kubectl apply -f deploy.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

LINK: tym.rajarshi.agileguru.org (It is temporary)

Security:

  1. At first application build failed for code quality and some silly errors. So I use Sonar plugins to identify and fix them.

  2. I also use NeuVector to search for vulnerabilities. It is showing a low amount of vulnerabilities, which is good to go.

Conclusion:

After completing this project, I gained knowledge about

  1. Development workflow optimization.

  2. Shift-left approach to avoid pushing bugs and vulnerabilities into the git repo.

  3. Creating and maintaining containers with Jenkins and Google Artifact Registry.

  4. Easy deployment on GKE.

  5. Cost optimization using a private address to access the database.

Get in touch:

Github: https://github.com/rajarshigit2441139

LinkedIn: www.linkedin.com/in/rajarshi-mandal-b79307189

mail: rajarshi.official99@gmail.com

0
Subscribe to my newsletter

Read articles from Rajarshi Mandal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rajarshi Mandal
Rajarshi Mandal

Passionate DevOps enthusiast from India with a strong foundation in technology and a drive for automation. I bring proven expertise across a broad range of technical domains, from cloud infrastructure to container orchestration. My journey in the tech industry has been fueled by a constant eagerness to learn, innovate, and make a meaningful impact within the DevOps community.