3

使用 Jenkins 构建 CI/CD 之多分支流水线

 2 years ago
source link: https://my.oschina.net/u/4518070/blog/5290963
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

由于公司的 Jenkins 配置没有部署成功的通知,在我学了几天的 Jenkins 后终于是对公司的 Jenkins 配置下手了,结果我刚装完 dingtalk 插件自动重启后,发现之前主管配置的构建项目数据都丢失了,正好给了我练手的机会,于是就有了以下从0到1的辛酸历程。

在 Docker 中安装并运行 Jenkins

这里假设你的服务器已经装好了docker

使用的镜像是 jenkinsci/blueocean,这是一个 Jenkins 的稳定及持续维护的镜像源,本身就集成了 Blue Ocean 等使用插件,非常方便。拉取镜像

docker pull jenkinsci/blueocean

运行 Jenkins

docker run -idt —name kmywjenkins -p 9090:8080 -p 60000:50000 -v jenkins-data:/var/jenkins_home -v /data/web-data/docker.sock:/var/run/docker.sock jenkinsci/blueocean

参数解释:

  • -idt 以交互的方式、新建一个模拟终端运行容器
  • —name 容器的别名
  • -p 指定容器映射宿主机的端口 -> 宿主机端口:容器端口
  • -v jenkins-data:/var/jenkins_home Jenkins容器在工作的时候,如果要执行Docker的命令(例如 docker ps、docker run等),需要有个途径能连接到宿主机的docker服务,此参数就是用来建立容器和宿主机docker服务的连接的
  • -v /data/web-data/docker.sock:/var/run/docker.sock 将该容器的数据保留在宿主机的目录,这样即使容器崩溃了,里面的配置和任务都不会丢失

需要注意的是,docker 中默认是以 Jenkins 用户运行的 Jenkins,如需以 root 用户可以加参数 -u root,本示例未指定 root。访问 Jenkins Docker 容器

有时候需要进入 Jenkins 容器执行一些命令,可以通过 docker exec 命令访问,例如:docker exec -it [containerid] bash若要手动重启 Jenkins,可以执行以下命令:docker restart [containerid]

Jenkins 基本配置 通过以上步骤,如果正常走到这里,可以通过以下地址访问http://121.41.16.183:9090/,IP 地址为服务器的地址。

解锁 Jenkins

输入一下命令获取解锁的 token,

docker exec kmywjenkins cat /var/jenkins_home/secrets/initialAdminPassword

在浏览器中输入对应的 token 以解锁:

创建凭据 连接 git 仓库,ssh 连接服务器均需要相应的凭据,可以在凭据管理中先创建好,然后需要使用的地方直接选择凭据即可。这里以连接git、ssh需要的凭据为例:

我司用得版本管理工具是 gitte,以 gitte 为例,其它版本管理工具配置也一样

类型选择 Username with password,用户名密码为登录 gitte 的账号密码,ID 是凭据的唯一标识,可自定义,后面在 JenkinsFile 中通过 ID 去引用凭据。配置后的结果SSH 连接服务器时需要密钥,我们先在服务器生成一对公私钥,然后复制私钥,填入即可。类型选择 SSH Username with private key,Username 是连接服务器的用户名,如 Jenkins 在 Private Key 项选中 Enter directly,点击 Add,粘贴刚复制的私钥。

配置后的结果

创建一个多分支流水线

之前的 Jenkins 任务是 FreeStyle 的方式创建的,这种方式不够灵活,界面也不够清爽,这里选择使用声明式流水线方式(Declarative Pipeline)创建,可以多分支独立构建,便于以后的扩展。

我们这里使用 BlueOcean 这种方式来完成此处 CI/CD 的工作,BlueOcean 是 Jenkins 团队从用户体验角度出发,专为 Jenkins Pipeline 重新设计的一套 UI 界面,仍然兼容以前的 fressstyle 类型的 job,BlueOcean 具有以下的一些特性:- 连续交付(CD)Pipeline 的复杂可视化,允许快速直观的了解 Pipeline 的状态

  • 可以通过 Pipeline 编辑器直观的创建 Pipeline
  • 需要干预或者出现问题时快速定位,BlueOcean 显示了 Pipeline 需要注意的地方,便于异常处理和提高生产力
  • 用于分支和拉取请求的本地集成可以在 GitHub 或者 Bitbucket 中与其他人进行代码协作时最大限度提高开发人员的生产力。

如果安装的是 Jenkinsci/blueocean 镜像,默认是已经集成了 BlueOcean,没有的可前往插件管理安装对应的插件。

点击打开Blue Ocean,可以看到已经创建好的两个流水线,分别是前端和后台,需要用到不同的工具,在后面会提到,如何创建流水线。

点击创建流水线

我司用的是gitte,所以选择Git,然后填入要连接的仓库地址,需要连接到Git仓库的凭据,我们之前已经创建好了,直接选中即可,如果未创建,在下面的表单直接编辑即可,最后点击创建流水线。

到这里我们就创建了一个多分支流水线,Jenkins 会扫描仓库,带有 JenkinsFile 的分支会被检测出来,JenkinFile 是多分支流水线的配置文件,使用的是 Groovy 语法,可以直接点击创建流水线,Jenkins 会自动为你的项目创建一个 JenkinsFile。

现在可以可视化地编辑想要执行的阶段及步骤,这里加了一个打包的阶段,里面有个步骤是提示开始打包,点击保存。

填入提交信息,点击 Save & Run,会讲 JenkinsFile 上传到 git,并根据 JenkinsFile 执行一个构建任务,目前的构建步骤只有一个,是提示开始打包。

我这里不知道为什么会卡在这个地方不动,所以我在 vscode 直接创建并编辑 JenkinsFile,这种方式更灵活,我更推荐这种方式,下面我会先简单介绍下 JeninsFile 的基础语法,仅包含本项目用到的,对于中小企业的构建需求,基本够用了。

JenkinsFile 基础语法

只需先了解大致的语法,具体的用法会在后面说明:

// 前端项目JenkinsFile配置,后端项目配置稍有不同,后面会区分说明
pipeline {
  agent any
  environment {
    HOST_TEST = '[email protected]'
    HOST_ONLINE = '[email protected]'
    SOURCE_DIR = 'dist/*'
    TARGET_DIR = '/data/www/kuaimen-yunying-front'
  }
  parameters {
    choice(
      description: '你需要选择哪个环境进行部署 ?',
      name: 'env',
      choices: ['测试环境', '线上环境']
    )    
    string(name: 'update', defaultValue: '', description: '本次更新内容?')      
  }
  triggers {
    GenericTrigger(
     genericVariables: [
      [key: 'ref', value: '$.ref']
     ],
     causeString: 'Triggered on $ref',
     token: 'runcenter-front-q1w2e3r4t5',
     tokenCredentialId: '',
     printContributedVariables: true,
     printPostContent: true,
     silentResponse: false,
     regexpFilterText: '$ref',
     regexpFilterExpression: 'refs/heads/' + BRANCH_NAME
    )
  } 
  stages {
    stage('获取git commit message') {
     steps {
       script {
         env.GIT_COMMIT_MSG = sh (script: 'git log -1 --pretty=%B ${GIT_COMMIT}', returnStdout: true).trim()
       }
     }
  }

    stage('打包') {
      steps {
        nodejs('nodejs-12.16') {
          echo '开始安装依赖'
          sh 'yarn'
          echo '开始打包'
          sh 'yarn run build'
        }
      }
    }

    stage('部署') {
      when {
        expression {
          params.env == '测试环境'
        }
      }
      steps {
        sshagent(credentials: ['km-test2']) {
          sh "ssh -o StrictHostKeyChecking=no ${HOST_TEST} uname -a"
          sh "scp -r ${SOURCE_DIR} ${HOST_TEST}:${TARGET_DIR}"
          sh 'echo "部署成功~"'
        }
      }
    }

    stage('发布') {
      when {
        expression {
          params.env == '线上环境'
        }
      }
      steps {
        sshagent(credentials: ['km-online']) {
          sh "ssh -o StrictHostKeyChecking=no ${HOST_ONLINE} uname -a"
          sh "scp -r ${SOURCE_DIR} ${HOST_ONLINE}:${TARGET_DIR}"
          sh 'echo "发布成功~"'
        }
      }
    }
  }

  post {
    success {
      dingtalk (
        robot: '77d4c82d-3794-4583-bc7f-556902fee6b0',
        type: 'MARKDOWN',
        atAll: true,
        title: '你有新的消息,请注意查收',
        text:[
          '# 运营管理系统发布通知',
          '---',
          '#### **所属:前端**',
          "#### **构建任务:${env.BUILD_DISPLAY_NAME}**",
          "#### **Git commit:${env.GIT_COMMIT_MSG}**",
          "#### **本次更新内容:${params.update}**",
          "#### **部署环境:${params.env}**",
          '#### **构建结果:成功**'
        ]
      )
    }
  }
}
  • pipeline 必须在最外层
  • agent 定义了在哪个环境里执行,默认any
  • stages 阶段,标识构建流程的标签块,子节点是stage
  • steps 执行步骤
  • post 所有阶段执行完成后执行一些逻辑
  • when 可以控制该阶段是否执行
  • environment 环境变量,在这里定义的变量,JenkinsFile的任何地方都可以访问
  • tools 项目使用到的构建工具,声明系统配置中已经定义好的工具,如maven
  • parameters 定义参数,可以提供用户输入或者选择
  • post 构建结束后会执行这里,有success、failure、success,本示例将在success(构建成功时)发起钉钉通知

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK