Version: v1.1

Jenkins CI/CD

This section will introduce how to use KubeVela with existing CI/CD tools such as Jenkins and why.

Introduction

With a simple integration effort, KubeVela as a universal application delivery control plane can then supercharge existing CI/CD tools with modern application deployment capabilities such as:

  • hybrid/multi-cloud delivery;
  • cross-environments promotion;
  • service mesh based application rollout/rollback;
  • handling deployment dependencies and topology (DAG);
  • declare, provision and consume cloud resources alongside with your application;
  • enjoy benefits of GitOps delivery without the need to introduce full GitOps transformation to your team;
  • … and much more.

The following guide will use Jenkins as an example to release a sample HTTP server application step by step. The application code can be found in this GitHub repo.

Preparation

Before combining KubeVela and Jenkins, you need to ensure the following environments have already been set up.

  1. Deploy Jenkins service with Docker support, including related plugins and credentials which will be used to access image repository.
  2. A git repository with Webhook enabled. Ensure commits to the target branch will trigger the running of the Jenkins pipeline.
  3. Get Kubernetes for deployment. Install KubeVela and enable its apiserver. Ensure the KubeVela apiserver can be accessed from external environment.

Combining Jenkins with KubeVela apiserver

Deploy Jenkins pipeline with the following Groovy script. You can change the git repository address, image address, apiserver address and other environment configurations on demand. Your git repository should contain the Dockerfile and app.yaml configuration file to tell how to build the target image and which component the application contains.

  1. pipeline {
  2. agent any
  3. environment {
  4. GIT_BRANCH = 'prod'
  5. GIT_URL = 'https://github.com/Somefive/KubeVela-demo-CICD-app.git'
  6. DOCKER_REGISTRY = 'https://registry.hub.docker.com'
  7. DOCKER_CREDENTIAL = 'DockerHubCredential'
  8. DOCKER_IMAGE = 'somefive/kubevela-demo-cicd-app'
  9. APISERVER_URL = 'http://47.88.24.19'
  10. APPLICATION_YAML = 'app.yaml'
  11. APPLICATION_NAMESPACE = 'kubevela-demo-namespace'
  12. APPLICATION_NAME = 'cicd-demo-app'
  13. }
  14. stages {
  15. stage('Prepare') {
  16. steps {
  17. script {
  18. def checkout = git branch: env.GIT_BRANCH, url: env.GIT_URL
  19. env.GIT_COMMIT = checkout.GIT_COMMIT
  20. env.GIT_BRANCH = checkout.GIT_BRANCH
  21. echo "env.GIT_BRANCH=${env.GIT_BRANCH},env.GIT_COMMIT=${env.GIT_COMMIT}"
  22. }
  23. }
  24. }
  25. stage('Build') {
  26. steps {
  27. script {
  28. docker.withRegistry(env.DOCKER_REGISTRY, env.DOCKER_CREDENTIAL) {
  29. def customImage = docker.build(env.DOCKER_IMAGE)
  30. customImage.push()
  31. }
  32. }
  33. }
  34. }
  35. stage('Deploy') {
  36. steps {
  37. sh 'wget -q "https://github.com/mikefarah/yq/releases/download/v4.12.1/yq_linux_amd64"'
  38. sh 'chmod +x yq_linux_amd64'
  39. script {
  40. def app = sh (
  41. script: "./yq_linux_amd64 eval -o=json '.spec' ${env.APPLICATION_YAML} | sed -e 's/GIT_COMMIT/$GIT_COMMIT/g'",
  42. returnStdout: true
  43. )
  44. echo "app: ${app}"
  45. def response = httpRequest acceptType: 'APPLICATION_JSON', contentType: 'APPLICATION_JSON', httpMode: 'POST', requestBody: app, url: "${env.APISERVER_URL}/v1/namespaces/${env.APPLICATION_NAMESPACE}/applications/${env.APPLICATION_NAME}"
  46. println('Status: '+response.status)
  47. println('Response: '+response.content)
  48. }
  49. }
  50. }
  51. }
  52. }

Push commits to the target branch in the git repository, which the Jenkins pipeline focuses on. The webhook of git repo will trigger the newly created Jenkins pipeline. This pipeline will automatically build container images and push it to the image repository. Then it will send POST request to KubeVela apiserver, which will deploy app.yaml to Kubernetes cluster. An example of app.yaml is shown below.

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: kubevela-demo-app
  5. spec:
  6. components:
  7. - name: kubevela-demo-app-web
  8. type: webservice
  9. properties:
  10. image: somefive/kubevela-demo-cicd-app
  11. imagePullPolicy: Always
  12. port: 8080
  13. traits:
  14. - type: rollout
  15. properties:
  16. rolloutBatches:
  17. - replicas: 2
  18. - replicas: 3
  19. batchPartition: 0
  20. targetSize: 5
  21. - type: labels
  22. properties:
  23. jenkins-build-commit: GIT_COMMIT
  24. - type: ingress
  25. properties:
  26. domain: <your domain>
  27. http:
  28. "/": 8088

THe GIT_COMMIT identifier will be replaced by the current git commit id in Jenkins pipeline. You can check the deployment status in Kubernetes through kubectl.

  1. $ kubectl get app -n kubevela-demo-namespace
  2. NAME COMPONENT TYPE PHASE HEALTHY STATUS AGE
  3. cicd-demo-app kubevela-demo-app-web webservice running true 102s
  4. $ kubectl get deployment -n kubevela-demo-namespace
  5. NAME READY UP-TO-DATE AVAILABLE AGE
  6. kubevela-demo-app-web-v1 2/2 2 2 111s
  7. $ kubectl get ingress -n kubevela-demo-namespace
  8. NAME CLASS HOSTS ADDRESS PORTS AGE
  9. kubevela-demo-app-web <none> <your domain> 198.11.175.125 80 117s

In the deployed application, we use the rollout trait, which enables us to release 2 pods first for canary validation. After validation succeed, remove batchPatition: 0 in application configuration in the rollout trait. After that, a complete release will be fired. This mechanism greatly improves the security and stability of the releasing process. You can adjust the rollout strategy depending on your scenario.

  1. $ kubectl edit app -n kubevela-demo-namespace
  2. application.core.oam.dev/cicd-demo-app edited
  3. $ kubectl get deployment -n kubevela-demo-namespace
  4. NAME READY UP-TO-DATE AVAILABLE AGE
  5. kubevela-demo-app-web-v1 5/5 5 5 4m16s
  6. $ curl http://<your domain>/
  7. Version: 0.1.2

More

Refer to the blog post for more details about deploying Jenkins + KubeVela and more comprehensive demo for application rolling update.