Todos os produtos
Search
Central de documentação

Container Service for Kubernetes:Build a CI pipeline for a Golang project using a workflow cluster

Última atualização: Jun 27, 2026

Os clusters de fluxo de trabalho do ACK One executam Argo Workflows gerenciados com elasticidade integrada e Auto Scaling. Este tópico mostra como configurar um pipeline de Integração Contínua (CI) que clona um repositório Go, executa testes, cria uma imagem de contêiner e a envia para um registro — com duas camadas de cache persistente para manter cada execução rápida.

image

Como funciona

O pipeline utiliza um ClusterWorkflowTemplate predefinido chamado ci-go-v1. Cada execução processa três etapas como um grafo acíclico dirigido (DAG):

  1. Clone e checkout do Git: clona o repositório, faz o checkout da branch de destino e grava o ID curto do commit em um arquivo compartilhado.

  2. Teste Go: executa go test -v ./... no código-fonte clonado. O cache de módulos Go fica armazenado no diretório /pkg/mod em um sistema de arquivos NAS. Os módulos baixados em uma execução são reutilizados na seguinte, permitindo que go test e go build evitem baixar dependências novamente.

  3. Criação e envio da imagem: usa buildctl-daemonless.sh (BuildKit) para criar a imagem e enviá-la ao Container Registry Enterprise Edition (ACR EE). O BuildKit armazena as camadas da imagem em cache no registro sob a tag :buildcache. Camadas inalteradas não são recriadas nas execuções subsequentes.

Ambos os caches persistem entre as execuções do pipeline: o cache de módulos Go no NAS é compartilhado entre todas as tarefas de uma única execução, enquanto o cache de camadas do BuildKit reside no registro entre diferentes execuções.

Pré-requisitos

Antes de começar, verifique se você possui:

Etapa 1: Criar credenciais de registro no cluster de fluxo de trabalho

O BuildKit busca e envia imagens usando um Secret chamado docker-config. Crie-o no namespace onde você planeja enviar os pipelines.

Importante

O Secret e o volume NAS (criado na Etapa 2) devem pertencer ao mesmo namespace do pipeline que você enviar.

  1. Configure as credenciais de acesso para sua instância ACR EE. Consulte Configurar credenciais de acesso.

  2. Execute o comando a seguir para criar o Secret. Substitua $repositoryDomain, $username e $password pelo domínio e pelas credenciais do seu ACR EE.

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

Etapa 2: Montar um volume NAS no cluster de fluxo de trabalho

O volume NAS atende a duas finalidades:

  • Compartilhamento de dados entre tarefas: a tarefa git-checkout-pr grava aqui o repositório clonado e o arquivo de ID do commit, que serão lidos pelas tarefas subsequentes.

  • Persistência do cache de módulos Go: o cache em /pkg/mod é reutilizado entre as execuções do pipeline. A primeira execução baixa os módulos; as seguintes ignoram essa etapa.

O NAS utiliza o modo de acesso ReadWriteMany para que todas as tarefas do pipeline possam ler e gravar no volume simultaneamente.

  1. Obtenha o endereço do ponto de montagem do seu sistema de arquivos NAS. Consulte Gerenciar pontos de montagem.

  2. Aplique o manifesto a seguir para criar um volume persistente (PV) e uma solicitação de volume persistente (PVC) no cluster de fluxo de trabalho. Substitua <your nas filesystem mount point address> pelo endereço real do seu ponto de montagem. Para mais informações, consulte Usar volumes NAS.

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-nas
      labels:
        alicloud-pvname: pv-nas
    spec:
      capacity:
        storage: 100Gi
      accessModes:
        - ReadWriteMany          # Required: all pipeline tasks read and write this volume concurrently
      csi:
        driver: nasplugin.csi.alibabacloud.com
        volumeHandle: pv-nas
        volumeAttributes:
          server: <your nas filesystem mount point address>
          path: "/"
      mountOptions:
      - nolock,tcp,noresvport
      - vers=3
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: pvc-nas             # The predefined template references this name — do not change it
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Gi
      selector:
        matchLabels:
          alicloud-pvname: pv-nas

Etapa 3: Enviar um pipeline

O modelo predefinido ci-go-v1 está disponível em todos os clusters de fluxo de trabalho. Utilize o workbench do Argo ou a CLI Argo para enviar uma execução do pipeline.

Os exemplos abaixo utilizam um repositório Git público. Para um repositório privado, adicione uma etapa que faça o clone usando credenciais armazenadas antes da etapa de clone e checkout do git.

Enviar pelo workbench do Argo

  1. Faça login no console do ACK One. No painel de navegação à esquerda, escolha o cluster de fluxo de trabalho que você criou.

  2. Na página Cluster Information, clique em aba Basic Information. Na seção Common Operations, clique em Workflow Console (Argo).

  3. No workbench do Argo, clique em Cluster Workflow Templates no painel de navegação à esquerda e, em seguida, clique em modelo chamado ci-go-v1.

    image

  4. Clique em + SUBMIT no canto superior direito. Configure os parâmetros no painel exibido (consulte Parâmetros do modelo para descrições) e clique em + SUBMIT.

    image

  5. Visualize o status do pipeline na página de detalhes de Workflows.

    image

Enviar usando a CLI Argo

  1. Crie um arquivo chamado workflow.yaml com o conteúdo a seguir. Atualize os valores dos parâmetros para corresponder ao seu ambiente.

    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
  2. Envie o pipeline:

    argo submit workflow.yaml

Parâmetros do modelo

O modelo ci-go-v1 aceita os seguintes parâmetros.

Parâmetro

Descrição

Padrão

Exemplo

repo_url

URL do repositório Git

—

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

repo_name

Nome do repositório (usado como nome do diretório local)

—

echo-server

target_branch

Branch para checkout

main

main

container_image

Imagem a ser criada e enviada. Formato: <domínio ACR EE>/<namespace>/<repositório>

—

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

container_tag

Tag base da imagem

v1.0.0

v1.0.0

dockerfile

Caminho relativo para o Dockerfile a partir da raiz do repositório

./Dockerfile

./Dockerfile

enable_suffix_commitid

Anexa o ID curto do commit à tag da imagem, gerando <container_tag>-<commit_id>. Defina como false para usar apenas a tag base.

true

true

enable_test

Executa a etapa de teste Go. Defina como false para pular os testes e ir direto para a criação.

true

true

Referência do modelo predefinido

O modelo completo é fornecido abaixo para personalização. As seções principais estão anotadas.

apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
  name: ci-go-v1
spec:
  entrypoint: main
  volumes:
  - name: run-test
    emptyDir: {}          # Temporary volume scoped to the run-test task
  - name: workdir
    persistentVolumeClaim:
      claimName: pvc-nas  # NAS volume: shared across all tasks, persists Go module cache
  - name: docker-config
    secret:
      secretName: docker-config  # Registry credentials created in Step 1
  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"  # Skipped when enable_test=false
            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  # Point Go to the NAS-backed module cache

                    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  # e.g. v1.0.0-abc1234
                    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 \  # Save layer cache to registry
                    --import-cache type=registry,ref={{workflow.parameters.container_image}}:buildcache            # Reuse layer cache from previous runs

                    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

Próximos passos

  • Personalize o ci-go-v1: copie o modelo e modifique as etapas (por exemplo, adicione uma etapa de lint ou altere a versão do Go) para criar seu próprio ClusterWorkflowTemplate.

  • Acione pipelines automaticamente: integre o argo submit com o webhook da sua plataforma Git para executar o pipeline a cada push ou pull request.

Referências