The last article shows, how you should prepare your environment. This post describes the configuration of GitLab and Jenkins.

Jenkins configuration

At first Jenkins has to be configured. This will be done by WebUI, which is reachable by http://NODE_IP:8080/login

After a successfull authenication you will redirect to the Jenkins Dashboard. jenkinsDashboard

Configuring Credentials

For the CI/CD demo with the WebApp requires some credentials:

  • for Docker Hub, for uploading the Docker image
  • GitLab for reading the files or starting the WebHook

Credential for Dockerhub

On the left side go to “Credential” -> “System” -> “Global credential (unrestricted)” -> “Add Credential”

Now enter your dockerhub credential: jenkinsDockerCredential

Important: ID must be docker-hub-cred

Press “save” to save the configuration.

Credential for GitLab

Before your create the gitlab credentials you need the api key of your gitlab account.

Login to your gitlab account -> goto Settings -> Access Token

GitLabAPIToken

copy your token to an editor, because you need it later. GitLabAPIToken2

Go back to Jenkins in the submenu for creating credential and add create a credential set: jenkinsGitLabCredential

If there is no “GitLab API token” in the “Child” menu, the Gitlab plug-in must be installed first. API token is the token which has been created a step before.

Create a pipeline project

Now the basic configuration as been done and the pipeline project can be created. For a new project/pipeline click on “New Item” on the dashboard. A wizzard will help you to create the pipeline project. There are many project types with different functions. But for the demo case we will create a “Pipeline Project”. pipelineStep0

The pipeline project is seperated in four diffrent Sections:

  • General
  • Build Triggers
  • Advanced Project Options
  • Pipeline

General

In the General section you define basic setting of the project. In this case here there is nothing to do. pipelineStep1

Build Triggers

In Build Triggers you define how the pipeline would started. The demo build will start when a new commit will be published on gitlab. pipelineStep2

The point “Build when a change is pushed to GitLab. GitLab webhook URL: http://jenkins:8080/project/WebApp” must be enabled. In the background a Webhook link will be created which will be added to the gitlab project. For the webhook you need a security token which can be created under advenced:

pipelineStep3

Advanced Project Options

Here is nothing to configure :-)

Pipeline

In the last section you add your pipeline script to the project. The easiest way is to link the “Jenkins”-File to the file on your gitlab/github project. pipelineStep4

The Demo uses this Jenkinsfile:

podTemplate(label: 'mypod', containers: [
    containerTemplate(name: 'docker', image: 'docker', ttyEnabled: true, command: 'cat'),
    containerTemplate(name: 'kubectl', image: 'lachlanevenson/k8s-kubectl:v1.8.0', command: 'cat', ttyEnabled: true),
    containerTemplate(name: 'helm', image: 'lachlanevenson/k8s-helm:v2.7.2', command: 'cat', ttyEnabled: true)
  ],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
  ]) {
    node('mypod') {
        
        deleteDir()
        
        stage("Checkout") {
            checkout scm
        }
        stage('Build and Push Container') {
            container('docker') {

                withCredentials([[$class: 'UsernamePasswordMultiBinding',
                        credentialsId: 'docker-hub-cred',
                        usernameVariable: 'DOCKER_HUB_USER',
                        passwordVariable: 'DOCKER_HUB_PASSWORD']]) {
                    
                    sh "docker build -t DOCKER_HUB_USER/webapp:${env.BUILD_NUMBER} ."
                    sh "docker login -u DOCKER_HUB_USER -p ${env.DOCKER_HUB_PASSWORD} "
                   sh "docker push DOCKER_HUB_USERwebapp:${env.BUILD_NUMBER} "
                }
            }
        }
        stage("Create Test instance") {
            container('helm') {

               sh "helm install --name test --set service.nodePort=30001,cloneSource=prod,webappImage.tag=${env.BUILD_NUMBER} helm/webapp"
            }
        }
        
        stage ("Automated Test Cases"){
          
          // give the container 10 seconds to initialize the web server
          sh "sleep 10"

          // connect to the webapp and verify it listens and is connected to the db
          //
          // to get IP of jenkins host (which must be the same container host where dev instance runs)
          // we passed it as an environment variable when starting Jenkins.  Very fragile but there is
          // no other easy way without introducing service discovery of some sort
          echo "Check if webapp port is listening and connected with db"
          // sh "curl http://192.168.42.5:30001/v1/ping -o curl.out"
          // sh "cat curl.out"
          // sh "awk \'/true/{f=1} END{exit!f}\' curl.out"
          echo "<<<<<<<<<< Access this test build at http://192.168.42.5:30001 >>>>>>>>>>"        
        }
        def push = ""
        stage ("Manual Test & Approve Push to Production"){
          // Test instance is online.  Ask for approval to push to production.
          // notifyBuild('APPROVAL-REQUIRED')
          push = input(
            id: 'push', message: 'Push to production?', parameters: [
              [$class: 'ChoiceParameterDefinition', choices: 'Yes\nNo', description: '', name: 'Select yes or no']
            ]
          )
        }
        
        stage('Deploy in Production') {
            container('kubectl') {
                sh "sleep 10"
                withCredentials([[$class: 'UsernamePasswordMultiBinding', 
                        credentialsId: 'docker-hub-cred',
                        usernameVariable: 'DOCKER_HUB_USER',
                        passwordVariable: 'DOCKER_HUB_PASSWORD']]) {
                    
                    sh "kubectl set image deployments/prod-webapp webapp=dockerhubaccount/webapp:${env.BUILD_NUMBER}"
                }
            }
        }
        stage('Delete test instance') {
            container('helm') {

               sh "helm delete --purge test"
            }
        }
    }
}

Outlook to Part 3

In the next article I want to show you how NetApp comes into play here.

  • Cloning with NetApp Trident