CI/CD概念

CI/CD 是持续集成(Continuous Integration)和持续交付/持续部署(Continuous Delivery/Continuous Deployment)的缩写,持续集成(CI)是指开发人员经常把代码合并到共享代码库,并自动测试新代码,以确保不会破坏现有代码。持续交付(CD)是指自动化地构建/编译软件,使其随时可以发布。如果进一步实践持续部署(CD),则新代码会自动部署到任何环境,无需人工干预。简言之,CICD可以帮助团队更快地构建和发布软件,同时确保代码质量和稳定性。常见的CICD工具包括:Jenkins、GitlabCI/CD、Bamboo等

Jenkins

Jenkins是一个开源的、可扩展的持续集成、交付、部署(软件/代码的编译、打包、部署)的基于web界面的平台。它可以在代码上传到仓库(如gitlab)后,在jenkins中通过获取代码仓库中最新代码,进行自动化部署,而省去手动打包、上传服务器、部署这一系列步骤,非常方便。

Jenkins环境准备

  • 安装

    # 检查时区
    timedatectl status
    ​
    # 设置成中国时间
    timedatectl set-timezone Asia/Shanghai
    ​
    # 同步时间
    yum install ntpdate -y
    ntpdate ntp1.aliyun.com
    ​
    # 下载jdk和jenkins
    https://repo.huaweicloud.com/jenkins/redhat-stable/
    https://repo.huaweicloud.com/java/jdk/8u181-b13/
    ​
    # 先后安装jdk和jenkins
    rpm -ivh jdk-8u181-linux-x64.rpm
    rpm -ivh jenkins-2.99-1.1.noarch.rpm
    ​
    # 检查版本
    java -jar /usr/lib/jenkins/jenkins.war --version
    2.99
    ​
    systemctl start jenkins
  • 配置

    # jenkins初始密码
    /var/lib/jenkins/secrets/initialAdminPassword
    ​
    # 进入初始页面,修改密码
    http://ip:8080
    ​
    # Jenkins目录解析
    /etc/init.d/jenkins         # 启动目录
    /etc/logrotate.d/jenkins    # 日志切割
    /etc/sysconfig/jenkins      # jenkins主配置文件
    /usr/lib/jenkins            # jenkins程序文件,jenkins.war直接替换即可完成升级
    /usr/lib/jenkins/jenkins.war
    /usr/sbin/rcjenkins
    /var/cache/jenkins
    /var/lib/jenkins            # jenkins主目录,如果要备份jenkins数据,直接拷贝该目录即可
    /var/log/jenkins            # 日志目录
    ​
    # Jenkins主配置文件解析
    [root@it-jenkins ~]# grep -Ev "^$|^#" /etc/sysconfig/jenkins
    JENKINS_HOME="/var/lib/jenkins"
    JENKINS_JAVA_CMD=""
    JENKINS_USER="root"   # jenkins启动用户修改为root,避免构建时权限报错
    JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Dhudson.model.DownloadService.noSignatureCheck=true" # 解决签名验证报错
    JENKINS_PORT="8080"
    JENKINS_LISTEN_ADDRESS=""
    JENKINS_HTTPS_PORT=""
    JENKINS_HTTPS_KEYSTORE=""
    JENKINS_HTTPS_KEYSTORE_PASSWORD=""
    JENKINS_HTTPS_LISTEN_ADDRESS=""
    JENKINS_DEBUG_LEVEL="5"
    JENKINS_ENABLE_ACCESS_LOG="no"
    JENKINS_HANDLER_MAX="100"
    JENKINS_HANDLER_IDLE="20"
    JENKINS_ARGS="
    ​
    # 设置时区
    System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')
    ​
    # 修改镜像源
    https://repo.huaweicloud.com/jenkins/updates/2.89/update-center.json
    ​
    # 替换镜像源配置文件URL,解决安装插件时签名验证问题(重启jenkins生效)
    sed -i 's#http://updates.jenkins-ci.org/download#https://mirrors.huaweicloud.com/jenkins#g' /var/lib/jenkins/updates/default.json
    sed -i 's#http://www.google.com#https://www.baidu.com#g' /var/lib/jenkins/updates/default.json
  • 安装插件

    git                     # git依赖
    gitlab                  # Gitlab集成
    Publish Over SSH        # 基于ssh远程部署
    pipeline                # 流水线
    Blue Ocean              # 流水线可视化
    NodeJS                  # Nodejs依赖(可选)
  • Gitlab连接

    # Jenkins服务器安装git
    yum install git -y
    ​
    # Jenkins新建视图,源码管理选择Git,输入gitlab项目repo地址,此时会报错repo无法连接
    ​
    # 创建公私钥
    ssh-keygen -t rsa
    ​
    # 查看公钥
    cat /root/.ssh/id_rsa.pub 
    ​
    # 将公钥配置到gitlab用户中,过程略
    ​
    # 返回新建视图,源码管理选择Git,输入gitlab项目repo地址
    ​
    # 查看私钥
    cat /root/.ssh/id_rsa
    # 将私钥内容添加到repo凭据中
    ​
    # 此时repo地址无报错,保存item后点击立即构建,即可将gitlab项目代码拉取至workspace

部署Django、Vue前后端应用

  • 流水线示意图:

  • 环境准备:

    # Gitlab
    http://gitlab.transwarp.io/xinchen.luan/itops_frontend.git  #前端项目
    http://gitlab.transwarp.io/xinchen.luan/itops_backend.git   #后端项目
    ​
    172.16.30.132       # jenkins
    172.16.30.133       # 应用服务器
  • Django后端项目

    • 安装Docker、Docker-Compose,准备工作目录及配置文件(参考前一篇部署文章,此处略)

    • 创建后端View,关联后端gitlab项目和鉴权(关联项目时选择master或者prod分支,开发时使用develop分支)

    • 构建:由于我们使用Django,不需要进行编译,因此拉取代码后直接打包即可

      • 进入View配置,在构建选项中选择Execute shell,然后编写打包命令

        # 使用build_tag作为包名,打包工作区下所有文件
        # 打包时注意排除tar包,否则第二次构建会重复打包
        cd $WORKSPACE
        tar -czf $BUILD_TAG.tar.gz --exclude='*.tar.gz' * 

    • 部署:通过SSH将代码包发送到应用服务器,并执行部署

      • 进入系统管理-全局配置,拉到最下面找到Publish over SSH,添加SSH远端服务器

        这里有坑:Remote Directory是远端工作目录,后续上传文件时会被自动拼接到路径前面,只有这里填写根目录后,上传文件时的Remote Directory才能作为绝对路径使用。

      • 返回视图配置页,在构建环境选项中配置Send files or execute commands over SSH after the build runs,字面意思就是在构建完成后发送文件或命令给远端服务器。

      • 输入我们上一步构建出来的代码包名(可使用变量),再输入远端服务器的项目路径,然后再编写文件传输完成后的远端部署命令即可

        # 部署前清空已有代码
        rm -rf /opt/itops/myproject/*
        ​
        # 解包到代码目录,注意使用--no-same-owner参数取消携带权限
        tar -zxf /opt/itops/$BUILD_TAG.tar.gz --no-same-owner -C /opt/itops/myproject 
        ​
        # 部署完成后删除代码包
        rm /opt/itops/$BUILD_TAG.tar.gz

    • 保存配置后,点击立即构建即可实现后端代码自动打包、部署。

      构建过程可能不会一次成功,需要通过console不断观察错误信息,逐步构建逐个解决。

  • Vue前端项目

    • 在jenkins服务器中安装nodejs,用于构建vue项目,node版本尽量和开发环境保持一致

      # 下载地址
      https://nodejs.org/download/release/v16.17.1/
      ​
      # node安装比较简单,解压后创建软链接即可
      tar -zxf node-v16.17.1-linux-x64.tar.gz
      ln -s /opt/node-v16.17.1-linux-x64/bin/node /usr/local/bin/
      ln -s /opt/node-v16.17.1-linux-x64/bin/npm /usr/local/bin/
      ​
      # 检查版本
      node -v
      npm -v
    • 创建前端View,关联前端gitlab项目和鉴权(关联项目时选择master或者prod分支,开发时使用develop分支)

    • 配置NodeJS环境

      • 进入系统管理-全局工具配置,找到NodeJS安装,输入别名和node安装目录

    • 构建:npm构建前端代码并打包

      • 进入View配置,在构建环境选项勾选Provide Node & npm bin/ folder to PATH,并选择我们刚才配置的nodejs环境

      • 在构建选项中选择Execute shell,然后编写打包命令

        cd $WORKSPACE
        # npm构建前端代码
        npm run build
        # 使用build_tag作为包名,打包dist目录下所有文件
        tar -czf $BUILD_TAG.tar.gz -C dist .

      • 在构建环境选项中配置Send files or execute commands over SSH after the build runs,编写部署命令

        cd /opt/itops/
        # 部署前清空已有代码
        rm -rf compose/nginx/dist/*
        # 解包到代码目录,注意使用--no-same-owner参数取消携带权限
        tar -zxf $BUILD_TAG.tar.gz --no-same-owner -C compose/nginx/dist
        rm $BUILD_TAG.tar.gz

      • 保存配置,点击立即构建即可实现前端代码自动打包、部署

  • 小结

    至此我们实现了前端项目和后端项目的自动打包、部署,在上线新接口或者新页面时,在jenkins中点击构建即可,省去了我们手动打包部署的繁杂操作。

    • 思考一个问题:

      当前端项目和后端项目同时推送了新代码,此时需要jenkins分别构建前端和后端代码,并且需要进入应用服务器手动刷新服务,有没有更快捷的方式呢?

      后面我们将继续学习一个新的概念:Pipeline