首页 > 其他分享 >云原生时代:从 Jenkins 到 Argo Workflows,构建高效 CI Pipeline

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

时间:2024-06-05 18:45:13浏览次数:22  
标签:CI container name parameters workflow Argo Workflows

作者:蔡靖

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 个步骤:

  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

参数说明:

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

标签:CI,container,name,parameters,workflow,Argo,Workflows
From: https://www.cnblogs.com/alisystemsoftware/p/18233577

相关文章

  • P7860 [COCI2015-2016#2] ARTUR
    原题链接教训1.计算几何,能用乘法就不用除法2.计算几何,开longlong3.计算几何,注意直线的特殊性code#include<bits/stdc++.h>#definelllonglongusingnamespacestd;structnode{llx1,y1,x2,y2;}sk[5005];intcheck(nodea,nodeb){if(a.x2<b.x1||a.x1>b.......
  • 【计算机网络】P2 计算机网络体系结构基本概念,涉及分层的基本术语、SDU、PCI 与 PDU
    目录概述分层的基本元组基本术语SDU、PCI以及PDU层次结构含义概述在两个系统中实体间的通信是一个很复杂的过程。而为了降低协议设计以及调试过程的复杂性,同时便于对网络进行研究、实现和维护,促进标准化工作,通常对计算机网络的体系结构以分层的方式进行建模。我们......
  • C# Parallel foreach Parallel Source array was not long enough. Check srcIndex an
    //Indexwasoutsidetheboundsofthearray.//Sourcearraywasnotlongenough.ChecksrcIndexandlength,andthearray'slowerbounds//usingSystem;usingSystem.Collections.Concurrent;usingSystem.Collections.Generic;usingSystem.Linq;usingSy......
  • QEMU EDU设备模拟PCI设备驱动编写
    环境安装buildroot编译buildroot下载,编译:下载地址:Indexof/downloads(buildroot.org)下载版本:https://www.buildroot.org/downloads/buildroot-2022.02.2.tar.gz下载完成后,解压:$tar-vxfbuildroot-2022.02.2.tar.gz$cdbuildroot-2022.02.2/$makeqemu_aarc......
  • Luogu P2036 [COCI2008-2009 #2] PERKET
    LuoguP2036[COCI2008-2009#2]PERKET#include<bits/stdc++.h>usingnamespacestd;intn,ans=1e9+5;//ans初始化值大于所有可用食材全部使用产生的总酸度和总苦度ints[15],b[15];voiddfs(inttot,intk,intl){//k为当前酸度,l为当前甜度if(to......
  • 【TPAMI-2024】EfficientTrain++帮你降低网络训练的成本
    写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除!文章目录前言论文更容易学习的模式:频域易于学习的模式:空间域统一的训练课程EFFICIENTTRAIN++计算约束的顺序搜索高效低频下采样EfficientTrain++的实现技术实验......
  • 【EI会议征稿通知】第五届智能计算与人机交互国际研讨会(ICHCI 2024)
    第五届智能计算与人机交互国际研讨会(ICHCI2024)20245th InternationalConferenceonIntelligentComputingandHuman-ComputerInteraction第五届智能计算与人机交互国际研讨会(ICHCI2024)由南昌大学主办,将于2024年9月27-29日在中国南昌隆重召开。ICHCI2024的主题是“AI......
  • Dated Data: Tracing Knowledge Cutoffs in Large Language Models
    本文是LLM系列文章,针对《DatedData:TracingKnowledgeCutoffsinLargeLanguageModels》的翻译。日期数据:追踪大型语言模型中的知识截断摘要1引言2相关工作3方法4结果5为什么模型与截止日期不一致?6结论摘要已发布的大型语言模型(LLM)通常与声称的......
  • Efficient Pruning of Large Language Model with Adaptive Estimation Fusion
    本文是LLM系列文章,针对《EfficientPruningofLargeLanguageModelwithAdaptiveEstimationFusion》的翻译。基于自适应估计融合的大型语言模型的高效修剪摘要1引言2相关工作3方法4实验5结论摘要大型语言模型(LLM)已经成为许多生成下游任务的关键,这......
  • CI+GPT双引擎驱动, 开启AI代码评审新纪元
    一.现状问题代码评审CodeReview是提高代码质量、促进团队合作、知识间共享的关键环节,对于系统代码质量和稳定性都至关重要。 时间消耗大:代码评审是一个耗时的过程,特别对于大型项目和复杂的代码更是如此。无档期:评审者无时间会造成研发卡点。一致性缺乏:不同的审......