作者:蔡靖
Argo Workflows
Argo Workflows [ 1] 是用於在 Kubernetes 上編排 Job 的開源的雲原生工作流引擎。可以輕鬆自動化和管理 Kubernetes 上的複雜工作流程。適用於各種場景,包括定時任務、機器學習、ETL 和資料分析、模型訓練、資料流 pipline、CI/CD 等。
Kubernetes Jobs 只提供基礎的任務執行,但是無法定義步驟依賴關係和順序、缺乏工作流模版、沒有視覺化介面,也不支援工作流級別的錯誤處理等,對於批處理、資料處理、科學計算、持續整合等業務場景,Kubernetes Job 無法勝任。
Argo Workflows 作為 CNCF 的畢業專案,已被使用在多種場景,持續整合(CI)是其一個重要應用領域。
CI 與 Jenkins
持續整合和持續部署(CI/CD)是軟體開發生命週期中的重要部分,它允許團隊以敏捷流程開發應用並提高所構建應用程式的質量。持續整合(CI)是面向開發者的自動化流程,經測試、構建等步驟,有助於更頻繁、可靠地將程式碼變更提交到主分支。
Jenkins 作為 CI/CD 領域最常見的解決方案,其具有開源免費、外掛豐富、社群成熟諸多優點,但它仍然存在一些問題,尤其是雲原生大背景的當下:
- 非 kubernetes 原生;
- 隨著 pipeline 和外掛的增加,Jenkins 會面臨效能瓶頸;
- 自動擴充套件能力不足,併發不足,執行時間長,空閒計算浪費成本;
- 維護成本方面,雖然 Jenkins 的外掛生態系統豐富,但這也可能導致外掛版本不相容、更新不及時或安全漏洞等問題,管理外掛更新和許可權是一個持續的挑戰;
- 專案隔離/許可權分配方案的缺陷等。
Argo Workflows 與 Jenkins 的對比
相比於 Jenkins,Argo Workflows 有諸多優勢。Argo Workflows 構建在 Kubernetes 之上,使其具有 Kubernetes 經過時間考驗的優勢,其 Autoscaling 和併發等能力,使得 Argo Workflows 可以處理大規模的 pipelins,具有更快的執行速度,和更低的費用/使用成本,讓開發者更加聚焦業務功能和為客戶提供、傳播價值;並且與 Argo 生態的 Argo CD、Argo Rollout、Argo Event 的無縫整合,為 CI 等場景提供更強大的能力。您可以基於 Argo Workflows 來構建更加雲原生、大規模、高效率、低成本的 CI Pipeline。
對比如下:
基於 ACK One Serverless Argo 工作流的 CI Pipeline
ACK One Serverless Argo 工作流
ACK One Serverless Argo 工作流 [ 2] 作為一款完全遵循社群規範的全託管式 Argo Workflows 服務,致力於應對大規模計算密集型作業,透過整合阿里雲 ECI 實現自動擴充套件和極致彈性、按需擴容以最小化成本,透過使用 spot ECI(搶佔式 ECI 例項 [ 3] )可以降低 80% 成本。
CI Pipeline 概述
基於 ACK One Serverless Argo 工作流叢集構建 CI Pipeline,主要使用 BuildKit [ 4] 實現容器映象的構建和推送,並使用 BuildKit Cache [ 5] 加速映象的構建,使用 NAS 來儲存 Go mod cache 加速 go test 和 go build,最終大幅加速 CI Pipeline 流程。
我們將實現的 CI Pipeline 的 ClusterWorkflowTemplate 預置在工作流叢集中(名為 ci-go-v1),其中主要包含 3 個步驟:
-
Git Clone & Checkout:Clone Git 倉庫,Checkout 到目標分支;並獲取 commit id。
-
Run Go Test:透過引數控制是否執行,使用 NAS 儲存 Go mod cache 進行加速
-
Build & Push Image:
a. 使用 BuildKit 構建和推送容器映象,並使用 BuildKit Cache 中 registry 型別 cache 來加速映象構建;
b. 映象 tag 預設使用 {container_tag}-{commit_id} 格式,可在提交工作流時透過引數控制是否追加 commit id;
c. 推送映象的同時,也會推送覆蓋其 latest 映象。
您可執行以下步驟完成 CI Pipeline 的執行,詳細步驟請參見最佳實踐 [ 6] :
- 在工作流叢集中準備好 ACR EE 的憑據和 NAS 儲存卷
- 基於預置模板啟動工作流(workflow)執行 CI Pipeline
預置 CI Pipeline 模板
工作流叢集中預設已經預置了名為 ci-go-v1 的工作流模板(ClusterWorkflowTemplate),yaml 如下所示,詳細引數說明請參見最佳實踐 [ 6] :
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 {{workflow.parameters.target_branch}}
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
在控制檯執行 CI Pipeline
- 登入 ACK One 工作流叢集控制檯 [ 7]
- 在基礎資訊,開啟工作流控制檯(Argo) ,並訪問進入頁面
- 左側選單欄 Cluster Workflow Templates,單擊 ci-go-v1 預置模板進入詳情頁
- 單擊+ SUBMIT,在右側填入您的引數,單擊下方+ SUBMIT
引數說明:
執行完以後,可在 Argo UI 的 workflow 詳情頁檢視執行情況,如下所示:
總結
ACK One Serverless Argo 工作流作為全託管的 Argo 工作流服務,可以幫助您實現更大規模、具有更快的執行速度、及更低成本的 CI Pipeline,與 ACK One GitOps [ 8] (Argo CD)、Argo Event 等事件驅動架構可以構建完整的自動化 CI/CD Pipeline。
歡迎加入 ACK One 客戶交流釘釘與我們一同交流。(釘釘群號:35688562)
相關連結:
[1] Argo Workflows
https://argoproj.github.io/argo-workflows/
[2] ACK One Serverless Argo 工作流**
https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/overview-12
[3] 搶佔式 ECI 例項
https://help.aliyun.com/zh/eci/use-cases/run-jobs-on-a-preemptible-instance?spm=a2c4g.11186623.0.i7
[4] BuildKit
https://github.com/moby/buildkit
[5] BuildKit Cache
https://github.com/moby/buildkit?tab=readme-ov-file#cache
[6] 最佳實踐
https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/use-cases/building-a-ci-pipeline-of-golang-project-based-on-workflow-cluster
[7] ACK One 工作流叢集控制檯
https://account.aliyun.com/login/login.htm?oauth_callback=https%3A%2F%2Fcs.console.aliyun.com%2Fone%3Fspm%3Da2c4g.11186623.0.0.555018e1SiD2lC#/argowf/cluster/detail
[8] ACK One GitOps
https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/gitops-overview