Version: v1.1

Jenkins CI/CD

本文将介绍如何使用 KubeVela 同已有的 CI/CD 工具(比如 Jenkins)共同协作来进行应用的持续交付,并解释这样集成的好处是什么。

简介

KubeVela 作为一个普适的应用交付控制平面,只需要一点点集成工作就可以同任何现有的 CI/CD 系统对接起来,并且为它们带来一系列现代云原生应用交付的能力,比如:

  • 混合云/多云应用交付;
  • 跨环境发布(Promotion);
  • 基于 Service Mesh 的发布与回滚;
  • 处理部署过程中的各种依赖关系和拓扑结构;
  • 统一进行云服务的声明、部署和服务绑定;
  • 无需强迫你的团队采纳完整的 GitOps 协作方式即可享受 GitOps 技术本身的一系列好处
  • …… 以及更多。

接下来,本文将会以一个 HTTP 服务的开发部署为例,介绍 KubeVela + Jenkins 方式下应用的持续集成与持续交付步骤。这个应用的具体代码在这个 GitHub 库中

准备工作

在对接之前,用户首先需要确保以下环境。

  1. 已部署好 Jenkins 服务并配置了 Docker 在 Jenkins 中的环境,包括相关插件及镜像仓库的访问权限。
  2. 已配置好的 Git 仓库并开启 Webhook。确保 Git 仓库对应分支的变化能够通过 Webhook 触发 Jenkins 流水线的运行。
  3. 准备好需要部署的 Kubernetes 集群环境,并在环境中安装 KubeVela 基础组件及 apiserver,确保 KubeVela apiserver 能够从公网访问到。

对接 Jenkins 与 KubeVela apiserver

在 Jenkins 中以下面的 Groovy 脚本为例设置部署流水线。可以将流水线中的 Git 地址、镜像地址、apiserver 的地址、应用命名空间及应用替换成自己的配置,同时在自己的代码仓库中存放 Dockerfile 及 app.yaml,用来构建及部署 KubeVela 应用。

  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. }

之后向流水线中使用的 Git 仓库的分支推送代码变更,Git 仓库的 Webhook 会触发 Jenkins 中新创建的流水线。该流水线会自动构建代码镜像并推送至镜像仓库,然后对 KubeVela apiserver 发送 POST 请求,将仓库中的应用配置文件部署到 Kubernetes 集群中。其中 app.yaml 可以参照以下样例。

  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

其中 GIT_COMMIT 会在 Jenkins 流水线中被替换为当前的 git commit id。这时可以通过 kubectl 命令查看 Kubernetes 集群中应用的部署情况。

  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

在部署的应用文件中,我们使用了灰度发布(Rollout)的特性,应用初始发布先创建 2 个 Pod,以便进行金丝雀验证。待验证完毕,你可以将应用配置中 Rollout 特性的 batchPatition: 0 删去,以便完成剩余实例的更新发布。这个机制大大提高发布的安全性和稳定性,同时你也可以根据实际需要,调整 Rollout 发布策略。

  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

更多

详细的环境部署流程以及更加完整的应用滚动更新可以参考博客