Deploy Kubernetes Apps with Jenkins
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.
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
- Create one Docker Image from the Dockerfile of our application
- Push Docker image into AWS ECR
- Fetching this Docker image and deploying our application
- 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 URL → http://<jenkins_ec2_IP>:8080/github-webhook/
Content type → application/json
Which events would you like to trigger this webhook? → Just the push event
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
.
- Docker Pipeline
- Amazon ECR
- 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
- Create an Access Token by navigating to GitHub → Settings → Developer Settings → Personal access tokens (classic) → Generate new token (classic).
- 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 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.
Step 7: Create Jenkins Pipeline
- Go to your Jenkins console.
- Add item → Name your pipeline → Select Pipeline.
- In the Build Triggers section, check the
“GitHub hook trigger for GITScm polling”
option. - 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
Step 6: Application Setup
In our case, we have a total of 5 files with different purposes,
- index.html → contains application data
- Dockerfile → Use to create App image that we are pushing in ECR
- Jenkinsfile → Used for CI/CD to deploy automatically image to ECR and using that ECR image to deploy our application.
- deployment.yaml → Kubernetes deployment definition file that deploys our app in EKS
- 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.
- To check our application, enter the load balancer endpoint that is created after the pipeline is completed.
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 🛠️