文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

gitlab ci cd 命令的使用不完全指南

2023-05-16 11:12

关注

gitlab 可能大家很常用,CI、CD 也应该早有耳闻,但是可能还没有去真正地了解过,这篇文章就是我对 gitlab CI、CD 的一些理解,以及踩过的一些坑,希望能帮助到大家。

什么是 CI、CD

CI(Continuous Integration)持续集成,CD(Continuous Deployment)持续部署(也包含了持续交付的意思)。

CI 指的是一种开发过程的的自动化流程,在我们提交代码的时候,一般会做以下操作:

这个过程我们可以称之为 CI,也就是持续集成,这个过程是自动化的,也就是说我们不需要手动去执行这些操作,只需要提交代码,这些操作就会自动执行。

CD 指的是在我们 CI 流程通过之后,将代码自动发布到服务器的过程,这个过程也是自动化的。 在有了前面 CI 的一些操作之后,说明我们的代码是可以安全发布到服务器的,所以就可以进行发布的操作。

为什么要使用 CI、CD

实际上,就算没有 CI、CD 的这些花里胡哨的概念,对于一些重复的操作,我们也会尽量想办法会让它们可以自动化实现的,只不过可能效率上没有这么高,但是也是可以的。

CI、CD 相比其他方式的优势在于:

gitlab CI、CD

在开始之前,我们可以通过下图来了解一下 CI、CD 的整体流程:

在 CD 流程结束之后,我们就可以在服务器上看到我们的代码了。

gitlab CI、CD 中的一些基本概念

在开始之前,我们先来了解一下 gitlab CI、CD 中的一些基本概念:

CI、CD 的工作模型

我们以下面的配置为例子,简单说明一下 pipelinestagejob 的工作模型,以及 cacheartifacts 的作用:

ci 配置文件(也就是一个 pipeline 的所有任务):

# 定义一个 `pipeline` 的所有阶段,一个 `pipeline` 可以包含多个 `stage`,每个 `stage` 又包含多个 `job`。
# stage 的顺序是按照数组的顺序来执行的,也就是说 stage1 会先执行,然后才会执行 stage2。
stages:
  - stage1 # stage 的名称
  - stage2
# 定义一个 `job`,一个 `job` 就是一个任务,也是最小的执行单元。
job1:
  stage: stage1 # 指定这个 `job` 所属的 `stage`,这个 `job` 只会在 `stage1` 执行。
  script: # 指定这个 `job` 的脚本,这个脚本会在 `job` 执行的时候执行。
    - echo "hello world" > "test.txt"
  tags: # 指定这个 `job` 所属的 `runner` 的标签,这个 `job` 只会在标签为 `tag1` 的 `runner` 上执行。
    - tag1
  # cache 可以在当前 `pipeline` 后续的 `job` 中使用,也可以在后续的 `pipeline` 中使用。
  cache: # 指定这个 `job` 的缓存,这个缓存会在 `job` 执行结束之后保存起来,下次执行的时候会先从缓存中读取,如果没有缓存,就会重新下载。
    key: $CI_COMMIT_REF_SLUG # 缓存的 key
    paths: # 缓存的路径
      - node_modules/
  artifacts: # 指定这个 `job` 的构建产物,这个构建产物会在 `job` 执行结束之后保存起来。可以在下一个 stage 中使用,也可以在 pipeline 执行结束之后下载下来。
    paths:
      - test.txt
job2:
  stage: stage1
  script:
    - cat test.txt
  tags:
    - tag1
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
    # 指定这个 `job` 的缓存策略,只会读取缓存,不会写入缓存。默认是既读取又写入,在 job 开始的时候读取,在 job 结束的时候写入。
    # 但是实际上,只有在安装依赖的时候是需要写入缓存的,其他 job 都使用 pull 即可。
    policy: pull
# job3 和 job4 都属于 stage2,所以 job3 和 job4 会并行执行。
# job3 和 job4 都指定了 tag2 标签,所以 job3 和 job4 只会在标签为 tag2 的 runner 上执行。
# 同时,在 job1 中,我们指定了 test.txt 作为构建产物,所以 job3 和 job4 都可以使用 test.txt 这个文件。
job3:
  stage: stage2
  script:
    - cat test.txt
  tags:
    - tag1
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
    policy: pull
job4:
  stage: stage2
  script:
    - cat test.txt
  tags:
    - tag1
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
    policy: pull

上面的配置文件的 pipeline 执行过程可以用下面的图来表示:

说明:

需要特别注意的是:cache 是跨流水线共享的,而 artifacts 只会在当前流水线的后续 stage 共享。

其他一些在个人实践中的一些经验

gitlab 的 CI、CD 是一个很庞大的话题,同时很多内容可能比较少用,所以本文只是介绍个人在实践中用到的一些内容,其他的东西如果有需要,可以自行查阅官方文档。

指定特定分支才会执行的 job

这个算是基本操作了,我们可以通过 only 来指定特定分支才会执行的 job,也有其他方法可以实现,比如 rules,具体请参考官方文档。

deploy-job:
  stage: deploy
  # 当前的这个 job 只会在 master 分支代码更新的时候会执行
  only:
    - "master"

不同 job 之间的依赖

这个也是基本操作,我们可以通过 needs 来指定不同 job 之间的依赖关系,比如 job1 依赖 job2,那么 job1 就会在 job2 执行完毕之后才会执行。

job1:
  stage: deploy
  needs:
    - job2

指定执行 job 的 runner

我们可以通过 tags 来指定 job 执行的 runner,比如我们可以指定 job 只能在 api 标签的 runner 上执行。

build-job:
  stage: build
  tags:
    - api

如果我们没有标签为 apirunner,那么这个 job 就会一直不会被执行,所以需要确保我们配置的 tag 有对应的 runner

指定 job 的 docker image

注意:这个只在我们的 runnerexecutordocker 的时候才会生效。也就是我们的 runner 是一个 docker 容器。

有时候,我们需要执行一些特定命令,但是我们全局的 docker 镜像里面没有,可能只需要一个特定的 docker 镜像,这个时候我们可以通过 image 来指定 jobdocker 镜像。

deploy-job:
  stage: deploy
  tags:
    - api
  # 指定 runner 的 docker image
  image: eleven26/rsync:1.3.0
  script:
    # 下面这个命令只在上面指定的 docker 镜像中存在
    - rsync . root@example.com:/home/www/foo

为我们的集成测试指定一个 service

在我们的 CI 流程中,可能会有一些集成测试需要使用到一些服务,比如我们的 mysql,这个时候我们可以通过 services 来指定我们需要的服务。

test_rabbitmq:
  # 这会启动一个 rabbitmq 3.8 的 docker 容器,我们的 job 就可以使用这个容器了。
  # 我们的 job 可以连接到一个 rabbitmq 的服务,然后进行测试。
  # 需要注意的是,这个容器只会在当前 job 执行的时候存在,执行完毕之后就会被删除。所以产生的数据不会被保留。
  services:
    - rabbitmq:3.8
  stage: test
  only:
    - master
  tags:
    - go
  script:
    # 下面的测试命令会连接到上面启动的 rabbitmq 服务
    - "go test -v -cover ./pkg/rabbitmq"

复用 yaml 配置片段

yaml 中,有一种机制可以让我们复用 yaml 配置片段,比如:

# 发布代码的 job
.deploy-job: &release-job
  tags:
    - api
  image: eleven26/rsync:1.3.0
  script:
    - rsync . root@example.com:/home/www/foo
deploy-release:
  <<: *release-job
  stage: deploy
  only:
    - "release"
deploy-master:
  <<: *release-job
  stage: deploy
  only:
    - "master"

上面的代码中,我们定义了一个 release-job 的配置片段,然后在 deploy-releasedeploy-master 中,我们都引用了这个配置片段,这样我们就可以复用这个配置片段了。 等同于下面的代码:

# 发布代码的 job
.deploy-job: &release-job
  tags:
    - api
  image: eleven26/rsync:1.3.0
  script:
    - rsync . root@example.com:/home/www/foo
deploy-release:
  tags:
    - api
  image: eleven26/rsync:1.3.0
  script:
    - rsync . root@example.com:/home/www/foo
  stage: deploy
  only:
    - "release"
deploy-master:
  tags:
    - api
  image: eleven26/rsync:1.3.0
  script:
    - rsync . root@example.com:/home/www/foo
  stage: deploy
  only:
    - "master"

yaml 的术语中,这一种机制叫做 anchor

cache vs artifacts

初次使用的人,可能会对这个东西有点迷惑,因为它们好像都是缓存,但是实际上,它们的用途是不一样的。

指定 artifacts 的过期时间

我们可以通过 expire_in 来指定 artifacts 的过期时间,比如:

job1:
  stage: build
  only:
    - "release"
  image: eleven26/apidoc:1.0.0
  tags:
    - api
  artifacts:
    paths:
      - public
    expire_in: 1 hour

因为我们的 artifacts 有时候只是生成一些需要部署到服务器的东西,然后在下一个 stage 使用,所以是不需要长期保留的。所以我们可以通过 expire_in 来指定一个比较短的 artifacts 的过期时间。

cache 只 pull 不 push

gitlab CI 的 cache 有一个 policy 属性,它的值默认是 pull-push,也就是在 job 开始执行的时候会拉取缓存,在 job 执行结束的时候会将缓存指定文件夹的内容上传到 gitlab 中。

但是在实际使用中,我们其实只需要在安装依赖的时候上传这些缓存,其他时候都只是读取缓存的。所以我们在安装依赖的 job 中使用默认的 policy,而在后续的 job 中,我们可以通过 policy: pull 来指定只拉取缓存,不上传缓存。

job:
  tags:
    - api
  image: eleven26/rsync:1.3.0
  cache:
    key:
      files:
        - composer.json
        - composer.lock
    paths:
      - "vendor/"
    policy: pull  # 只拉取 vendor,在 job 执行完毕之后不上传 vendor

cache 的 key 使用文件

这一个特性是非常有用的,在现代软件工程的实践中,往往通过 *.lock 文件来记录我们使用的额依赖的具体版本,以保证在不同环境中使用的时候保持一致的行为。

所以,相应的,我们的缓存也可以在 *.lock 这类文件发生变化的时候,重新生成缓存。上面的例子就使用了这种机制。

script 中使用多行命令

script 中,我们可以使用多行命令,比如:

job:
  script:
    # 我们可以通过下面这种方式来写多行的 shell 命令,也就是以一个竖线开始,然后换行
    - |
      if [ "$release_host" != "" ]; then
        host=$release_host
      fi

CD - 如何同步代码到服务器

如果我们的项目需要部署到服务器上,那么我们还需要做一些额外的操作,比如同步代码到服务器上。 如果我们的 gitlab 是通过容器执行的,或者我们的 runner 的 executor 是 docker,那么有一种比较常见的方法是通过 ssh 私钥来进行部署。

我们可以通过以下流程来实现:

before_script:
  - chmod 600 $PRIVATE_KEY
deploy:
  stage: deploy
  image: eleven26/rsync:1.3.0
  script:
    # $user 是 ssh 的用户
    # $host 是 ssh 的主机
    # $port 是 ssh 的端口
    # $PRIVATE_KEY 是我们在 gitlab 中配置的私钥
    - rsync -az -e "ssh -o StrictHostKeyChecking=no -p $port -i $PRIVATE_KEY" --delete --exclude='.git' . $user@$host:/home/www

这里的 rsync 命令中,我们使用了 -o StrictHostKeyChecking=no 参数,这是为了避免每次都需要手动输入 yes 来确认服务器的指纹。

安全最佳实践:

必须严格遵循以上两步,否则会造成严重的安全问题。

总结

最后,总结一下本文中一些比较关键的内容:

以上就是gitlab ci cd 不完全指南的详细内容,更多关于gitlab ci cd 的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-服务器
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯