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

简介: 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)
相关实践学习
通过workbench远程登录ECS,快速搭建Docker环境
本教程指导用户体验通过workbench远程登录ECS,完成搭建Docker环境的快速搭建,并使用Docker部署一个Nginx服务。
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
2月前
|
Kubernetes Java 网络安全
GitLab CI构建SpringBoot-2.3应用
SpringBoot应用提交到GitLab后,会自动构建成docker镜像,甚至自动部署在K8S环境
GitLab CI构建SpringBoot-2.3应用
|
2月前
|
测试技术 Shell 持续交付
提升开发效率之利用GitLab CI/CD打包Android项目
提升开发效率之利用GitLab CI/CD打包Android项目
|
4月前
|
安全 Shell 持续交付
Gitlab CI/CD
Gitlab CI/CD
55 0
|
4月前
|
监控 测试技术 持续交付
构建自动化部署流水线:GitLab CI/CD的实践指南
在现代软件开发中,快速且可靠地交付软件是至关重要的。为了实现这一目标,构建自动化部署流水线成为一种常见的实践方法。本文将介绍如何使用GitLab CI/CD来构建自动化部署流水线,以提高开发团队的效率和软件交付质量。
591 0
|
5月前
|
存储 缓存 运维
Gitlab CI 小试牛刀
前言 前端工程化中 CI 是必不可少的一环,大家的团队中或多或少都有不同的 CI 能力,有的可能由运维同学使用 JIRA 配置(前司),更多的相信已经迁移到 Gitlab 到 CI/CD 中。那么今天就来聊聊什么是 CI 以及如何在 Gitlab 中配置 CI 能力。
|
6月前
|
存储 Ubuntu Java
还在用Jenkins?试试Gitlab的CI/CD功能吧,贼带劲!
还在用Jenkins?试试Gitlab的CI/CD功能吧,贼带劲!
|
9月前
|
Java jenkins Linux
Linux系统:第十五章:gitlab集成CI
Linux系统:第十五章:gitlab集成CI
102 0
Linux系统:第十五章:gitlab集成CI
|
9月前
|
Java Shell 测试技术
GitLab CI + Docker 持续集成操作手册
GitLab CI + Docker 持续集成操作手册
GitLab CI + Docker 持续集成操作手册
|
10月前
|
负载均衡 jenkins Java
CI/CD之Jenkins+Gitlab(五)
CI/CD之Jenkins+Gitlab(五)
144 0
CI/CD之Jenkins+Gitlab(五)
|
10月前
|
jenkins 应用服务中间件 持续交付
CI/CD之Jenkins+Gitlab(四)
CI/CD之Jenkins+Gitlab(四)
118 1
CI/CD之Jenkins+Gitlab(四)
推荐文章
更多