Deploy Kubernetes Apps with Jenkins

Dhruv Mavani
7 min readMay 11, 2024

--

In this blog, we can deep-dive into deploying our application on Kubernetes with Jenkins CI/CD. So, if we update our application code and push it onto GitHub, it will automatically deploy our application on Kubernetes.

Deploying Kubernetes with Jenkins

How does it work?

When you push code to gitHub, it triggers a webhook that initiates a CI/CD process in Jenkins. Jenkins then automatically deploys your application on Kubernetes.

Workflow for Deploying Applications in Kubernetes with Jenkins

  1. Create one Docker Image from the Dockerfile of our application
  2. Push Docker image into AWS ECR
  3. Fetching this Docker image and deploying our application
  4. Expose our application to external users using a load balancer service

Let’s deploy our app in Kubernetes with Jenkins

Pre-requisites:

Before we begin, ensure you have the following:

  • EKS cluster
  • Jenkins is setup
  • AWS CLI installed and configured on Jenkins EC2
  • EKS is accessible through Jenkins EC2 using Kubectl
  • Nginx is installed
  • Docker Installed

Follow the steps outlined below to seamlessly deploy application in kubernetes with Jenkins:

Step 1: Create an empty private git repository

In this repository, we store our application code, Dockerfile, Jenkinsfile, and all the necessary files.
Make sure to upload all the code mentioned in the further steps, and ensure that you can upload the Jenkinsfile and Dockerfile to the root directory.

Step 2: Set up a webhook on GitHub

The webhook functions like a postman in our deployment process; it notifies Jenkins to trigger the pipeline whenever we push code to our Git repository.

To create a webhook, navigate to your Git repository → settings → on the left sidebar, locate Webhooks and click to open it → add a webhook and follow this configuration,

Payload URLhttp://<jenkins_ec2_IP>:8080/github-webhook/

Content typeapplication/json

Which events would you like to trigger this webhook?Just the push event

Webhook Creation

Step 3: Configure an EKS cluster on our Jenkins EC2 server

Jenkins needs to authenticate our EKS cluster to deploy our application on it. For that, we move the .kube and .aws directories from the root directory to our Jenkins directory.

SSH into your jenkins EC2 and perform this,

cd /home/ubuntu/
sudo mv .kube /var/lib/jenkins/

#For reading permissions
sudo chown -R jenkins:jenkins /var/lib/jenkins/.kube/
sudo mv .aws /var/lib/jenkins
sudo service jenkins restart

Step 4: Set up an AWS ECR private repository to store docker images

Go to AWS accounts → ECR service → create an ECR Private Repository with a chosen name.

Step 5: Install important plugins so Jenkins can communicate with EKS

Installed the following list of plugins from the Jenkins console by navigating to Manage Jenkins → Plugins → Available Plugins.

  1. Docker Pipeline
  2. Amazon ECR
  3. AWS Credentials

Step 6: Jenkins Credentials Configuration

We need to configure two sets of credentials: one for accessing the GitHub private repository so that our Jenkins pipeline can access it, and another for AWS credentials.

Configure Github Credentials

  1. Create an Access Token by navigating to GitHub → Settings → Developer Settings → Personal access tokens (classic) → Generate new token (classic).
  2. Configure Github credentials by navigating to Manage Jenkins → Credentials → System → Global credentials (unrestricted) → Add Credentials and below configurations,
  • Kind: Username with password
  • Scope: Global (Jenkins, nodes, items, all child items, etc)
  • Password: <pate_your_access_token>

Note: You may skip other fields.

Configure Github Credentials

Configure AWS Credentials

Here, we need to configure our AWS credentials and other settings so that our Jenkins can seamlessly communicate with EKS and deploy our application.

Configure AWS credentials by navigating to Manage Jenkins → Credentials → System → Global credentials (unrestricted) → Add Credentials and below configurations,

  • Kind: AWS Credentials
  • Scope: Global (Jenkins, nodes, items, all child items, etc)
  • ID: AWS-Credentials
  • Access Key ID: <your_aws_access_key>
  • Secret Access Key: <your_aws_secret_key>

Note: Provide the Access Key ID and Secret Access Key of the AWS user used to create the EKS. If you created the EKS using the root user of AWS, then generate these keys directly by navigating to the right corner → Security credentials. If you are using an IAM user to create EKS, then generate these keys from IAM.

Configure AWS Credentials

Step 7: Create Jenkins Pipeline

  1. Go to your Jenkins console.
  2. Add item → Name your pipeline → Select Pipeline.
  3. In the Build Triggers section, check the “GitHub hook trigger for GITScm polling” option.
  4. In Pipeline section do below configutaion,
  • Definition: Pipeline script from SCM
  • SCM: Git
  • Repository URL: <Provide your githup repo link that we create in 1st step>
  • Credentials: select the Credentials that we created in step-6 in “Configure Github Credentials”.
  • Branch Specifier: <your_branch>
  • Script Path: Jenkinsfile
Pipeline settings

Step 6: Application Setup

In our case, we have a total of 5 files with different purposes,

  1. index.html → contains application data
  2. Dockerfile → Use to create App image that we are pushing in ECR
  3. Jenkinsfile → Used for CI/CD to deploy automatically image to ECR and using that ECR image to deploy our application.
  4. deployment.yaml → Kubernetes deployment definition file that deploys our app in EKS
  5. service.yaml → load balancer type service used to expose our application to external user
  • index.html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>K8 Deployment with Jenkins</title>
</head>
<body>
<h1>Dhruv Mavani!!</h1>
</body>
</html>
  • Dockerfile
# Use the official Nginx image as base
FROM nginx:latest

# Copy the custom index.html file into the Nginx document root
COPY index.html /usr/share/nginx/html

# Expose port 80 to the outside world
EXPOSE 80
  • Jenkinsfile

Make sure you change the REGION-CODE, ECR-REPO-LINK, Your-IMG-NAME in this file.

pipeline {
agent any

environment {
AWS_REGION = '<REGION-CODE>'
ECR_REPO = '<ECR-REPO-LINK>'
DOCKER_IMAGE_NAME = '<Your-IMG-NAME>'
KUBECONFIG = "/var/lib/jenkins/.kube/config" //locate in jenkins EC2 serevr
}

stages {
stage('Build Docker Image') {
steps {
script {
// Build Docker image
docker.build("$DOCKER_IMAGE_NAME:${env.GIT_COMMIT}")
}
}
}

stage('Tag Docker Image') {
steps {
script {
// Tag Docker image using Docker command directly
sh "docker tag $DOCKER_IMAGE_NAME:${env.GIT_COMMIT} $ECR_REPO:${env.GIT_COMMIT}"
}
}
}


stage('Push to ECR') {
steps {
script {
// Authenticate Docker client to ECR using AWS CLI
withCredentials([aws(credentialsId: 'AWS-Credentials', region: AWS_REGION)]) {
sh "aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_REPO"
}

// Push Docker image to ECR
sh "docker push $ECR_REPO:${env.GIT_COMMIT}"
}
}
}

stage('Deploy to EKS') {
steps {
script {
// Set KUBECONFIG environment variable
withEnv(["KUBECONFIG=${KUBECONFIG}"]) {
// Get the latest image tag from the GIT_COMMIT environment variable
def imageTag = env.GIT_COMMIT

// Replace the placeholder ${IMAGE_TAG} in deployment.yaml with the actual image tag
sh "sed -i 's|\${IMAGE_TAG}|${imageTag}|' deployment.yaml"

// Apply deployment.yaml to the EKS cluster
sh "kubectl apply -f deployment.yaml"
sh "kubectl apply -f service.yaml"
}
}
}
}
}
}
  • deployment.yaml

Make sure you change the ECR-REPO-LINK in this file.

apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-app
spec:
replicas: 2
selector:
matchLabels:
app: DemoApp
template:
metadata:
labels:
app: DemoApp
spec:
containers:
- name: hello-app-container
image: <ECR-REPO-LINK>:${IMAGE_TAG}
imagePullPolicy: Always
ports:
- containerPort: 80
  • service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-app-service
spec:
selector:
app: DemoApp
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer

Step 7: Run Pipeline

Now all setup and we can run our pipeline,
You can push this all file in github repostiry that we created in 1st step and our pipeline is runned suucfully.

Make sure to push your Jenkinsfile and Dockerfile directly into the root folder of project.

Jenkins Pipeline
  • To check our application, enter the load balancer endpoint that is created after the pipeline is completed.
Output of first pipleline

Now, finally, we have successfully deployed our application in Kubernetes with Jenkins. Whenever you make changes to the code in your application, such as the index.html file, and push it to GitHub, our CI/CD pipeline runs automatically and deploys the application on Kubernetes.

If you found this blog helpful, clap 👏 and share 🔗 in your network!

Conclusion

We utilized the webhook provided by GitHub to detect changes in code and different plugins to authenticate our Jenkins with EKS. We implemented commit-based logic in our Jenkins pipeline, ensuring that each Docker image is tagged with the commit ID and dynamically updated in the deployment file using the sed command during our pipeline run.

Connect With Me

Catch me on LinkedIn for more insights and discussions! Together, let’s navigate the intricate world of AWS, cloud strategies, Kubernetes, and beyond. Connect with me to exchange ideas, seek advice, or simply to say hello. 🌐

Happy deploying! 🚀

Happy Kubernetings! ⎈

Happy Jenkins 🛠️

--

--

Dhruv Mavani
Dhruv Mavani

Written by Dhruv Mavani

👨‍💻 DevOps Engineer Writing about DevOps and cloud topics, including Docker, Kubernetes, deployment, and more. https://www.linkedin.com/in/dhruv-mavani/

No responses yet