全部產品
Search
文件中心

Container Service for Kubernetes:基於工作流程叢集構建Golang專案的CI Pipeline

更新時間:Jul 01, 2024

ACK One工作流程叢集基於開源Argo Workflows專案構建,全託管Argo Workflows,具有極致彈性、自動擴充、無營運成本等優勢,可以協助您快速實現更簡單、低成本、高效率的CI流水線。本文為您介紹如何基於工作流程叢集構建Golang專案的CI Pipeline。

方案介紹

ACK One工作流程叢集構建CI Pipeline,主要使用BuildKit實現容器鏡像的構建和推送,並使用BuildKit Cache加速鏡像的構建。使用NAS儲存Go mod cache,可加速go testgo build運行過程,最終大幅加速CI Pipeline的流程。

預置工作流程範本說明

工作流程叢集中預設已經預置了名為ci-go-v1的CI工作流程範本(ClusterWorkflowTemplate),其使用BuildKit Cache和NAS儲存Go mode cache,可大幅加速CI Pipeline的流程。

您可以直接使用預置模板,也可以基於預置模板自訂自己的CI工作流程範本。

預置的CI工作流程範本中包含以下流程:

  1. Git Clone & Checkout

    • 用於Clone Git倉庫,將Git倉庫Checkout到目標分支。

    • 擷取Commit ID,在構建鏡像時根據Commit ID追加Tag尾碼。

  2. Run Go Test

    • 預設運行Git Repo(Go專案)中的所有測試案例。

    • 可通過工作流程參數enable_test控制是否運行該步驟。

    • 其中Go mod cache儲存在NAS的/pkg/mod目錄,用於go test和後續的go build的加速。

  3. Build & Push Image

    • 使用BuildKit構建和推送容器鏡像,並使用BuildKit Cache中registry類型的cache來加速鏡像構建。

    • 鏡像Tag預設使用{container_tag}-{commit_id}格式,可在提交工作流程時通過參數控制是否追加Commit ID。

    • 推送鏡像的同時,也會推送覆蓋其latest版本鏡像。

預置的CI工作流程範本內容如下:

展開查看模板內容

apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
  name: ci-go-v1
spec:
  entrypoint: main
  volumes:
  - name: run-test
    emptyDir: {}
  - name: workdir
    persistentVolumeClaim:
      claimName: pvc-nas
  - name: docker-config
    secret:
      secretName: docker-config
  arguments:
    parameters:
    - name: repo_url
      value: ""
    - name: repo_name
      value: ""
    - name: target_branch
      value: "main"
    - name: container_image
      value: ""
    - name: container_tag
      value: "v1.0.0"
    - name: dockerfile
      value: "./Dockerfile"
    - name: enable_suffix_commitid
      value: "true"
    - name: enable_test
      value: "true"
  templates:
    - name: main
      dag:
        tasks:
          - name: git-checkout-pr
            inline:
              container:
                image: alpine:latest
                command:
                  - sh
                  - -c
                  - |
                    set -eu
                    
                    apk --update add git
          
                    cd /workdir
                    echo "Start to Clone "{{workflow.parameters.repo_url}}
                    git -C "{{workflow.parameters.repo_name}}" pull || git clone {{workflow.parameters.repo_url}} 
                    cd {{workflow.parameters.repo_name}}
          
                    echo "Start to Checkout target branch" {{workflow.parameters.target_branch}}
                    git checkout --track origin/{{workflow.parameters.target_branch}} || git checkout {{workflow.parameters.target_branch}}
                    git pull
                    
                    echo "Get commit id" 
                    git rev-parse --short origin/{{workflow.parameters.target_branch}} > /workdir/{{workflow.parameters.repo_name}}-commitid.txt
                    commitId=$(cat /workdir/{{workflow.parameters.repo_name}}-commitid.txt)
                    echo "Commit id is got: "$commitId
                                        
                    echo "Git Clone and Checkout Complete."
                volumeMounts:
                - name: "workdir"
                  mountPath: /workdir
                resources:
                  requests:
                    memory: 1Gi
                    cpu: 1
                activeDeadlineSeconds: 1200
          - name: run-test
            when: "{{workflow.parameters.enable_test}} == true"
            inline: 
              container:
                image: golang:1.22-alpine
                command:
                  - sh
                  - -c
                  - |
                    set -eu
                    
                    if [ ! -d "/workdir/pkg/mod" ]; then
                      mkdir -p /workdir/pkg/mod
                      echo "GOMODCACHE Directory /pkg/mod is created"
                    fi
                    
                    export GOMODCACHE=/workdir/pkg/mod
                    
                    cp -R /workdir/{{workflow.parameters.repo_name}} /test/{{workflow.parameters.repo_name}} 
                    echo "Start Go Test..."
                    
                    cd /test/{{workflow.parameters.repo_name}}
                    go test -v ./...
                    
                    echo "Go Test Complete."
                volumeMounts:
                - name: "workdir"
                  mountPath: /workdir
                - name: run-test
                  mountPath: /test
                resources:
                  requests:
                    memory: 4Gi
                    cpu: 2
              activeDeadlineSeconds: 1200
            depends: git-checkout-pr    
          - name: build-push-image
            inline: 
              container:
                image: moby/buildkit:v0.13.0-rootless
                command:
                  - sh
                  - -c
                  - |         
                    set -eu
                     
                    tag={{workflow.parameters.container_tag}}
                    if [ {{workflow.parameters.enable_suffix_commitid}} == "true" ]
                    then
                      commitId=$(cat /workdir/{{workflow.parameters.repo_name}}-commitid.txt)
                      tag={{workflow.parameters.container_tag}}-$commitId
                    fi
                    
                    echo "Image Tag is: "$tag
                    echo "Start to Build And Push Container Image"
                    
                    cd /workdir/{{workflow.parameters.repo_name}}
                    
                    buildctl-daemonless.sh build \
                    --frontend \
                    dockerfile.v0 \
                    --local \
                    context=. \
                    --local \
                    dockerfile=. \
                    --opt filename={{workflow.parameters.dockerfile}} \
                    build-arg:GOPROXY=http://goproxy.cn,direct \
                    --output \
                    type=image,\"name={{workflow.parameters.container_image}}:${tag},{{workflow.parameters.container_image}}:latest\",push=true,registry.insecure=true \
                    --export-cache mode=max,type=registry,ref={{workflow.parameters.container_image}}:buildcache \
                    --import-cache type=registry,ref={{workflow.parameters.container_image}}:buildcache
                    
                    echo "Build And Push Container Image {{workflow.parameters.container_image}}:${tag} and {{workflow.parameters.container_image}}:latest Complete."
                env:
                  - name: BUILDKITD_FLAGS
                    value: --oci-worker-no-process-sandbox
                  - name: DOCKER_CONFIG
                    value: /.docker
                volumeMounts:
                  - name: workdir
                    mountPath: /workdir
                  - name: docker-config
                    mountPath: /.docker
                securityContext:
                  seccompProfile:
                    type: Unconfined
                  runAsUser: 1000
                  runAsGroup: 1000
                resources:
                  requests:
                    memory: 4Gi
                    cpu: 2
              activeDeadlineSeconds: 1200
            depends: run-test

模板中暴露的參數如下:

參數

說明

樣本值

entrypoint

定義入口模板。

main

repo_url

Git倉庫的url。

https://github.com/ivan-cai/echo-server.git

repo_name

倉庫名稱。

echo-server

target_branch

倉庫的目標分支。

預設為main。

main

container_image

要構建的鏡像。格式如下:

<ACR EE Domain>/<ACR EE命名空間>/<倉庫名>。

test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server

container_tag

要構建的鏡像Tag。

預設為v1.0.0。

v1.0.0

dockerfile

Dockerfile目錄和檔案名稱。

專案根目錄下的相對路徑,預設為./Dockerfile

./Dockerfile

enable_suffix_commitid

是否在鏡像Tag後追加Commit ID。

  • true:追加

  • false:不追加

預設值為true。

true

enable_test

是否開啟運行Go Test步驟。

  • true:開啟

  • false:不開啟

預設值為true。

true

前提條件

操作步驟

本文以公用Git倉庫為例為您介紹構建CI Pipeline的操作,如果您在工作流程的CI Pipeline中使用的是私人Git倉庫,則需要在CI流程中先成功Clone該私人倉庫。具體的Clone操作,請參見在CI Pipeline中Clone私人Git倉庫

重要

儲存容器鏡像訪問憑證的Secret和掛載的NAS儲存卷都需要與最終提交的工作流程在同一個命名空間下。

步驟一:在工作流程叢集中建立ACR EE訪問憑證

ACR EE訪問憑證主要用於BuildKit推送鏡像。

  1. 為ACR EE配置訪問憑證。具體操作,請參見配置訪問憑證

  2. 執行如下命令,在工作流程叢集中建立Secret儲存ACR EE的密碼,供BuildKit使用。

    $username:$password需要替換為您實際為ACR EE配置的訪問憑證資訊。

    kubectl create secret generic docker-config --from-literal="config.json={\"auths\": {\"$repositoryDomain\": {\"auth\": \"$(echo -n $username:$password|base64)\"}}}"

步驟二:在工作流程叢集中掛載NAS儲存卷

使用NAS儲存卷的目的如下:

  • 在工作流程的各任務之間共用資料,如Clone的代碼倉庫資訊等。

  • 儲存Go mod cache,用於加速CI Pipeline中的go testgo build過程。

工作流程叢集中使用NAS儲存卷的步驟如下:

  1. 擷取NAS檔案系統的掛載點地址。具體操作,請參見管理掛載點

  2. 使用以下內容在工作流程叢集中建立PV/PVC。具體操作,請參見使用NAS儲存卷

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-nas
      labels:
        alicloud-pvname: pv-nas
    spec:
      capacity:
        storage: 100Gi
      accessModes:
        - ReadWriteMany
      csi:
        driver: nasplugin.csi.alibabacloud.com
        volumeHandle: pv-nas   # 必須與PV Name保持一致。
        volumeAttributes:
          server: <your nas filesystem mount point address>
          path: "/"
      mountOptions:
      - nolock,tcp,noresvport
      - vers=3
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: pvc-nas
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Gi
      selector:
        matchLabels:
          alicloud-pvname: pv-nas

步驟三:基於預置模板啟動工作流程

通過控制台提交工作流程

  1. 登入ACK One控制台,在左側導覽列選擇工作流程叢集

  2. 工作流程叢集頁面,單擊基礎資訊頁簽,然後在下方常用操作地區,單擊工作流程控制台(Argo)

  3. 在Argo工作台左側導覽列單擊Cluster Workflow Templates,然後單擊ci-go-v1預置模板名稱。

    image

  4. 在模板詳情頁左上方單擊+ SUBMIT,然後在彈出的面板中填寫相關參數,並在面板下方單擊+ SUBMIT

    參數填寫請參考模板參數說明將參數值設定為您實際使用的參數值。

    image

    操作完成後,您可在Workflows詳情頁查看工作流程運行情況:

    image

通過Argo CLI提交工作流程

  1. 使用以下內容建立workflow.yaml檔案,按照模板參數說明將參數值修改為您實際使用的參數值。

    apiVersion: argoproj.io/v1alpha1
    kind: Workflow
    metadata:
      generateName: ci-go-v1-
      labels:
        workflows.argoproj.io/workflow-template: ackone-ci
    spec:
      arguments:
        parameters:
        - name: repo_url
          value: https://github.com/ivan-cai/echo-server.git
        - name: repo_name
          value: echo-server
        - name: target_branch
          value: main
        - name: container_image
          value: "test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server"
        - name: container_tag
          value: "v1.0.0"
        - name: dockerfile
          value: ./Dockerfile
        - name: enable_suffix_commitid
          value: "true"
        - name: enable_test
          value: "true"
      workflowTemplateRef:
        name: ci-go-v1
        clusterScope: true
  2. 執行以下命令提交工作流程。

    argo submit workflow.yaml

相關文檔

本文以公用Git倉庫為例為您介紹構建CI Pipeline的操作,如果您在工作流程的CI Pipeline中使用的是私人Git倉庫,則需要在CI流程中先成功Clone該私人倉庫。具體的Clone操作,請參見在CI Pipeline中Clone私人Git倉庫