Build a CI pipeline with Argo Workflows

更新时间:
复制 MD 格式

Argo Workflows provides easy-to-use interfaces and tools that let you define workflows in YAML to quickly configure a CI pipeline. You can run tasks in parallel within your cluster, dynamically scale computing resources as needed, and improve the efficiency of your CI pipeline.

How it works

When building a CI pipeline with Argo Workflows, you primarily use BuildKit to build and push container images and BuildKit Cache to accelerate the build process. By storing the Go mod cache on File Storage NAS, you can speed up the go test and go build processes, significantly accelerating the entire CI pipeline.

image

Predefined workflow template

You can use the predefined template directly or customize it to create your own. This example creates a CI workflow template (ClusterWorkflowTemplate) named ci-go-v1. This template uses BuildKit Cache and File Storage NAS to store the Go mod cache, accelerating the CI pipeline.

View the stages of the CI workflow template

  1. Git clone and checkout

    • Clones a Git repository and checks out the target branch.

    • Gets the commit ID to append as a suffix to the image tag during the image build process.

  2. Run go test

    • By default, this stage runs all test cases in the Git repository (for Go projects).

    • You can use the workflow parameter enable_test to control whether to run this stage.

    • This stage stores the Go mod cache in the /pkg/mod directory on File Storage NAS to accelerate the go test and subsequent go build processes.

  3. Build & push image

    • Uses BuildKit to build and push the container image. It uses a registry-type cache from BuildKit Cache to accelerate the image build.

    • The image tag defaults to the {container_tag}-{commit_id} format. You can control whether to append the commit ID when submitting the workflow.

    • This stage also updates the latest tag to point to the newly pushed image.

View the CI workflow template content

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: mirrors-ssl.aliyuncs.com/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: mirrors-ssl.aliyuncs.com/golang:alpine3.21
                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: mirrors-ssl.aliyuncs.com/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

You can run the kubectl apply -f cluster-workflow-template.yaml command to deploy the template to your cluster.

View the template parameter descriptions

Parameter

Description

Example

entrypoint

Defines the entrypoint template.

main

repo_url

The URL of the Git repository.

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

repo_name

The name of the repository.

echo-server

target_branch

The target branch of the repository. Default value: main.

main

container_image

The container image to build. Use the following format: <ACR EE Domain>/<ACR EE namespace>/<repository name>.

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

container_tag

The tag for the new image. Default value: v1.0.0.

v1.0.0

dockerfile

The directory and name of the Dockerfile.

A relative path in the project root directory. Default value: ./Dockerfile.

./Dockerfile

enable_suffix_commitid

Specifies whether to append the commit ID to the image tag.

  • true (default): Appends the commit ID.

  • false: Does not append.

true

enable_test

Whether to enable the Run Go Test step.

  • true (Default): Enabled.

  • false: Disabled.

true

Procedure

This topic demonstrates how to build a CI pipeline with a public Git repository. If your CI pipeline uses a private Git repository, you must first clone the repository. For more information, see Clone a private Git repository in a CI pipeline.

Important

The Secret for container image access credentials and the mounted File Storage NAS volume must be in the same namespace as the workflow.

Step 1: Create access credentials for ACR EE

BuildKit primarily uses ACR EE access credentials to push images.

  1. Configure access credentials for Container Registry Enterprise Edition (ACR EE). For more information, see Configure access credentials.

  2. Run the following command to create a Secret in the cluster. This Secret stores the ACR EE password used by BuildKit.

    Note

    $repositoryDomain: Replace this with the address of your Container Registry repository.

    $username: Replace this with the username for your Container Registry repository.

    $password: Replace this with the password for your Container Registry repository.

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

Step 2: Mount a File Storage NAS volume

After you mount a File Storage NAS volume, you can share data, such as cloned repository information, between different tasks in a workflow. The volume also stores the Go mod cache, which accelerates the go test and go build processes in the CI pipeline.

For more information about how to mount a File Storage NAS volume, see Use volumes.

Step 3: Start a workflow from the template

Console

  1. Log on to the Argo console. In the left-side navigation pane, click Cluster Workflow Templates, and then click the predefined template named ci-go-v1.

  2. On the template details page, click + SUBMIT in the upper-left corner. In the panel that opens, enter the required parameters, and then click + SUBMIT at the bottom of the panel.

    Refer to the template parameter descriptions to set the parameter values based on your actual configuration.

    After the workflow starts, go to the Workflows details page to check its status:

    A green check mark on each node in the workflow DAG (git-checkout-prrun-testbuild-push-image) indicates that the stage is complete.

Argo CLI

  1. Create a workflow.yaml file with the following content. Modify the parameter values based on your requirements. For more information, see the template parameter descriptions.

    apiVersion: argoproj.io/v1alpha1
    kind: Workflow
    metadata:
      generateName: ci-go-v1-
      labels:
        workflows.argoproj.io/workflow-template: ackone-ci
      namespace: argo  
    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. Run the following command to submit the workflow.

    argo submit workflow.yaml

Contact us

If you have any product suggestions or questions, you can contact us by joining the DingTalk group (ID: 35688562).