Ruddra.com

Deploy Django to OpenShift Using Jenkins Pipeline(CI/CD)

Deploy Django to OpenShift Using Jenkins Pipeline(CI/CD)

Using Jenkins pipeline, you can easily automate your deployments in OpenShift. In this post, we are going to use this powerful tool to deploy a Django project. But before we start, one thing I need to mention is that, this project has been tested on in Minishift 1.2.0, OpenShift v3.9.0 and Kubernetes v1.9.1. So without further adieu, let us begin.

Source code

You can find the source code for a this project here: https://github.com/ruddra/openshift-django

Pipeline execution steps

On every pipeline execution, the code goes through the following steps:

  1. First, jenkins will check if build configuration for this repo exists in dev project.
  2. If not, then it will create new app using the templates provided in code.
  3. Then, it will build and test the code
  4. After successful build, it will deploy the image to dev project.
  5. Then it will prompt if it will deploy the code to stage. If yes, then it will proceed to next step, else it will abort.
  6. It will push the dev image to stage and tag it as promoteToQA.
  7. This image will be deployed to stage project and will be scaled to 3.

Automated deploy on minishift

Go to scripts directory and run ./setup.sh

Manual deploy on minishift

First, run minishift using minishift start memory=4000. Then, run the following commands to create projects in OpenShift.

# Create Projects
oc new-project dev --display-name="Tasks - Dev"
oc new-project stage --display-name="Tasks - Stage"
oc new-project cicd --display-name="CI/CD"

Install Jenkins in cicd by running

oc project cicd
oc new-app openshift/jenkins-2-centos7

Now, give permission to Jenkins to modify in dev and stage project.

oc policy add-role-to-user edit system:serviceaccount:cicd:jenkins -n dev
oc policy add-role-to-user edit system:serviceaccount:cicd:jenkins -n stage

Deploy the MySQL in cicd project by loading MySQL template like this:

oc new-app -f .openshift/templates/mysql-template.yaml

It will create the mysql server. Please keep in mind that, this MySQL will be available in 172.30.0.30. This configurations in defined in Service configuration section of the template

So, we are almost ready. Now please load the pipeline using:

oc new-app -f .openshift/pipelines/openshift-django-pipeline.yaml

Now you will be able to see the pipeline in Console > CI/CD > Build > Pipelines. You can run it from there or from CLI like:

oc start-build djangopipeline

To implement webhooks, you can look into this project.

Screenshots

Pipeline execustion looks like this in Blue Ocean:

Screen-Shot-2018-07-24-at-8.17.19-PM

Stage View in Jenkins looks like this:

Screen-Shot-2018-07-24-at-8.20.50-PM

In CI/CD project of OpenShift:

Screen-Shot-2018-07-24-at-8.22.46-PM

In Dev project of OpenShift:

Screen-Shot-2018-07-24-at-8.23.06-PM

In Stage project of OpenShift:

Screen-Shot-2018-07-24-at-8.23.25-PM

After Pipeline execution, it should look like this:

Screen-Shot-2018-07-24-at-8.37.52-PM

Deploy your project: pre-requisite

  1. Have a Django Project with Docker to deploy it.
  2. Have minishift installed in your local machine.
  3. Give it 4GB memory.
  4. If you can pull python, jenkins-2-centos7, mysql-55-centos7 images beforehand using docker pull <image name>, it would make the deployment much more faster.

deploy your project: modify pipeline

You can use this Pipeline to deploy your own project with this minimal changes:

  1. Go to Pipeline template at in my github repository: OR Take this pipeline:
def openshiftDjangoRepo="https://raw.githubusercontent.com/ruddra/openshift-django/develop/.openshift/templates/openshift-django-template.yaml"
def stageTag="promoteToQA"
def DEV_PROJECT="dev"
def STAGE_PROJECT="stage"
def templateName="openshift-django"

pipeline{
  agent { label ""}
  stages{
    stage('Create in DEV') {
      when {
        expression {
          openshift.withCluster() {
            openshift.withProject(DEV_PROJECT) {
              echo "checking openshift django exists in DEV"
              return !openshift.selector("bc", "${templateName}").exists();
            }
          }
        }
      }
      steps {
        script {
          openshift.withCluster() {
            openshift.withProject(DEV_PROJECT) {
              openshift.newApp(openshiftDjangoRepo).narrow("svc").expose();
            }
          }
        }
      }
    }
    stage('Build and Test in DEV'){
      steps {
        script {
          openshiftBuild(namespace: "${DEV_PROJECT}", buildConfig: "${templateName}", showBuildLogs: 'true',  waitTime: "600000")
        }
      }
    }
    stage('Rollout to DEV') {
      steps {
        script {
          openshiftDeploy(namespace: "${DEV_PROJECT}", deploymentConfig: "${templateName}", waitTime: "600000")
        }
      }
    }
    stage('Scale in DEV') {
      steps {
        script {
          openshiftScale(namespace: "${DEV_PROJECT}", deploymentConfig: "${templateName}", replicaCount: '1')
        }
      }
    }
    stage('Promote to STAGE?') {
      steps {
        timeout(time:15, unit:'MINUTES') {
          input message: "Promote to STAGE?", ok: "Promote"
        }

        script {
          openshift.withCluster() {
            openshift.tag("${DEV_PROJECT}/${templateName}:latest", "${STAGE_PROJECT}/${templateName}:${stageTag}")
          }
        }
      }
    }
    stage('Rollout to STAGE') {
      steps {
        script {
          openshift.withCluster() {
            openshift.withProject(STAGE_PROJECT) {
              if (openshift.selector('dc', "${templateName}").exists()) {
                openshift.selector('dc', "${templateName}").delete()
                openshift.selector('svc', "${templateName}").delete()
                openshift.selector('route', "${templateName}").delete()
              }
            openshift.newApp("${templateName}:${stageTag}").narrow("svc").expose()
          }
        }
      }
    }
  }
  stage('Scale in STAGE') {
      steps {
        script {
          openshiftScale(namespace: "${STAGE_PROJECT}", deploymentConfig: "${templateName}", replicaCount: '3')
        }
      }
    }
  }
}
  1. Edit this line in the template:
    def openshiftDjangoRepo="https://raw.githubusercontent.com/ruddra/openshift-django/master/.openshift/templates/openshift-django.yaml"
    

    Change the url to either your repository link like https://github.com/ruddra/openshift-django

  2. Change the template name in there as well:
def templateName="openshift-django"

Advanced implementation

In this post, we have deployed our application by using only OpenShift APIs in Jenkins Plugin. If you want more advanced implementation, like having Jenkins do build, testing, store test results etc with more advanced pipeline, then please look into these posts:

  1. Deploy A Python App to OpenShift: Planning and Preparations
  2. Writing Jenkins Pipeline For OpenShift Deployment
  3. Automated Deployment to OpenShift Using Jenkins and Webhook

Thanks for reading. Cheers!!

Last updated: Apr 05, 2024


← Previous
Boilerplate For Angular 1.X and Django

Simple and clean boilerplate for using Django with angular 1.x, with basic structure comes built-in.

Next →
Deploy A Python App to OpenShift: Planning and Preparations

Deploying a Python application to OpenShift is fairly easy. Write a Dockerfile and run oc new-app …

Share Your Thoughts
M↓ Markdown