Wednesday, June 12, 2024

 

CANARY DEPLOYMENTS WITH KUBERNETES AND JENKINS

Today we'll look at canary deployments with Kubernetes. Your team is building an application, but there were some recent deployments that introduced bugs. They tested and tested and tried to ensure that no bugs, but unfortunately anytime they deploy the application they still have some bugs.

Now we want to mitigate these kinds of issues, therefore the team has requested you to develop a Canary deployment. That means that when we want to deploy new code, we will actually release that code into production to a portion of our user base, so it will not be used by everyone, but a certain percentage of people will be using the new code even if they are unaware of it, and once we verify that everything is up and running and everything looks good with that code, we will proceed to roll it out to the entire population. Our application is presently running on a Kubernetes cluster, and the team is using a Jenkins pipeline to execute continuous integration and deployments, thus we will need to add lo`gic to this existing pipeline to accomplish the Canary deployment.

SETUP YOUR CODE REPO AND JENKINS

Ø  First, we need to go to this code and fork the repo: https://github.com/ACloudGuru-Resources/cicd-pipeline-train-schedule-canary.

Ø  After creating your personal fork, edit the Jenkinsfile and put in your DockerHub username.

Ø  Log Into our Jenkins Server

 

SET UP OUR JENKINS CREDENTIALS

Select Manage Jenkins > Credentials from the menu.

From the single credential present, click on global, then Add Credentials.

Enter your personal GitHub user name in the Username section.

Copy your Github token, and back in Jenkins, paste the token into the Password field.

Set the ID to github_key and the Description to GitHub Key.

Click Create.

 

ADD DOCKER HUB CREDENTIALS

Click + Add Credentials.

Provide your Docker Hub username and password in the corresponding fields.

Set the ID to docker_hub_login and the Description to Docker Hub.

Click Create.

 

 

ADD KUBERNETES CREDENTIALS

Click + Add Credentials.

Set the Kind to Kubernetes configuration (kubeconfig)

Set the ID to kubeconfig and the description to Kubeconfig.

SSH into the Cloud Server Kubernetes Master host.

Run the following:

ssh cloud_user@

cat ~/.kube/config

Copy the contents of the file that appears.

Back in our Jenkins browser, paste what was copied into the Enter directly > Content section.

Click Create.

 

SET UP THE PROJECT

Go back to the main page by selecting the Jenkins icon at the top left of the website.

Click New Item.

Give the item the name

Select Multibranch Pipeline and click OK.

Under Branch Sources, change the Add source to GitHub.

Set up the page as follows:

Credentials: Option that ends in (GitHub Key)

Repository HTTPS URL: your github repository

Select Save.

BUILD THE JOB IN JENKINS

Click on our Kubernetes server, and enter the following to review our deployment:

kubectl get pods

launch the application with Kubernetes master ip address and port 8080

 

ADD A CANARY STAGE TO THE PIPELINE

To complete this, you will need to do the following:

Go back to GitHub and go to the fork that we made.

Copy the train-schedule-kube-canary.yml code.

Click Add file > Create new file.

Name the file train-schedule-kube-canary.yml.

Paste in the train-schedule-kube-canary.yml code.

Click Commit new file.

Select the Jenkinsfile, which can be found here.

Add a new stage after the Push Docker Image stage and before DeployToProduction



kind: Service
apiVersion: v1
metadata:
  name: train-schedule-service-canary
spec:
  type: NodePort
  selector:
    app: train-schedule
    track: canary
  ports:
  - protocol: TCP
    port: 8080
    nodePort: 8081

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: train-schedule-deployment-canary
  labels:
    app: train-schedule
spec:
  replicas: $CANARY_REPLICAS
  selector:
    matchLabels:
      app: train-schedule
      track: canary
  template:
    metadata:
      labels:
        app: train-schedule
        track: canary
    spec:
      containers:
      - name: train-schedule
        image: $DOCKER_IMAGE_NAME:$BUILD_NUMBER
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 15
          timeoutSeconds: 1
          periodSeconds: 10
        resources:
          requests:
            cpu: 200m
Jenkinsfile

pipeline {
    agent any
    environment {
        //be sure to replace "willbla" with your own Docker Hub username
        DOCKER_IMAGE_NAME = "willbla/train-schedule"
    }
    stages {
        stage('Build') {
            steps {
                echo 'Running build automation'
                sh './gradlew build --no-daemon'
                archiveArtifacts artifacts: 'dist/trainSchedule.zip'
            }
        }
        stage('Build Docker Image') {
            when {
                branch 'master'
            }
            steps {
                script {
                    app = docker.build(DOCKER_IMAGE_NAME)
                    app.inside {
                        sh 'echo Hello, World!'
                    }
                }
            }
        }
        stage('Push Docker Image') {
            when {
                branch 'master'
            }
            steps {
                script {
                    docker.withRegistry('https://registry.hub.docker.com', 'docker_hub_login') {
                        app.push("${env.BUILD_NUMBER}")
                        app.push("latest")
                    }
                }
            }
        }
        stage('CanaryDeploy') {
            when {
                branch 'master'
            }
            environment { 
                CANARY_REPLICAS = 1
            }
            steps {
                kubernetesDeploy(
                    kubeconfigId: 'kubeconfig',
                    configs: 'train-schedule-kube-canary.yml',
                    enableConfigSubstitution: true
                )
            }
        }
        stage('DeployToProduction') {
            when {
                branch 'master'
            }
            environment { 
                CANARY_REPLICAS = 0
            }
            steps {
                input 'Deploy to Production?'
                milestone(1)
                kubernetesDeploy(
                    kubeconfigId: 'kubeconfig',
                    configs: 'train-schedule-kube-canary.yml',
                    enableConfigSubstitution: true
                )
                kubernetesDeploy(
                    kubeconfigId: 'kubeconfig',
                    configs: 'train-schedule-kube.yml',
                    enableConfigSubstitution: true
                )
            }
        }
    }
}

RUN A SUCCESSFUL DEPLOYMENT

Check on our website that everything is working by putting in the Public IP address for our Kubernetes with port :8081 at the end.

Once we know the site is working, go back to Jenkins, hover over DeployToProduction, and click Proceed.

On our Kubernetes server,we see the new node running

No comments:

Post a Comment

  PROMETHEUS AND GRAFANA A robust performance monitoring and alerting stack is crucial to service reliability. Cloud Native Computing Foun...