ACK One工作流集群基于開源Argo Workflows項目構建,全托管Argo Workflows,具有極致彈性、自動擴展、無運維成本等優勢,可以幫助您快速實現更簡單、低成本、高效率的CI流水線。本文為您介紹如何基于工作流集群構建Golang項目的CI Pipeline。
方案介紹
ACK One工作流集群構建CI Pipeline,主要使用BuildKit實現容器鏡像的構建和推送,并使用BuildKit Cache加速鏡像的構建。使用NAS存儲Go mod cache,可加速go test
和go build
運行過程,最終大幅加速CI Pipeline的流程。
預置工作流模板說明
工作流集群中默認已經預置了名為ci-go-v1
的CI工作流模板(ClusterWorkflowTemplate),其使用BuildKit Cache和NAS存儲Go mode cache,可大幅加速CI Pipeline的流程。
您可以直接使用預置模板,也可以基于預置模板自定義自己的CI工作流模板。
預置的CI工作流模板中包含以下流程:
Git Clone & Checkout
用于Clone Git倉庫,將Git倉庫Checkout到目標分支。
獲取Commit ID,在構建鏡像時根據Commit ID追加Tag后綴。
Run Go Test
默認運行Git Repo(Go項目)中的所有測試用例。
可通過工作流參數
enable_test
控制是否運行該步驟。其中Go mod cache存儲在NAS的
/pkg/mod
目錄,用于go test
和后續的go build
的加速。
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目錄和文件名。 項目根目錄下的相對路徑,默認為 |
|
enable_suffix_commitid | 是否在鏡像Tag后追加Commit ID。
默認值為true。 | true |
enable_test | 是否開啟運行Go Test步驟。
默認值為true。 | true |
前提條件
從ACK One控制臺獲取工作流集群的KubeConfig,并通過kubectl連接至工作流集群。具體操作,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
操作步驟
本文以公共Git倉庫為例為您介紹構建CI Pipeline的操作,如果您在工作流的CI Pipeline中使用的是私有Git倉庫,則需要在CI流程中先成功Clone該私有倉庫。具體的Clone操作,請參見在CI Pipeline中Clone私有Git倉庫。
保存容器鏡像訪問憑證的Secret和掛載的NAS存儲卷都需要與最終提交的工作流在同一個命名空間下。
步驟一:在工作流集群中創建ACR EE訪問憑證
ACR EE訪問憑證主要用于BuildKit推送鏡像。
為ACR EE配置訪問憑證。具體操作,請參見配置訪問憑證。
執行如下命令,在工作流集群中創建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 test
和go build
過程。
在工作流集群中使用NAS存儲卷的步驟如下:
獲取NAS文件系統的掛載點地址。具體操作,請參見管理掛載點。
使用以下內容在工作流集群中創建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
步驟三:基于預置模板啟動工作流
通過控制臺提交工作流
登錄ACK One控制臺,在左側導航欄選擇 。
在集群信息頁面,單擊基礎信息頁簽,然后在下方常用操作區域,單擊工作流控制臺(Argo)。
在Argo工作臺左側導航欄單擊Cluster Workflow Templates,然后單擊ci-go-v1預置模板名稱。
在模板詳情頁左上角單擊+ SUBMIT,然后在彈出的面板中填寫相關參數,并在面板下方單擊+ SUBMIT。
參數填寫請參考模板參數說明將參數值設置為您實際使用的參數值。
操作完成后,您可在Workflows詳情頁查看工作流運行情況:
通過Argo CLI提交工作流
使用以下內容創建
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
執行以下命令提交工作流。
argo submit workflow.yaml
相關文檔
本文以公共Git倉庫為例為您介紹構建CI Pipeline的操作,如果您在工作流的CI Pipeline中使用的是私有Git倉庫,則需要在CI流程中先成功Clone該私有倉庫。具體的Clone操作,請參見在CI Pipeline中Clone私有Git倉庫。