GitLab CI/CD 自动化构建与发布实践

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: GitLab CI/CD 自动化构建与发布实践

流程介绍

CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。这篇文章中,我将会介绍基于 GitLab CI/CD 的自动化构建与发布实践。如下图所示,整个流程将分为几个部分:

  • 1.首先开发人员在本地完成项目的开发之后,将代码推送到 Gitlab 仓库中。
  • 2.当代码提交到 Gitlab 仓库时,会触发 Pipeline,Gitlab Runner 会根据 .gitlab-ci.yml 配置文件运行 Pipeline 中各阶段的任务。我总共定义了 3 个阶段:compile,build,deploy。
  • 3.在 compile 阶段,Gitlab Runner 将项目编译成 jar 包,使用 MinIO 作为缓存,首次编译项目时会从 Maven 官网拉取依赖,之后会将依赖压缩后上传至 MinIo,在下一次编译时就可以直接从 MinIO 下载依赖文件。
  • 4.在 build 阶段,Gitlab Runner 使用在 compile 阶段编译生成的 jar 包构建 Docker 镜像,并将镜像推送至镜像仓库。
  • 5.在 deploy 阶段,Gitlab Runner 使用构建好 Docker 镜像在 Kubernetes 集群中部署应用。

image.png

GitLab 介绍

GitLab[1] 是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的 Git 项目仓库,可通过 Web 界面进行访问公开的或者私有的项目。它拥有与 GitHub 类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。

GitLab CI/CD 介绍

Gitlab CI/CD[2] 是一个内置在 GitLab 中的工具,用于通过持续方法进行软件开发。

  • 持续集成(Continuous Integration):频繁地(一天多次)将代码集成到主干。让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。
  • 持续交付(Continuous Delivery):频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。
  • 持续部署(continuous Deployment):代码通过评审以后,自动部署到生产环境。是持续部署是持续交付的下一步,持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。

GitLab Runner 介绍

GitLab Runner[3] 用于执行 Gitlab CI/CD 触发的一系列作业,并将结果发送回 Gitlab。GitLab Runner 可以在 Docker 容器内运行或部署到 Kubernetes 集群中。

Pipeline

Pipeline[4] 中文称为流水线,是分阶段执行的构建任务。如:安装依赖、运行测试、打包、部署开发服务器、部署生产服务器等流程,合起来称为 Pipeline。image.png

Stage

Stage[5] 表示构建阶段,可以理解为上面所说安装依赖、运行测试等环节的流程。我们可以在一次 Pipeline 中定义多个 Stage。

Job

Job[6] 表示构建的作业(或称之为任务),表示某个 Stage 里面执行的具体任务。我们可以在 Stages 里面定义多个 Jobs。

Pipeline,Stage 和 Job 的关系可以用下图表示。image.png

MinIO 介绍

MinIO 是一款分布式,高性能的对象存储服务,专为大型私有云环境而设计。MinIO 兼容 Amazon S3 对象存储接口,非常适合存储大容量的非结构化数据,例如图片、视频、日志文件、镜像等等。本文将使用 MinIO 作为编译 Springboot 项目时使用的缓存,首次编译项目时会从 Maven 官网拉取依赖,之后会将依赖压缩后上传至 MinIo,在下一次编译时就可以直接从 MinIO 下载依赖文件。

环境搭建

前提条件

  • 部署好一套 Kubernetes 集群。
  • 安装好 Helm 工具,关于 Helm 安装可以参考 安装 Helm[7]

MinIO 部署

Helm 是 Kubernetes 生态系统中的一个软件包管理工具,方便我们快速部署应用。这里选择使用 Helm 在 Kubernetes 集群中部署 MinIO。

添加 Helm 仓库。

helm repo add minio https://helm.min.io/

使用以下命令安装 Helm。设置用户名为 admin,密码为 admin123456,在 minio 命名空间中部署。

helm install minio \
--set accessKey=admin,secretKey=admin123456 \
--namespace minio --create-namespace \
minio/minio
#返回结果
minio/minio
NAME: minio
LAST DEPLOYED: Wed Aug 18 13:23:45 2021
NAMESPACE: minio
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Minio can be accessed via port 9000 on the following DNS name from within your cluster:
minio.minio.svc.cluster.local
To access Minio from localhost, run the below commands:
  1. export POD_NAME=$(kubectl get pods --namespace minio -l "release=minio" -o jsonpath="{.items[0].metadata.name}")
  2. kubectl port-forward $POD_NAME 9000 --namespace minio
Read more about port forwarding here: http://kubernetes.io/docs/user-guide/kubectl/kubectl_port-forward/
You can now access Minio server on http://localhost:9000. Follow the below steps to connect to Minio server with mc client:
  1. Download the Minio mc client - https://docs.minio.io/docs/minio-client-quickstart-guide
  2. Get the ACCESS_KEY=$(kubectl get secret minio -o jsonpath="{.data.accesskey}" | base64 --decode) and the SECRET_KEY=$(kubectl get secret minio -o jsonpath="{.data.secretkey}" | base64 --decode)
  3. mc alias set minio-local http://localhost:9000 "$ACCESS_KEY" "$SECRET_KEY" --api s3v4
  4. mc ls minio-local
Alternately, you can use your browser or the Minio SDK to access the server - https://docs.minio.io/categories/17

为了在本地电脑可以访问到 MinIO 的 Web 界面,使用以下命令开启端口转发。你也可以选择通过 NodePort 或者其他方式将 MinIO 服务暴露到集群外部。

export POD_NAME=$(kubectl get pods --namespace minio -l "release=minio" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 9000 --namespace minio

浏览器输入 http://localhost:9000 访问 MinIO 界面。用户名:admin,密码 admin123456,是我们前面用 helm install 安装 minio 时设置的。image.pngimage.pngimage.pngimage.png

kubectl create secret -n acp generic s3access \
--from-literal=accesskey=admin \
--from-literal=secretkey=admin123456

添加 Gilab Helm 仓库,并下载 Gitlab Runner Helm 资源文件。

helm repo add gitlab https://charts.gitlab.io
helm pull gitlab/gitlab-runner --untar

编辑 gitlab-runner 目录下的 values.yaml 文件,有以下几个配置需要修改。

  • gitlabUrl:设置 Gitlab 的 IP 地址。
  • runnerRegistrationToken:设置 Gitlab Runner 注册的 token。进入项目 -> Settings -> CI/CD -> Runners settings 查看注册 Gitlab Runner 所需的 registration token。image.png
  • cache:设置缓存。
# gitlab IP 地址
gitlabUrl: http://gitlab ip地址/
# 注册 gitlab runner 的 token
runnerRegistrationToken: "o_4r2uvptQYmmr79e2uF"
runners:
# 设置缓存
  cache:
    ## General settings
    cacheType: s3
    cachePath: "gitlab-runner-elasticsearch-api" # 缓存路径,gitlab runner 会自动在 bucket 下创建该目录
    cacheShared: true
    ## S3 settings
    s3ServerAddress: minio.minio.svc.cluster.local:9000 # kubernetes 集群 clusterip service 访问的地址
    s3BucketName: gitlab-runner-cache-maven # bucket 名字
    s3BucketLocation:
    s3CacheInsecure: true # http 登录
    secretName: s3access # 使用 Minio 用户名密码创建的 secert

配置完成后,使用以下命令安装 Gitlab Runner。

helm install -n acp gitlab-runner-elasticsearch-api gitlab-runner

一切顺利的话,可以在 Gitlab 上看到 Gitlab Runner 成功注册上来。image.png查看在 Kubernetes 集群中创建的 Gitlab Runner 的 Pod

❯ kubectl get pod -n acp | grep runner
gitlab-runner-elasticsearch-api-gitlab-runner-88f7b64fc-rdfch   1/1     Running     0          113s

配置 .gitlab-ci.yml 文件

Gitlab CI/CD 通过 .gitlab-ci.yml 配置文件中定义流水线(Pipeline)的各个阶段(Stage),以及各个阶段中的若干作业(Job)。例如以下配置文件,我们定义了 3 个 Stage:

  • 1.compile:使用 openjdk 镜像编译项目。
  • 2.build:使用 compile 阶段编译好的 jar 包构建 Docker 镜像,并推送至镜像仓库。
  • 3.deploy:在 Kubernetes 集群中使用构建好的 Docker 镜像部署应用。
stages:
  - compile
  - build
  - deploy
variables:
  KUBECONFIG: /tmp/config
  CI_REGISTRY: 你的镜像仓库 IP
  CI_REGISTRY_IMAGE: 你的镜像仓库项目路径
# maven 依赖缓存
cache:
  paths:
    - cache 
# 编译项目
compile:
  stage: compile
  image: openjdk:8-jdk-alpine
  # 只有打 tag 时才会触发任务
  only:
    - tags
  # 编译项目,跳过单元测试,指定本地依赖目录
  script:
    - ./mvnw package -Dmaven.test.skip=true -Dmaven.repo.local=cache
  # 将编译好的 jar 包传递给下一个阶段,用于 kaniko 构建 docker 镜像
  artifacts:
    paths:
      - target
# 构建镜像
build:
  image: gcr.io/kaniko-project/executor:debug # 可能需要手动提前下载
  stage: build
  only:
    - tags
  script:
   # 使用 kaniko 构建 docker 镜像
    - mkdir -p /kaniko/.docker
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASS\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
#部署到 kubernetes 环境中
deploy:
  image: bitnami/kubectl:1.19
  stage: deploy
  only:
    - tags
  script:
    # 设置 kubectl 容器的 kubeconfig 文件,使 kubectl 容器有在 Kubernetes 中部署应用的权限
    - echo $kube_config | base64 -id > $KUBECONFIG
    - sed -i "s/CI_COMMIT_TAG/$CI_COMMIT_TAG/g" manifests/deployment.yaml
    - cat manifests/*.yaml
    - kubectl apply -f manifests/

注意事项:

  • 为了安全性,我们将镜像仓库的用户名、密码以及 Kubernetes 集群的 kubeconfig 文件设置在 Gitlab 的 Secret variables 中。进入项目 -> Settings -> CI/CD -> Secret variables。注意 kubeconfig 文件的值是 base64 加密后的,镜像仓库的用户名和密码正常设置即可。image.png需要在项目根路径下创建一个 cache 目录,用于临时存放从 MinIo 下载的依赖,这个目录名可以自定义,要和 .gitlab-ci.yml 文件中设置的 cache path 一致。在 compile 阶段指定 -Dmaven.repo.local=cache 参数使用 cache 作为依赖仓库,这样就可以用上从 MinIO 中提取的依赖了。
  • 在 build 阶段使用 compile 阶段编译好的 jar 包构建 Docker 镜像,Dockerfile 内容如下。
FROM openjdk:8-jdk-alpine  
# 设置工作目录  
WORKDIR /app  
# 语言,时区设置  
ENV TZ=Asia/Shanghai  
ENV LANG=en_US.UTF-8  
ENV LANGUAGE=en_US:en  
ENV iC_ALL=en_US.UTF-8  
EXPOSE 8080  
# 拷贝 compile 阶段编译好的 jar 包  
COPY target/*.jar elasticsearch-api.jar  
CMD ["java","-jar","elasticsearch-api.jar"]
  • deploy 阶段用于在 Kubernetes 环境中部署的资源文件在 manifests 目录中,根据你自身项目的情况来编写。image.png

流程验证

完成项目的开发之后,将代码推送到 Gitlab 仓库中。

git add .
git commit -m "首次触发任务"
git push

此时并不会触发 Pipline,因为我们在 .gitlab-ci.yml 配置文件中设置了只有打了 tag 才会触发 Pipline。推送 tag 触发 Pipeline。

git tag 3.0.4
git push origin 3.0.4

等待 Pipeline 执行完成。image.pngimage.pngimage.pngimage.pngimage.png

参考资料

  • [1][Gitlab] (https://about.gitlab.com/)
  • [2][Gitlab CI/CD] (https://docs.gitlab.com/ee/ci/index.html)
  • [3][GitLab Runner] (https://docs.gitlab.com/runner/)
  • [4][Pipelines] (https://docs.gitlab.com/ce/ci/pipelines.html)
  • [5][Stages] (https://docs.gitlab.com/ce/ci/yaml/README.html#stages)
  • [6][Jobs] (https://docs.gitlab.com/ce/ci/pipelines.html#jobs)
  • [7][安装 Helm] (https://helm.sh/zh/docs/intro/install/)
  • [Use kaniko to build Docker images] (https://docs.gitlab.com/ee/ci/docker/using_kaniko.html)
  • [常用容器镜像构建工具和方案介绍] (https://cloud.51cto.com/art/202108/679757.htm)
  • [如何在 Docker 中使用 Docker] (https://mp.weixin.qq.com/s/vARJJeNLBKgxn4T7oqC41Q)
  • [配置使用分布式缓存] (http://docs.idevops.site/gitlabci/chapter05/01/05-%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8minio%E5%88%86%E5%B8%83%E5%BC%8F%E5%AD%98%E5%82%A8/)
  • [用 GitLab 做 CI/CD 是什么感觉,太强了!!] (https://cloud.tencent.com/developer/article/1684099)
  • [GitLab CI/CD 介绍和使用] (https://blinkfox.github.io/2018/11/22/ruan-jian-gong-ju/devops/gitlab-ci-jie-shao-he-shi-yong/)
  • [GitLab CI/CD 官网] (https://docs.gitlab.com/ee/ci/)
  • [DevOps之Gitlab-CICD实践篇] (https://zhuanlan.zhihu.com/p/105157319)
  • [GitLab CI/CD 实践] (https://xiangflight.github.io/gitlab-cd-practice/)
  • [CI/CD是什么?如何理解持续集成、持续交付和持续部署] (https://www.redhat.com/zh/topics/devops/what-is-ci-cd)
相关实践学习
通过容器镜像仓库与容器服务快速部署spring-hello应用
本教程主要讲述如何将本地Java代码程序上传并在云端以容器化的构建、传输和运行。
Kubernetes极速入门
Kubernetes(K8S)是Google在2014年发布的一个开源项目,用于自动化容器化应用程序的部署、扩展和管理。Kubernetes通常结合docker容器工作,并且整合多个运行着docker容器的主机集群。 本课程从Kubernetes的简介、功能、架构,集群的概念、工具及部署等各个方面进行了详细的讲解及展示,通过对本课程的学习,可以对Kubernetes有一个较为全面的认识,并初步掌握Kubernetes相关的安装部署及使用技巧。本课程由黑马程序员提供。   相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
15天前
|
机器学习/深度学习 人工智能 jenkins
软件测试中的自动化与持续集成实践
在快速迭代的软件开发过程中,自动化测试和持续集成(CI)是确保代码质量和加速产品上市的关键。本文探讨了自动化测试的重要性、常见的自动化测试工具以及如何将自动化测试整合到持续集成流程中,以提高软件测试的效率和可靠性。通过案例分析,展示了自动化测试和持续集成在实际项目中的应用效果,并提供了实施建议。
|
15天前
|
Java 测试技术 持续交付
探索自动化测试在软件开发中的关键作用与实践
在现代软件开发流程中,自动化测试已成为提升产品质量、加速交付速度的不可或缺的一环。本文深入探讨了自动化测试的重要性,分析了其在不同阶段的应用价值,并结合实际案例阐述了如何有效实施自动化测试策略,以期为读者提供一套可操作的实践指南。
|
14天前
|
监控 jenkins 测试技术
自动化测试框架的构建与实践
【10月更文挑战第40天】在软件开发周期中,测试环节扮演着至关重要的角色。本文将引导你了解如何构建一个高效的自动化测试框架,并深入探讨其设计原则、实现方法及维护策略。通过实际代码示例和清晰的步骤说明,我们将一起探索如何确保软件质量,同时提升开发效率。
34 1
|
2天前
|
数据库 Docker 容器
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。Dockerfile定义了构建镜像所需的所有指令,包括基础镜像选择、软件安装、文件复制等,极大提高了开发和部署的灵活性与一致性。掌握Dockerfile的编写,对于提升软件开发效率和环境管理具有重要意义。
19 9
|
5天前
|
敏捷开发 前端开发 Java
软件测试中的自动化测试框架选择与实践
在当今软件开发生命周期中,自动化测试已成为提升软件质量和开发效率的关键手段。本文旨在探讨自动化测试框架的选择标准及其在实际项目中的应用实践。通过对主流自动化测试框架的分析比较,结合具体案例,本文将阐述如何根据项目需求和团队特点选择合适的自动化测试工具,并分享实施过程中的经验教训。
14 1
|
13天前
|
Devops jenkins 测试技术
DevOps实践:自动化部署与持续集成的融合之旅
【10月更文挑战第41天】在软件开发的世界中,快速迭代和高效交付是企业竞争力的关键。本文将带你走进DevOps的核心实践——自动化部署与持续集成,揭示如何通过它们提升开发流程的效率与质量。我们将从DevOps的基本理念出发,逐步深入到具体的技术实现,最终展示一个实际的代码示例,让理论与实践相结合,为你的开发旅程提供清晰的指引。
25 4
|
7月前
|
Linux 应用服务中间件 网络安全
linux安装Gitlab
linux安装Gitlab
174 0
|
4月前
|
Shell Docker 容器
GitlabCI学习笔记之一:安装Gitlab和GitLabRunner
GitlabCI学习笔记之一:安装Gitlab和GitLabRunner
|
3月前
|
Docker 容器
Docker安装Gitlab和Gitlab-Runner并实现项目CICD
Docker安装Gitlab和Gitlab-Runner并实现项目CICD
|
5月前
|
Devops 持续交付 开发工具
入职必会-开发环境搭建54-GitLab下载和安装
GitLab 是一个基于 web 的 Git 仓库管理工具,提供了代码托管、版本控制、协作开发、持续集成等功能,是一个综合的 DevOps 平台。用户可以使用 GitLab 托管他们的代码仓库,并利用其丰富的功能来管理和协作开发项目。 以下是 GitLab 的一些主要特点和功能。
入职必会-开发环境搭建54-GitLab下载和安装