CI/CD

相关概念

什么是CI

CI:Continuous integration持续集成

开发人员通常使用称为CI Server的工具来进行构建和集成。CI要求自检代码。这是用于自我测试以确保其按预期工作的代码,这些测试通常称为单元测试。集成代码后,当所有单元测试通过时,将得一个最新的的代码版本。这表明他们已经验证了自己的更改已成功集成到一起,并且代码按测试期望的那样工作。

什么是CD

CD:Continuous deployment持续部署

在这种实践中,团队负责人所做的每一项更改都通过了所有测试阶段,并自动投入生产。要实现连续部署,团队负责人首先需要进行连续交付,因此在开始练习连续部署之前,先决定哪个对您更合适,持续交付都是为了增强整个业务的能力,因此至少您应该参与确定是否应该使用持续部署。

CD还有个小号,叫持续交付,英文全称是Continuous delivery,缩写也是CD

为什么需要CI/CD

持续集成(CI)是一种开发实践,其中开发人员经常(最好每天几次)将代码集成到共享存储库中。然后可以通过自动构建和自动测试来验证每个集成。尽管自动化测试不是严格意义上的CI的一部分,但通常隐含了它。定期集成的主要好处之一是,您可以快速检测到错误并更轻松地定位它们。由于引入的每个更改通常很小,因此可以快速查明引入缺陷的特定更改。
近年来,CI已成为软件开发的最佳实践,并遵循一系列关键原则。其中包括版本控制,构建自动化和自动化测试。此外,持续部署和持续交付已成为最佳实践,可让您随时随地部署应用程序,甚至在每次引入新更改时甚至将主代码库自动推入生产环境。这使您的团队可以快速行动,同时保持可以自动检查的高质量标准。

大致流程

image-20230131210254544

环境搭建

环境落地:

  • 代码仓库:GitLab(进行代码托管/合并/冲突)

GitLab搭建

官方网站:https://about.gitlab.com/

安装文档:https://gitlab.cn/install/?version=ce

安装所需最小配置:内存至少要分配4G

具体步骤:

普通安装
  1. 创建一台内存大于5G的linux虚拟机

  2. 安装和配置必须的依赖项:

    1
    2
    3
    4
    5
    6
    sudo yum install -y curl policycoreutils-python openssh-server perl
    sudo systemctl enable sshd
    sudo systemctl start sshd
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
    sudo systemctl reload firewalld
  3. 配置镜像:

    1
    curl -fsSL https://packages.gitlab.cn/repository/raw/scripts/setup.sh | /bin/bash
  4. 开始安装:

    1
    sudo EXTERNAL_URL="自己的ip/域名" yum install -y gitlab-jh
  5. 访问:http://ip

Docker方式安装
  1. 创建一台内存大于5G的linux虚拟机

  2. 安装docker(省略)

  3. 创建gitlab容器(会自动拉取镜像):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sudo docker run --detach \
    --hostname 本机ip \
    --publish 443:443 --publish 80:80 --publish 22:22 \
    --name gitlab \
    --restart always \
    --volume $GITLAB_HOME/config:/etc/gitlab \
    --volume $GITLAB_HOME/logs:/var/log/gitlab \
    --volume $GITLAB_HOME/data:/var/opt/gitlab \
    --shm-size 256m \
    registry.gitlab.cn/omnibus/gitlab-jh:latest
  4. 运行容器:docker start gitlab

  5. 访问:http://ip

除非您在安装过程中指定了自定义密码,否则将随机生成一个密码并存储在 /etc/gitlab/initial_root_password 文件中(出于安全原因,24 小时后,此文件会被第一次 gitlab-ctl reconfigure 自动删除,因此若使用随机密码登录,建议安装成功初始登录成功之后,立即修改初始密码)。使用此密码和用户名 root 登录。并且可以登录后在gitlab的管理中心-用户进行修改密码。

具体文档参考:https://docs.gitlab.cn/omnibus/installation/

GitLab常用命令:

  • 启动所有gitlab组件:gitlab-ctl start
  • 停止所有gitlab组件:gitlab-ctl stop
  • 重启所有gitlab组件:gitlab-ctl restart
  • 查看服务状态:gitlab-ctl status
  • 启动服务:gitlab-ctl reconfigure
  • 修改默认配置文件:vi /etc/gitlab/gitlab.rb
  • 查看日志:gitlab-ctl tail

JenKins 安装

官方文档:https://www.jenkins.io

安装需求:

  • 最低推荐配置:

    256MB可用内存

    1GB可用磁盘空间(作为一个Docker容器运行jenkins的话推荐10GB)

  • 为小团队推荐的硬件配置:

    1GB+可用内存

    50 GB+ 可用磁盘空间

  • 软件配置:

    Java 8—无论是Java运行时环境(JRE)还是Java开发工具包(JDK)都可以。

注意: 如果将Jenkins作为Docker 容器运行,这不是必需的

安装步骤

  1. 下载Jenkins,并上传到虚拟机
  2. 安装JDK:
    1. 检查可用包:yum search java|grep jdk
    2. 安装JRE:yum install java-1.8.0-openjdk
    3. 再安装JDK:yum install -y java-devel
  3. 运行Jenkins:java -jar jenkins.war
  4. 访问Jenkins进行初始化并安装推荐插件:http://ip:8080
  5. 安装maven(如果下载依赖慢可以配置国内仓库):
    1. 官方下载压缩包,并上传到虚拟机
    2. 解压:tar -zxvf apache-maven-3.8.7-bin.tar.gz
    3. 移动目录:mv apache-maven-3.8.7 /usr/local/maven
    4. 查看版本:/usr/local/maven/bin/mvn -v
    5. 修改maven配置文件修改仓库源为国内仓库
  6. 安装Git:yum install git

Jenkins简单使用

配置Maven + Git自动构建jar包

  1. 进入Jenkins

  2. 在Manage Jenkins 一栏中Plugin Manager安装Maven Integration插件

    image-20230206194944348

  3. 在首页点击构建Item新项目,选择构建一个Maven项目

  4. 项目配置:

    1. 修改源码管理为Git,并填写URL(如果仓库为非公开需要配置凭证),修改分支
    2. 配置Build,在Global Tool Configuration中配置Maven(Name和Maven_Home)
    3. 配置POM路径(相对于仓库根目录,一般为项目名/pom.xml)
  5. 首页选择刚创建的项目,点击右侧的开始Build按钮

配置将jar包自动部署在服务器

  1. 保证服务器上有Java环境

  2. 在Jenkins上安装Publish Over SSH插件

  3. 在Manage Jenkins一栏里的Configure System里配置Publish over SSH服务器

    1. 设置服务器名Name

    2. 设置主机地址Hostname

    3. 设置账号Username

    4. 设置密码:

      image-20230206201849153

  4. 重新配置刚才的创建的项目

    1. 配置Post Steps:

      1. 点击下面按钮

      image-20230206201429060

      1. 配置Source files路径(例如**/项目名/target/*.jar

      2. 配置Remove prefix移除不需要的路径前缀

      3. 配置Remote directory发送到的地址(例如:/usr/app/demo-1)

      4. 配置送到服务器后需要执行的命令:nohup java -jar jar包目录/demo*.jar >mylog.log 2>&1 & (2>&1的意思就是不管正常错误都写入日志)

      5. 如果jar过大,可以配置超时时间

        image-20230206204335299

    2. 配置Pre Steps(清理进程、jar包):

      1. 点击下面按钮

      image-20230206204533327

      1. 编写shell脚本:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        #!/bin/bash
        #删除历史数据
        rm -rf 每次传过来的项目路径
        appname=$1
        #获取正在运行的jar包pid
        pid=`ps -ef | grep $appname | grep -v grep | awk '{printf $2}'`
        #杀死当前进行
        #如果pid为空提示,否则执行kill
        if [ -z $pid ];
        then
        echo "$appname no started"
        else
        kill -9 $pid
        echo "$appname stopping.."
        fi
        check=`ps -ef | grep -w $pid | grep java`
        if [ -z $check ];
        then
        echo "$appname pid:$pid is stop"
        else
        echo "$appname stop failed"
        fi
      2. 配置送到服务器前需要执行的命令:./脚本名.sh 项目名

构建触发器

image-20230207194535764

cron网站:https://crontab.guru

自动化构建

如果gitlab上修改了代码,Jenkins就自动从gitlab中拉取并上传服务器。

实现步骤:

  1. 在Jenkins的项目配置中配置构建触发器:

    image-20230207192850303

  2. 在Jenkins里的Plugin Manager中安装Build Authorization Token Root插件(地址变为buildByToken/build?job=项目名&toekn=令牌)

  3. 在gitlab上的设置里的webhooks配置自动调用Jenkins的回调:

    image-20230207193606795

    如果出现Url is blocked:Requests to the local network are not allowed问题

    点击左上角菜单,点管理员->设置->网络->出站请求

    勾选允许来自web hooks 和服务对本地网络的请求

将jar包部署到Docker中

  1. 方式一:外挂目录

    适用于小型项目,最开始就创建一个jdk的容器,并且映射jar包的目录在宿主主机上,这样就可以只用修改宿主主机的jar包再重启容器即可完成部署。

    image-20230208195346442
  2. 方式二:jar包直接打包到镜像里

    Jenkins发送dockerfile和相关项目jar包到docker服务器中,并且根据dockerfile生成新的镜像,创建相应容器并启动完成部署。

    image-20230208195537230
  3. 方式三:生成新镜像,推送到docker私服中

    适用于大型项目,并且整个项目都是使用k8s等云原生环境的场景。

    Jenkins发送dockerfile和相关项目jar包到docker服务器中,并且根据dockerfile生成新的镜像,再将新的镜像推送到Harbor(docker私服)中,再由k8s集群去拉取镜像生成相应的docker容器。

    image-20230208195951246

方式一外挂目录

实现步骤:

  1. 创建有docker环境的虚拟机

  2. 上传jar包

  3. 根据jdk镜像创建容器:

    1
    docker run -d -p 8080:8080 --name demo-docker -v jar包路径:/app.jar openjdk:8 java -jar app.jar
  4. 在Jenkins的Pre Steps中添加清除jar包命令,Post Steps中添加重启容器

方式二jar包直接打包到镜像里

实现步骤:

  1. 创建有docker环境的虚拟机

  2. 上传jar包

  3. 编写dockerfile并存在java项目中并一起提交gitlab:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 基础镜像使用java
    FROM java:8
    # 作者
    MAINTAINER wht
    # WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录
    WORKDIR /root
    # 将jar包添加到容器中并更名为springBoot_docker.jar
    ADD docker_boot*.jar /root/springBoot_docker.jar
    # 运行jar包
    RUN bash -c 'touch /root/springBoot_docker.jar'
    ENTRYPOINT ["java","-jar","/root/springBoot_docker.jar"]
    #暴露8080端口作为微服务
    EXPOSE 8080
  4. 在Jenkins的Pre Steps中添加清除jar包命令删除镜像、容器:

    image-20230208202331560

  5. Post Steps中添加编写的dockerfile并根据dockerfile创建镜像运行容器:

    • 构建镜像:docker build -f Dockerfile -t springBoot_docker:1.6
    • 运行容器:docker run -d -p 8080:8080 springBoot_docker:1.6

Jenkins集群/并发构建

  • 首先准备多台安装了Jenkins、Maven、jdk的虚拟机

  • 在主节点上进行配置:

    • 点击Manage Jenkins里的Manage Nodes and Clouds

    • 点击新建多个节点,并配置远程工作目录、标签、用法、启动方式为ssh

      image-20230209195352910

      image-20230209195702888

    • 对Item项目进行配置:

      • 在General中勾选【在必要的时候并发构建】

流水线pipeline

流水线既能作为任务的本身,也能作为Jenkinsfile

使用流水线可以让我们的任务从ui手动操作,转换为代码化,像docker的dockerfile一样,从shell命令到配置文件,更适合大型项目,可以让团队其他开发者同时参与进来,同时也可以编辑开发Jenkinswebui不能完成的更复杂的构建逻辑,作为开发者可读性也更好。

完整语法

5个必备的组成部分

  • pipeline:整条流水线
  • agent:指定执行器
  • stages:所有阶段
  • stage:某一阶段,可有多个
  • steps:阶段内的每一步,可执行命令

简单使用

  1. 首页新建Pipeline项目

  2. 编写Pipeline脚本并保存

    image-20230209201436239

  3. 点击运行按钮

如果想比原生ui更加直观的话,可有在插件管理中安装blue ocean插件

使用pipeline自动打包Docker镜像

  • 通过代码生成器,来通过ui生成pipeline脚本

  • 编写pipeline脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    pipeline{
    agent any
    tools {
    maven "maven3(Jekins里面配置的maven名称)"
    }
    stages {
    stage("拉取代码"){
    steps {
    git branch: 'master', credentialsId: 'gitlab', url: 'http:/ /192.168.44.103/root/java-project.git'
    echo '拉取成功'
    }
    }
    stage("执行构建"){
    steps {
    sh """
    cd demo-1
    mvn clean package
    """
    echo '构建成功'
    }
    }
    stage("清理工作"){
    steps {
    ...这里由代码生成器生成ssh清理文件镜像容器的脚本代码省略
    echo '清理成功'
    }
    }
    stage("发送jar包到测试服务器"){
    steps {
    ...这里由代码生成器生成的脚本代码省略
    echo '发送成功并构建了相应容器'
    }
    }
    }
    }
  • 运行项目

创建gitlab多分支job

大致流程:

image-20230209204610486

简单使用:

  1. 在blue ocean里面点击创建流水线,点击Git创建Git连接

    image-20230209204514131

  2. 修改项目的gitlab凭证配置

  3. 修改项目的Jenkinsfile配置:

    image-20230209204738905

  4. 给各个分支编写Jenkinsfile

  5. 让项目进行重新scan

  6. 点击分支查看:

    image-20230209204956745