天天看點

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 叢集中部署應用。
GitLab CI/CD 自動化建構與釋出實踐

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。

GitLab CI/CD 自動化建構與釋出實踐

Stage

Stage

[5] 表示建構階段,可以了解為上面所說安裝依賴、運作測試等環節的流程。我們可以在一次 Pipeline 中定義多個 Stage。

Job

Job

[6] 表示建構的作業(或稱之為任務),表示某個 Stage 裡面執行的具體任務。我們可以在 Stages 裡面定義多個 Jobs。

Pipeline,Stage 和 Job 的關系可以用下圖表示。

GitLab CI/CD 自動化建構與釋出實踐

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 時設定的。

GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐
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。
    GitLab CI/CD 自動化建構與釋出實踐
  • 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 成功注冊上來。

GitLab CI/CD 自動化建構與釋出實踐

檢視在 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 加密後的,鏡像倉庫的使用者名和密碼正常設定即可。
    GitLab CI/CD 自動化建構與釋出實踐
    需要在項目根路徑下建立一個 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 目錄中,根據你自身項目的情況來編寫。
    GitLab CI/CD 自動化建構與釋出實踐

流程驗證

完成項目的開發之後,将代碼推送到 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 執行完成。

GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐
GitLab CI/CD 自動化建構與釋出實踐

參考資料

  • [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)