Project 9 →Deployment of Tetris game on Kubernetes and Automating it with argo-cd and terraform via jenkins Pipeline
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
- open your terminal and make a separate folder for Tetris→mkdir tetris-game
- cd tetris-game
- 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
- go to folder → cd Jenkins-terraform
- there are four files present main.tf, install_jenkins.sh , provider.tf, backend.tf
- open the file →vim Main.tf
- 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
5. exit from the file and edit backend.tf →vim backend.tf
Now run terraform commands →
terraform init
terraform validate
terraform plan
terraform apply --auto-approve
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
- 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 →
- 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
Step 4 → ci-cd pipeline to build and push the image to docker hub
1. Install Plugins listed below
- Terrform
- Eclipse Temurin Installer (Install without restart)
- SonarQube Scanner (Install without restart)
- NodeJs Plugin (Install Without restart)
- Parameterized Trigger (to trigger another pipeline if one completed)
- 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.
- Prometheus metrics →to moniter jenkins on grafana dashboard
- 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
- go to http://publicip:9000
- now enter your username and password
- click on security →users →token →generate token
- token_name==sonar-token
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
- go to your sonarqube server
- click on projects
- in the name field type tetris
- click on set up
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!”
- Go to adiministration →configuration →webhooks
2. click on create and your webhook is created
Sonarqube is setup here
d. Setup docker credentials
- go to your jenkins →manage jenkins →credentials →global →add credentials
- provide your username and password of your dockerhub
- id==docker
credentials for both are setup
e. setup git credentials →click on me to see how to generate token in github
- Now copy that token from github and
- go to your jenkins →manage jenkins →credentials →global →add credentials
- provide your username and password of your github
- id==github
2. Now we are going to setup tools for jenkins
go to manage jenkins → tools
a. add jdk
- click on add jdk and select installer adoptium.net
- choose jdk 17.0.8.1+1version and in name section enter jdk 17
b. add node js
- click on add nodejs
- enter node16 in name section
- choose version nodejs 16.2.0
c. add docker →
- click on add docker
- name==docker
- add installer ==download from docker.com
d. add sonarqube →
- add sonar scanner
- 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
- add dependency check
- name == DP-Check
- from add installer select install from github.com
f. terraform
- go to manage jenkins →tools →search for terraform
- add terraform
- provide the name in the name field and untick the install automatically option and give the path /usr/bin/
- As terraform is installed in this section it takes it from there
5. click on apply and save
3. Configure global setting for sonarube
- go to manage jenkins →Configure global setting →add sonarqube servers
- name ==sonar-server
- server_url==http://public_ip:9000
- 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)
- 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"
}
}
}
}
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)
- 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"
}
}
}
}
}
}
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
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
Step 6→EKS cluster creation
1. Create cluster with terraform using jenkins
- go to new item in jenkins and name it eks terraform
- 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
4. pipeline script
- 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
2. Create cluster without terraform
Note!! use this step if you don’t want to use jenkins pipeline for eks cluster creation
- 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
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
- 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
- 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 →
- 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
8. This is the version 1 of application for version 2
- 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
4. now again refresh the load balancer ingress
Here is our new version of game
our both version of game is deployed now let’s destroy all the resources
Step 9 →Destruction
- 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 )
- delete using jenkins pipeline by terraform
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