すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:ワークフロークラスターを使用した Golang プロジェクトの CI パイプラインの構築

最終更新日:Mar 27, 2026

ACK One のワークフロークラスターは、ホスト型の Argo Workflows を実行し、組み込みの伸縮性と自動スケーリング機能を備えています。このトピックでは、Go リポジトリをクローンし、テストを実行し、コンテナイメージをビルドしてレジストリにプッシュする継続的インテグレーション (CI) パイプラインを設定する方法について説明します。各実行を高速に保つために、2 層の永続的なキャッシュを使用します。

image

仕組み

このパイプラインは、ci-go-v1 という名前の事前定義された ClusterWorkflowTemplate を使用します。各実行は、有向非循環グラフ (DAG) として 3 つのステップを実行します。

  1. Git のクローンとチェックアウト — リポジトリをクローンし、ターゲットブランチをチェックアウトし、短いコミット ID を共有ファイルに書き込みます。

  2. Go テスト — クローンされたソースに対して go test -v ./... を実行します。Go モジュールキャッシュは、NAS ファイルシステムの /pkg/mod ディレクトリに保存されます。ある実行でダウンロードされたモジュールは次の実行で再利用されるため、go testgo build は依存関係の再ダウンロードをスキップします。

  3. イメージのビルドとプッシュbuildctl-daemonless.sh (BuildKit) を使用してイメージをビルドし、Container Registry Enterprise Edition (ACR EE) にプッシュします。BuildKit は、:buildcache タグでイメージレイヤーをレジストリにキャッシュします。変更されていないレイヤーは、後続の実行では再ビルドされません。

両方のキャッシュはパイプラインの実行をまたいで永続化します。NAS 上の Go モジュールキャッシュは単一の実行内のすべてのタスクで共有され、BuildKit レイヤーキャッシュは実行間でレジストリ内に存在します。

前提条件

開始する前に、以下が準備できていることを確認してください。

ステップ 1: ワークフロークラスターでのレジストリ認証情報の作成

BuildKit は、docker-config という名前のシークレットを使用してイメージをプルおよびプッシュします。パイプラインをサブミットする予定の名前空間に作成します。

重要

シークレットと NAS ボリューム (ステップ 2 で作成) は、サブミットするパイプラインと同じ名前空間に属している必要があります。

  1. ご利用の ACR EE インスタンスのアクセス認証情報を設定します。「アクセス認証情報の設定」をご参照ください。

  2. 次のコマンドを実行してシークレットを作成します。$repositoryDomain$username$password をご利用の ACR EE ドメインと認証情報に置き換えます。

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

ステップ 2: ワークフロークラスターへの NAS ボリュームのマウント

NAS ボリュームは 2 つの目的を果たします。

  • タスク間のデータ共有: クローンされたリポジトリとコミット ID ファイルは、git-checkout-pr タスクによってここに書き込まれ、下流のタスクによって読み取られます。

  • Go モジュールキャッシュの永続化: /pkg/mod 内のキャッシュは、パイプラインの実行をまたいで再利用されます。最初の実行でモジュールがダウンロードされ、後続の実行ではそのステップがスキップされます。

NAS は ReadWriteMany アクセスモードを使用するため、すべてのパイプラインタスクがボリュームを同時に読み書きできます。

  1. ご利用の NAS ファイルシステムのマウントターゲットアドレスを取得します。「マウントターゲットの管理」をご参照ください。

  2. 次のマニフェストを適用して、ワークフロークラスターに永続ボリューム (PV) と永続ボリューム要求 (PVC) を作成します。<your nas filesystem mount point address> を実際ののマウントターゲットアドレスに置き換えます。詳細については、「NAS ボリュームの使用」をご参照ください。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-nas
      labels:
        alicloud-pvname: pv-nas
    spec:
      capacity:
        storage: 100Gi
      accessModes:
        - ReadWriteMany          # 必須: すべてのパイプラインタスクがこのボリュームを同時に読み書きします
      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             # 事前定義されたテンプレートはこの名前を参照します — 変更しないでください
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Gi
      selector:
        matchLabels:
          alicloud-pvname: pv-nas

ステップ 3: パイプラインのサブミット

事前定義された ci-go-v1 テンプレートは、すべてのワークフロークラスターで利用可能です。Argo ワークベンチまたは Argo CLI を使用してパイプラインの実行をサブミットします。

以下の例では、パブリック Git リポジトリを使用しています。プライベートリポジトリの場合は、Git のクローンとチェックアウトのステップの前に、保存された認証情報を使用してクローンするステップを追加してください。

Argo ワークベンチからのサブミット

  1. ACK One コンソールにログインします。左側のナビゲーションウィンドウで、作成したワークフロークラスターを選択します。

  2. [クラスター情報] ページで、[基本情報] タブをクリックします。[一般的な操作] セクションで、[ワークフローコンソール (Argo)] をクリックします。

  3. Argo ワークベンチで、左側のナビゲーションウィンドウの [Cluster Workflow Templates] をクリックし、[ci-go-v1] という名前のテンプレートをクリックします。

    image

  4. 右上隅の [+ SUBMIT] をクリックします。表示されるパネルでパラメーターを設定し (説明については「テンプレートパラメーター」をご参照ください)、[+ SUBMIT] をクリックします。

    image

  5. [Workflows] 詳細ページでパイプラインのステータスを表示できます。

    image

Argo CLI を使用したサブミット

  1. workflow.yaml という名前のファイルを次の内容で作成します。パラメーター値をご利用の環境に合わせて更新します。

    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. パイプラインをサブミットします。

    argo submit workflow.yaml

テンプレートパラメーター

ci-go-v1 テンプレートは、次のパラメーターを受け入れます。

パラメーター 説明 デフォルト
repo_url Git リポジトリの URL https://github.com/ivan-cai/echo-server.git
repo_name リポジトリ名 (ローカルディレクトリ名として使用) echo-server
target_branch チェックアウトするブランチ main main
container_image ビルドしてプッシュするイメージ。フォーマット: <ACR EE ドメイン>/<名前空間>/<リポジトリ> test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server
container_tag ベースイメージタグ v1.0.0 v1.0.0
dockerfile リポジトリルートからの Dockerfile への相対パス ./Dockerfile ./Dockerfile
enable_suffix_commitid 短いコミット ID をイメージタグに追加し、<container_tag>-<commit_id> を生成します。ベースタグのみを使用するには、false に設定します。 true true
enable_test Go テストステップを実行します。テストをスキップしてビルドに直接進むには、false に設定します。 true true

事前定義テンプレートのリファレンス

カスタマイズ用に完全なテンプレートを以下に示します。主要なセクションには注釈が付いています。

apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
  name: ci-go-v1
spec:
  entrypoint: main
  volumes:
  - name: run-test
    emptyDir: {}          # run-test タスクにスコープされた一時ボリューム
  - name: workdir
    persistentVolumeClaim:
      claimName: pvc-nas  # NAS ボリューム: すべてのタスクで共有され、Go モジュールキャッシュを永続化します
  - name: docker-config
    secret:
      secretName: docker-config  # ステップ 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"  # 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  # Go を NAS ベースのモジュールキャッシュに向けます

                    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  # 例: 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 \  # レイヤーキャッシュをレジストリに保存します
                    --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-go-v1 のカスタマイズ — テンプレートをコピーしてステップを変更し (たとえば、lint ステップを追加したり、Go のバージョンを変更したり)、独自の ClusterWorkflowTemplate を作成します。

  • パイプラインの自動トリガー — argo submit をご利用の Git プラットフォームの Webhook と統合して、すべてのプッシュまたはプルリクエストでパイプラインを実行します。

参考資料