云原生时代:从Jenkins到Argo Workflows,构建高效CI Pipeline

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
文件存储 NAS,50GB 3个月
简介: 基于Argo Workflows可以构建大规模、高效率、低成本的CI流水线

阅读原文】戳:云原生时代:从Jenkins到Argo Workflows,构建高效CI Pipeline

 

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。

 

对比如下:

 

  Argo Workflows Jenkins
kubernetes原生

kubernetes原生,因此也具有k8s的部分管理容器的优势,如:

容器故障后自动恢复

弹性伸缩

支持RBAC,配合Argo的集成SSO能力,很容易实现企业的多租隔离场景

非kubernetes原生
Autoscaling、并发、性能

Argo被用来处理大规模pipeline,自动扩展

并发让运行更快,效率更高

Jenkins更适合规模较小的场景,在处理大量pipelines时,性能下降。自动扩展能力差。

并发不足,运行时间长

成本

自动伸缩,最小化成本

原生支持Spot ECI运行任务,降低成本

Jenkins空闲计算浪费成本
社区与生态 Argo社区不断壮大,与其生态的Argo CD、Argo Rollout、Argo Event的无缝集成,为CI等场景提供更强大的能力 Jenkins社区成熟、资源丰富,大量插件降低使用门槛,但随着时间推移,插件更新和权限管理极大增加运维成本,使开发者更多精力在维护插件,而非聚焦业务功能和为客户提供价值

 

 

基于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的Cluster Workflow Template预置在工作流集群中(名为ci-go-v1),其中主要包含3个步骤:

 

1.Git Clone&Checkout:Clone Git仓库,Checkout到目标分支;并获取commit id。

 

2.Run Go Test:通过参数控制是否运行,使用NAS存储Go mod cache进行加速。

 

3.Build&Push Image:

 

a.使用BuildKit构建和推送容器镜像,并使用BuildKit Cache中 registry类型cache来加速镜像构建;

 

b.镜像tag默认使用 {container_tag}-{commit_id} 格式,可在提交工作流时通过参数控制是否追加commit id;

 

c.推送镜像的同时,也会推送覆盖其latest镜像。

 

您可执行以下步骤完成CI Pipeline的运行,详细步骤请参见最佳实践[6]

 

1.在工作流集群中准备好ACR EE的凭据和NAS存储卷

 

2.基于预置模板启动工作流(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

 

 

1.登录ACK One工作流集群控制台[7]

 

2.在基础信息,开启工作流控制台(Argo),并访问进入页面;

 

3.左侧菜单栏Cluster Workflow Templates,单击ci-go-v1预置模板进入详情页;

 

4.单击+SUBMIT,在右侧填入您的参数,单击下方+SUBMIT

 

 

参数说明:

 

参数 说明 参数值
repo_url 仓库url https://github.com/ivan-cai/echo-server.git
repo_name 仓库名 echo-server
target_branch 目标分支 默认是main
container_image 要build的镜像信息 test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server
container_tag 要build的镜像tag 默认v1.0.0
dockerfile

Dockerfile目录和文件名

(项目根目录下的相对路径)

默认./Dockerfile
enable_suffix_commitid 在container_tag后追加commit id true/false(默认true)
enable_test 开启运行Go Test步骤 true/false(默认true)

 

执行完以后,可在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

 


我们是阿里巴巴云计算和大数据技术幕后的核心技术输出者。

欢迎关注 “阿里云基础设施”同名微信微博知乎

获取关于我们的更多信息~

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
6天前
|
监控 Cloud Native 持续交付
构建未来:云原生技术驱动的云计算平台
【5月更文挑战第52天】 随着数字化转型的不断深化,企业对于敏捷性、可扩展性和成本效益的需求日益增长。本文探讨了如何通过采纳云原生技术来构建和优化云计算平台,以支持不断变化的业务需求。文章首先概述了云原生技术的核心概念及其优势,随后详细分析了在设计云平台时应考虑的关键要素,并通过案例研究展示了云原生实践在实际中的应用效果。最后,文章提出了面向未来的云平台发展趋势和挑战。
|
3天前
|
弹性计算 监控 Cloud Native
构建多模态模型,生成主机观测指标,欢迎来战丨2024天池云原生编程挑战赛
本次比赛旨在如何通过分析 ECS 性能数据和任务信息,综合利用深度学习、序列分析等先进技术,生成特定机器的性能指标。参赛者的解决方案将为云资源管理和优化决策提供重要参考,助力云计算资源的高效稳定运行和智能化调度。
|
13天前
|
运维 Cloud Native 开发者
云原生技术:构建未来软件架构的基石
【6月更文挑战第13天】随着云计算的不断演进,云原生技术已成为推动现代软件开发、部署和运维的关键力量。本文深入探讨了云原生的核心概念、优势以及它在企业中的应用,旨在揭示如何借助云原生技术实现更高效、灵活和可靠的软件解决方案。
95 2
|
13天前
|
运维 Cloud Native 持续交付
云原生技术:构建现代应用的基石
【6月更文挑战第13天】本文深入探讨了云原生技术的核心概念、优势以及在现代应用开发中的关键作用。我们将分析云原生如何通过容器化、微服务架构和持续集成/持续部署(CI/CD)等原则,为开发者提供灵活性、可扩展性及高效的运维模式,从而推动企业数字化转型和创新。
|
13天前
|
Cloud Native 持续交付 云计算
云原生技术:构建现代应用的基石
【6月更文挑战第13天】随着云计算的普及,云原生技术已经成为了构建、部署和运行现代应用程序的事实标准。本文将深入探讨云原生技术的核心概念,以及如何利用这些技术来优化应用的性能、可扩展性和可靠性。
|
15天前
|
运维 Cloud Native 持续交付
云原生技术:构建未来应用的基石
【6月更文挑战第12天】在数字化转型的浪潮中,云原生技术以其灵活性、可扩展性和高可用性成为推动现代应用发展的关键力量。本文将深入探讨云原生的核心概念、优势以及它如何重塑软件开发和运维模式,为企业带来前所未有的效率和创新能力。
19 2
|
15天前
|
Cloud Native 持续交付 开发者
云原生技术:构建现代应用的基石
【6月更文挑战第12天】本文深入探讨了云原生技术如何成为现代应用开发的中坚力量。我们将分析其核心概念,如容器化、微服务架构以及持续集成/持续部署(CI/CD),并讨论这些技术如何促进开发效率、提高应用的可扩展性与可靠性。通过实际案例,揭示云原生技术在数字化转型中的关键作用及其对IT行业的深远影响。
16 2
|
1天前
|
存储 消息中间件 Cloud Native
AutoMQ:基于 Regional ESSD 构建十倍降本的云原生 Kafka
本文介绍了AutoMQ基于Regional ESSD构建的十倍降本云原生,降低成本并提供无限容量,通过将存储层分离,使用ESSD作为WAL,OSS作为主存储,实现了成本降低和性能优化。此外,它利用弹性伸缩和抢占式实例,减少了70%的计算成本,并通过秒级分区迁移实现了高效弹性。而且,AutoMQ与Apache Kafka相比,能实现10倍成本优化和百倍弹性效率提升,且完全兼容Kafka API。
|
12天前
|
人工智能 Cloud Native 调度
未来云:构建智能云原生生态系统
在数字化时代,云计算已经成为企业发展的关键驱动力。本文从构建智能云原生生态系统的角度出发,探讨了云平台和云原生技术的发展趋势,以及未来云计算的可能演进方向。
21 0
|
13天前
|
Cloud Native 持续交付 开发者
云原生技术:构建现代应用的基石
【6月更文挑战第13天】在数字化转型的浪潮中,云原生技术以其独特的优势,为现代应用的开发和部署提供了强大的支持。本文将深入探讨云原生技术的核心概念、优势以及实践方法,帮助读者更好地理解和应用这一前沿技术。

热门文章

最新文章