Project 9 →Deployment of Tetris game on Kubernetes and Automating it with argo-cd and terraform via jenkins Pipeline

Aakib
17 min readJan 31, 2024

--

Project Intoduction

Today we are going to deploy 2 version of tetris game on aws EKS ckuster for this we are using terraform to create a base instance called the jenkins server than from this intance we setup pipeline for two version of tetris , which build docker image and push it to dockerhub than setup eks cluster and argo cd inside the cluster to deploy our application

Completion steps →

Step 1 → Setup Terraform and configure aws on your local machine

Step 2 → Building a simple Infrastructure from code using terraform

Step 3 → Setup Sonarqube and jenkins

Step 4 → ci-cd pipeline to build and push the image to docker hub

Step 5→ Update Image name In deployment repo

Step 6→EKS cluster creation

Step 7→Install Argo cd

Step 8 →Deploy Application with ArgoCD

Step 9 →Destruction

Step 1 → Setup Terraform and configure aws on your local machine

  1. open your terminal and make a separate folder for Tetris→mkdir tetris-game
  2. cd tetris-game
  3. clone the github repo
git clone https://github.com/Aakibgithuber/Tetris-gamev1.git

1. Setup Terraform

To install terraform copy and paste the below commands

sudo su
snap install terraform --classic
which terraform

2. Configure aws

1. Create an IAM user

click on iam

2. click on user →create user

3. Give a name to your user and tick on provide user access to management console and then click on I want an IAM user option

5. choose a password for your user →click next

6. Attach the policies directly to your iam user → click next

note →I will provide the administrator accesss for now but we careful while attaching the policies at your workapce

review and create user

7. click on create user

8. download your password file if it is autogenerated otherwise it is your’s choice

9. Now click on your IAM user →security credentials

10. scroll down to access keys and create an access keys

11.choose aws cli from the options listed

12. click next and download you csv file for username and password

13. go to your terminal and type →aws configure

14. Now it is ask to your access key and secret key for this open your csv file and paste the access and secret key and remain everything default

15. Now you are ready to configure aws from your terminal

Step 2 → Building a simple Infrastructure from code using terraform

  1. go to folder → cd Jenkins-terraform
  2. there are four files present main.tf, install_jenkins.sh , provider.tf, backend.tf
  3. open the file →vim Main.tf
  4. main.tf includes userdata which links install_jenkins.sh file on which execution install jenkins,docker,trivy,and start the sonarqube container on port 9000

Note →you need to edit the key_name and ami section according to your aws account

need to change this section

5. exit from the file and edit backend.tf →vim backend.tf

edit the bucket name and provide your aws bucket name

Now run terraform commands →

terraform init
terraform validate
terraform plan
terraform apply --auto-approve
terraform init and plan output let’s apply
terraform apply output

Go to your aws console and checkout the ec2 instances

Here we see Jenkins-Server instance is created by terraform with the given configuration

Step 3 → Setup Sonarqube and jenkins

1.Sonarqube →

copy the public ip of your machine

  1. go to your browser and type →<publicip>:9000

sonarqube window open

2. iniatially username and password is admin

3. update your password

4. welcome window of Sonarqube

2. Jenkins →

  1. on browser type →<public_ip>:8080

2. for this go to your ec2 and connect it

3. run the below commands

sudo su
cat /var/lib/jenkins/secrets/initialAdminPassword

output is your password and paste it to your jenkins

4. Install the suggested plugins

5. Setup your jenkins user

Welcome to jenkins dashboard

Step 4 → ci-cd pipeline to build and push the image to docker hub

1. Install Plugins listed below

  1. Terrform
  2. Eclipse Temurin Installer (Install without restart)
  3. SonarQube Scanner (Install without restart)
  4. NodeJs Plugin (Install Without restart)
  5. Parameterized Trigger (to trigger another pipeline if one completed)
  6. owasp →The OWASP Plugin in Jenkins is like a “security assistant” that helps you find and fix security issues in your software. It uses the knowledge and guidelines from the Open Web Application Security Project (OWASP) to scan your web applications and provide suggestions on how to make them more secure. It’s a tool to ensure that your web applications are protected against common security threats and vulnerabilities.
  7. Prometheus metrics →to moniter jenkins on grafana dashboard
  8. Download all the docker realated plugins

1. add credentials of Sonarqube and Docker

1st we genrate a token for sonarqube to use in jenkins credentials as secret text

a. setup sonarqube credentials

  1. go to http://publicip:9000
  2. now enter your username and password
  3. click on security →users →token →generate token
  4. token_name==sonar-token
your token is generated let’s go to jenkins

5. copy the token and go to your jenkins →manage jenkins →credentials →global →add credentials

6. select secret text from dropdown

7. secret text ==your token , id =sonar-token →click on create

b. setup projects in sonarqube for jenkins

  1. go to your sonarqube server
  2. click on projects
  3. in the name field type tetris
  4. click on set up
click on manually

Sonarqube project for jenkins is setup now

C. Now setup Webhooks for sonarqube

webhook in SonarQube is a way for SonarQube to notify or inform other systems or tools when something important happens. It’s like a virtual hand raising to say, “Hey, something noteworthy just occurred here!”

  1. Go to adiministration →configuration →webhooks

2. click on create and your webhook is created

Sonarqube is setup here

d. Setup docker credentials

  1. go to your jenkins →manage jenkins →credentials →global →add credentials
  2. provide your username and password of your dockerhub
  3. id==docker

credentials for both are setup

e. setup git credentials →click on me to see how to generate token in github

  1. Now copy that token from github and
  2. go to your jenkins →manage jenkins →credentials →global →add credentials
  3. provide your username and password of your github
  4. id==github
click on create

2. Now we are going to setup tools for jenkins

go to manage jenkins → tools

a. add jdk

  1. click on add jdk and select installer adoptium.net
  2. choose jdk 17.0.8.1+1version and in name section enter jdk 17

b. add node js

  1. click on add nodejs
  2. enter node16 in name section
  3. choose version nodejs 16.2.0

c. add docker →

  1. click on add docker
  2. name==docker
  3. add installer ==download from docker.com

d. add sonarqube →

  1. add sonar scanner
  2. name ==sonar-scanner

e. add owasp dependency check →

Adding the Dependency-Check plugin in the “Tools” section of Jenkins allows you to perform automated security checks on the dependencies used by your application

  1. add dependency check
  2. name == DP-Check
  3. from add installer select install from github.com

f. terraform

  1. go to manage jenkins →tools →search for terraform
  2. add terraform
  3. provide the name in the name field and untick the install automatically option and give the path /usr/bin/
  4. As terraform is installed in this section it takes it from there

5. click on apply and save

3. Configure global setting for sonarube

  1. go to manage jenkins →Configure global setting →add sonarqube servers
  2. name ==sonar-server
  3. server_url==http://public_ip:9000
  4. server authentication token == sonar-token→it is created in sonarqube security configurations

All the tools and configurations for jenkins are set up now let’s run the pipeline

4. pipeline script for building image and push it to dockerhub(Version1)

  1. click on new item and name it tetris image build and click on ok

2. scroll to pipeline script and paste the following script there

pipeline{
agent any
tools{
jdk 'jdk17'
nodejs 'node16'
}
environment {
SCANNER_HOME=tool 'sonar-scanner'
}
stages {
stage('clean workspace'){
steps{
cleanWs()
}
}
stage('Checkout from Git'){
steps{
git branch: 'main', url: 'https://github.com/Aakibgithuber/Tetris-gamev1.git'
}
}
stage("Sonarqube Analysis "){
steps{
withSonarQubeEnv('sonar-server') {
sh ''' $SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=TetrisVersion1.0 \
-Dsonar.projectKey=TetrisVersion1.0 '''
}
}
}
stage("quality gate"){
steps {
script {
waitForQualityGate abortPipeline: false, credentialsId: 'sonar-token'
}
}
}
stage('Install Dependencies') {
steps {
sh "npm install"
}
}
stage('OWASP FS SCAN') {
steps {
dependencyCheck additionalArguments: '--scan ./ --disableYarnAudit --disableNodeAudit', odcInstallation: 'DP-Check'
dependencyCheckPublisher pattern: '**/dependency-check-report.xml'
}
}
stage('TRIVY FS SCAN') {
steps {
sh "trivy fs . > trivyfs.txt"
}
}
stage("Docker Build & Push"){
steps{
script{
withDockerRegistry(credentialsId: 'docker', toolName: 'docker'){
sh "docker build -t tetrisv1 ."
sh "docker tag tetrisv1 aakibkhan1212/tetrisv1:latest "
sh "docker push aakibkhan1212/tetrisv1:latest "
}
}
}
}
stage("TRIVY"){
steps{
sh "trivy image aakibkhan1212/tetrisv1:latest > trivyimage.txt"
}
}
}
}
checkout the console output if any errors

Your image is build and push to dockerhub let’s see changes in dockerhub

5. pipeline script for building image and push it to dockerhub(Version2)

  1. for version 2 you only need to change the url of your repo

2. pipeline script for version 2

pipeline{
agent any
tools{
jdk 'jdk17'
nodejs 'node16'
}
environment {
SCANNER_HOME=tool 'sonar-scanner'
GIT_REPO_NAME = "Tetris-deployment-file"
GIT_USER_NAME = "Aakibgithuber"
}
stages {
stage('clean workspace'){
steps{
cleanWs()
}
}
stage('Checkout from Git'){
steps{
git branch: 'main', url: 'https://github.com/Aakibgithuber/tetris-gamev2.git'
}
}
stage("Sonarqube Analysis "){
steps{
withSonarQubeEnv('sonar-server') {
sh ''' $SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=tetrisv1 \
-Dsonar.projectKey=tetrisv1 '''
}
}
}
stage("quality gate"){
steps {
script {
waitForQualityGate abortPipeline: false, credentialsId: 'Sonar-token'
}
}
}
stage('Install Dependencies') {
steps {
sh "npm install"
}
}
stage('OWASP FS SCAN') {
steps {
dependencyCheck additionalArguments: '--scan ./ --disableYarnAudit --disableNodeAudit', odcInstallation: 'DP-Check'
dependencyCheckPublisher pattern: '**/dependency-check-report.xml'
}
}
stage('TRIVY FS SCAN') {
steps {
sh "trivy fs . > trivyfs.txt"
}
}
stage("Docker Build & Push"){
steps{
script{
withDockerRegistry(credentialsId: 'docker', toolName: 'docker'){
sh "docker build -t tetrisv2 ."
sh "docker tag tetrisv2 aakibkhan1212/tetrisv2:latest "
sh "docker push aakibkhan1212/tetrisv2:latest "
}
}
}
}
stage("TRIVY"){
steps{
sh "trivy image aakibkhan1212/tetrisv2:latest > trivyimage.txt"
}
}
stage('Checkout Code') {
steps {
git branch: 'main', url: 'https://github.com/Aakibgithuber/Tetris-deployment-file.git'
}
}
stage('Update Deployment File') {
steps {
script {
withCredentials([string(credentialsId: 'github', variable: 'GITHUB_TOKEN')]) {
NEW_IMAGE_NAME = "aakibkhan1212/tetrisv1:latest"
sh "sed -i 's|image: .*|image: $NEW_IMAGE_NAME|' deployment.yml"
sh 'git add deployment.yml'
sh "git commit -m 'Update deployment image to $NEW_IMAGE_NAME'"
sh "git push @github.com/${GIT_USER_NAME}/${GIT_REPO_NAME">https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main"
}
}
}
}
}
}
your V2 image is also build and push
Here’s is your two version of tetris

Step 5→ Update Image name In deployment repo

Everything is done now we need to update the image name in my second repository that is used for creating pod inside our Elastic kubernetes cluster

  1. go to →https://github.com/Aakibgithuber/Tetris-deployment-file/blob/main/deployment.yml

2. you need to automate that when image is build and push by above pipeline than it is automatically update the image name here with the image name created by above pipeline

3. So for that we need to create another pipeline and use the triggerd option means when one pipeline succesfully complete which push the image to dockerhub than it triggers to another pipeline which is than update the image name in the tetris deployment repository

#add inside environment
environment {
GIT_REPO_NAME = "Tetris-deployment-file"
GIT_USER_NAME = "Aakibgithuber" # change your Github Username here
}

# add these stages after trivy image scan
stage('Checkout Code') {
steps {
git branch: 'main', url: 'https://github.com/Aakibgithuber/Tetris-deployment-file.git'
}
}
stage('Update Deployment File') {
steps {
script {
withCredentials([gitUsernamePassword(credentialsId: 'github', gitToolName: 'Default')]){
NEW_IMAGE_NAME = "aakibkhan1212/tetrisv1:latest" #update your image here
sh "sed -i 's|image: .*|image: $NEW_IMAGE_NAME|' deployment.yml"
sh 'git add deployment.yml'
sh "git commit -m 'Update deployment image to $NEW_IMAGE_NAME'"
sh "git push @github.com/${GIT_USER_NAME}/${GIT_REPO_NAME">https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main"
}
}
}
}

Or you could also build a single pipeline for all that

Full pipeline script below →

pipeline{
agent any
tools{
jdk 'jdk17'
nodejs 'node16'
}
environment {
SCANNER_HOME=tool 'sonar-scanner'
GIT_REPO_NAME = "Tetris-deployment-file"
GIT_USER_NAME = "Aakibgithuber"
}
stages {
stage('clean workspace'){
steps{
cleanWs()
}
}
stage('Checkout from Git'){
steps{
git branch: 'main', url: 'https://github.com/Aakibgithuber/Tetris-gamev1.git'
}
}
stage("Sonarqube Analysis "){
steps{
withSonarQubeEnv('sonar-server') {
sh ''' $SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=tetrisv1 \
-Dsonar.projectKey=tetrisv1 '''
}
}
}
stage("quality gate"){
steps {
script {
waitForQualityGate abortPipeline: false, credentialsId: 'Sonar-token'
}
}
}
stage('Install Dependencies') {
steps {
sh "npm install"
}
}
stage('OWASP FS SCAN') {
steps {
dependencyCheck additionalArguments: '--scan ./ --disableYarnAudit --disableNodeAudit', odcInstallation: 'DP-Check'
dependencyCheckPublisher pattern: '**/dependency-check-report.xml'
}
}
stage('TRIVY FS SCAN') {
steps {
sh "trivy fs . > trivyfs.txt"
}
}
stage("Docker Build & Push"){
steps{
script{
withDockerRegistry(credentialsId: 'docker', toolName: 'docker'){
sh "docker build -t tetrisv1 ."
sh "docker tag tetrisv1 aakibkhan1212/tetrisv1:latest "
sh "docker push aakibkhan1212/tetrisv1:latest "
}
}
}
}
stage("TRIVY"){
steps{
sh "trivy image aakibkhan1212/tetrisv1:latest > trivyimage.txt"
}
}
stage('Checkout Code') {
steps {
git branch: 'main', url: 'https://github.com/Aakibgithuber/Tetris-deployment-file.git'
}
}
stage('Update Deployment File') {
steps {
script {
withCredentials([string(credentialsId: 'github', variable: 'GITHUB_TOKEN')]) {
NEW_IMAGE_NAME = "aakibkhan1212/tetrisv1:latest"
sh "sed -i 's|image: .*|image: $NEW_IMAGE_NAME|' deployment.yml"
sh 'git add deployment.yml'
sh "git commit -m 'Update deployment image to $NEW_IMAGE_NAME'"
sh "git push @github.com/${GIT_USER_NAME}/${GIT_REPO_NAME">https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main"
}
}
}
}
}
}

4. click on build

your repo name is update let’s go to see changes in github
here is the changes
Here we see the updated image name

Step 6→EKS cluster creation

1. Create cluster with terraform using jenkins

  1. go to new item in jenkins and name it eks terraform
  2. choose the pipeline from the listing and click ok

3. After that tick on This project is parameterised which enables you to run your your pipeline in two ways first commmand is apply to create infrastructure and second is destroy to delete all infrastructure after pipeline runs

4. click on add parameter →choice parameter →provide name and then two commands apply and destroy

set these two commands

4. pipeline script

  1. Paste the below code to pipeline script section
pipeline{
agent any
stages {
stage('Checkout from Git'){
steps{
git branch: 'main', url: 'https://github.com/Aakibgithuber/Tetris-gamev1.git'
}
}
stage('Terraform version'){
steps{
sh 'terraform --version'
}
}
stage('Terraform init'){
steps{
dir('Eks-terraform') {
sh 'terraform init'
}
}
}
stage('Terraform validate'){
steps{
dir('Eks-terraform') {
sh 'terraform validate'
}
}
}
stage('Terraform plan'){
steps{
dir('Eks-terraform') {
sh 'terraform plan'
}
}
}
stage('Terraform apply/destroy'){
steps{
dir('Eks-terraform') {
sh 'terraform ${Action} --auto-approve'
}
}
}
}
}

2. click on apply and save

3. on clicking on Build with parmaters option you will see two option apply and destroy as explained above

4. select apply and click on build

5. It takes about 15 to 20 mins to build a cluster

here is my cluster and ec2 instance

2. Create cluster without terraform

Note!! use this step if you don’t want to use jenkins pipeline for eks cluster creation

  1. In your base ec2 run the below command
eksctl create cluster --name EKS_CLOUD --region ap-south-1 --node-type t2.medium --nodes-min 1 --nodes-max 2
it takes 15–20 mins for cluster creation
aws eks update-kubeconfig --region ap-south-1 --name EKS_CLOUD

Step 7→Install Argo cd

Argo CD is a tool that helps software developers and teams manage and deploy their applications to Kubernetes clusters more easily. It simplifies the process of keeping your applications up to date and in sync with your desired configuration by automatically syncing your code with what’s running in your Kubernetes environment. It’s like a traffic cop for your chmod 700 get_helm.shapplications on Kubernetes, ensuring they are always in the right state without you having to manually make changes.

First we need to install helm →Install helm

snap install helm --classic
  1. Add the Argo CD Helm repository:
helm repo add argo-cd https://argoproj.github.io/argo-helm

2. Update your Helm repositories:

helm repo update

3. Create a namespace for Argo CD (optional but recommended):

kubectl create namespace argocd

4. Install Argo CD using Helm:

helm install argocd argo-cd/argo-cd -n argocd

5. To see installation of argocd run

kubectl get all -n argocd

Expose argocd-server

By default argocd-server is not publicaly exposed. For the purpose of this workshop, we will use a Load Balancer to make it usable:

kubectl patch svc argocd-server -n argocd -p ‘{“spec”: {“type”: “LoadBalancer”}}’
snap install jq
export ARGOCD_SERVER=`kubectl get svc argocd-server -n argocd -o json | jq --raw-output '.status.loadBalancer.ingress[0].hostname'`
echo $ARGOCD_SERVER

you have given a url copy and paste it on your chrome browser

username ==admin

For Password →

export ARGO_PWD=`kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath=”{.data.password}” | base64 -d`
echo $ARGO_PWD
  1. output == password for argocd

copy and paste the password on argocd page and you are logged in

Step 8 →Deploy Application with ArgoCD

Sign into argo cd using above steps →

  1. go to setting →repositories →connect repo

select these options and on repo url copy n paste below github url https://github.com/Aakibgithuber/Tetris-deployment-file.git

2. click on connect output →successful

3. Now go to application →newapp

4. select the above options and click on create

5. Now click on sync →force →sync →ok

6. click on tetris-service →details

7.copy the load balancer ingress url and paste it to web browser

run the below command and open the listed port

kubectl get all
open 30561 port no.

8. This is the version 1 of application for version 2

  1. go to your github and locate the deployment repo and change the image name in deployment.yaml file

2. change the image name from v1 to v2

3. go to your argo cd and click on sync →force →sync →ok

here are the changes says that i had updated the deployment.yaml

4. now again refresh the load balancer ingress

click on start

Here is our new version of game
our both version of game is deployed now let’s destroy all the resources

Step 9 →Destruction

  1. Deletion of app in argo cd

2. Delete argo cd from terminal of jenkins server node

kubectl delete svc argocd-server -n argocd

3. Now delete the EKS cluster (two ways )

  1. delete using jenkins pipeline by terraform
click on build

2. delete from terminal if you have used aws cli to create → Cluster run the following command on jenkins server node

eksctl delete cluster --name EKS_CLOUD--region ap-south-1
aws cloudformation delete-stack --stack-name eksctl-EKS_CLOUD

4. delete the base EC2 or jenkins server → go to your terminal and run the

terraform destroy --auto-approve

Here’s is out project completed see you in next project

do clap if you liked it and

follow me on linkedin

follow me on github

--

--

Aakib

Cloud computing and DevOps Engineer and to be as a fresher I am learning and gaining experiance by doing some hands on projects on DevOps and in AWS OR GCP