本チュートリアルでは、ACK One GitOps および Container Registry (ACR) を活用して、開発(Dev)、ステージング(Staging)、本番(Production)の各クラスターにまたがる完全な CI/CD パイプラインを構築する手順を説明します。ソースコードへのコミットを契機として、ACR が自動的にコンテナイメージをビルド・プッシュします。ACK One GitOps はその新規イメージを検出し、更新されたタグをデプロイメントリポジトリへ書き戻し、変更を各クラスターへデプロイします。この際、Dev クラスターでは自動デプロイが行われ、Staging および Production クラスターでは手動承認とカナリアリリースによる段階的適用が実行されます。
仕組み
本パイプラインは、以下の 2 つのシステムを連携させます:
-
CI(Container Registry):ソースコードリポジトリを監視します。ビルドルール(例:
release-*)に一致するタグをプッシュすると、ACR がコンテナイメージをビルドし、イメージリポジトリへプッシュします。 -
CD(ACK One GitOps):ArgoCD Image Updater を実行し、イメージリポジトリを定期的にポーリングします。新規イメージタグを検出すると、そのタグをデプロイメントリポジトリへコミットし、ArgoCD が対象クラスターへ変更を同期します。
なぜ別々のリポジトリを使用するのか? ソースコードリポジトリとデプロイメントリポジトリを分離することで、イメージタグのコミットが CI ビルドを再トリガーすることを防ぎ、無限ビルドループを回避できます。また、何がいつデプロイされたかを明確に追跡できる監査証跡が得られ、アプリケーションコードの作成者とは独立して、本番環境へのプッシュ権限を制御できます。
環境ごとの同期戦略:
| 環境 | 同期モード | 理由 |
|---|---|---|
| Dev | 自動 | 検出されたイメージ変更を即座に適用し、迅速なフィードバックを得られるようにするため |
| Staging | 手動 | 差分を確認したうえで、広範囲への展開前にカナリアリリースを実行するため |
| Production | 手動 | 完全展開前のカナリアリリースを承認 |
制限事項
-
ACK One GitOps を使用して作成されたアプリケーションにのみ適用されます。
-
Kustomize または Helm を使用してオーケストレーションされたアプリケーションにのみ適用されます。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
-
フリート管理が有効です。「フリート管理を有効化する」を参照してください。
-
フェレットインスタンスの kubeconfig ファイルをダウンロード済みであり、ACK One コンソール経由で
kubectlがフェレットインスタンスに接続済みであること。 -
フェレットインスタンスで ACK One GitOps が有効化されていること。詳細については、「GitOps システムへのログイン」をご参照ください。
-
最新版 ArgoCD CLI を ArgoCD リリースページからインストール済みであること。
-
Kruise Rollouts コンポーネントが ステージングおよび本番クラスターにインストール済みであり、kubectl-kruise コンポーネントもインストール済みであること。
サンプルアプリケーション
本チュートリアルでは、echo-server をサンプルアプリケーションとして使用します。以下のリポジトリを自身のアカウントへフォークしてください。ACK One GitOps は、イメージタグの変更をデプロイメントリポジトリへコミットするために、そのリポジトリへの書き込み権限を必要とします。
-
ビジネスコードリポジトリ 1(echo-server):Ealenn/Echo-Server
-
ビジネスコードリポジトリ 2(echo-web-server、複数の Deployment を含む):AliyunContainerService/echo-web-server
-
デプロイメントリポジトリ(gitops-demo):AliyunContainerService/gitops-demo
各環境では個別の values ファイルを使用します。image.repository および image.tag を、環境に応じて values.yaml 内で修正してください。
image:
repository: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/echo-server
pullPolicy: IfNotPresent
# デフォルト値はチャートの appVersion です。
tag: "v1.0"
本サンプルの最新情報については、「echo-server のサンプル」をご参照ください。
ステップ 1:Container Registry を使用した CI パイプラインの作成
Container Registry でイメージリポジトリを作成し、フォークした echo-server プロジェクトにバインドして、構築ルールを追加します。詳細については、「Container Registry Enterprise Edition インスタンスを使用してイメージを構築する」をご参照ください。
release- で始まる新しいタグがプッシュされた際にトリガーされるビルドルールを追加します。これにより、ACR が自動的にコンテナイメージをビルドし、リポジトリへプッシュします。正規表現は、ご使用のブランチ戦略に合わせて調整してください。
Kubernetes Secret を使用せずにイメージをプルできるようにするには、Container Registry Enterprise Edition インスタンスの概要ページから 匿名ユーザーによるパブリックアーティファクトのプルを許可 を有効化するか、aliyun-acr-credential-helper を設定してください。
ソースコードが GitHub 上でホストされており、コードのプル時にタイムアウトが発生する場合は、中国本土外に展開されたサーバーを使用したビルド を有効化してください。
ステップ 2:ACK One GitOps の認証情報の設定
ACK One GitOps は、イメージリポジトリをポーリングし、デプロイメントリポジトリへイメージタグの変更を書き戻すために、認証情報を必要とします。
-
ACK One GitOps へ接続します。詳細については、「GitOps システムへのログイン」をご参照ください。
-
デプロイメントリポジトリを ACK One GitOps へ追加します。詳細については、「ACK One GitOps への Git リポジトリの追加」をご参照ください。
-
GitOps アプリケーションを作成します。詳細については、「GitOps を使用したアプリケーションの管理」をご参照ください。
-
ACK One GitOps がイメージリポジトリに対して認証できるよう、
acrという名前のシークレットをargocd名前空間内に作成します。kubectl -n argocd apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: acr type: Opaque stringData: acr: <your_username>:<your_password> # ご使用のイメージリポジトリの認証情報を入力してください。 EOF
Git リポジトリをユーザー名とパスワード、または秘密鍵証明書(SSH 秘密鍵を含む)で追加した場合
ACK One GitOps がデプロイメントリポジトリへイメージタグの変更をコミットできるよう、書き戻し用の認証情報を設定します。Git リポジトリを追加する際に既に認証情報(ユーザー名/パスワードまたは SSH 秘密鍵)を指定済みの場合、Application に以下のアノテーションを追加してください。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
argocd-image-updater.argoproj.io/write-back-method: git
Git リポジトリをユーザー名とパスワード、または秘密鍵証明書なしで追加した場合
Git リポジトリを追加する際に認証情報を指定しなかった場合、Git の認証情報を含むシークレットを作成し、それをアノテーション内で参照します。
kubectl -n argocd create secret generic git-creds \
--from-literal=username=<your_username> \
--from-literal=password=<your_password>
その後、Application に以下のアノテーションを追加します(git:secret:argocd/git-creds は、git-creds という名前のシークレットを argocd 名前空間内で参照します)。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/git-creds
ステップ 3:自動イメージ更新の設定および複数クラスターへのデプロイ
各 ArgoCD アプリケーションにアノテーションを追加し、自動イメージ更新を有効化します。以下の例では、2 つのイメージ(echoserver および webserver)の更新を設定しています。
metadata:
annotations:
argocd-image-updater.argoproj.io/image-list: echoserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-server,webserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-web-server
argocd-image-updater.argoproj.io/echoserver.helm.image-name: image.echoServer.repository
argocd-image-updater.argoproj.io/echoserver.helm.image-tag: image.echoServer.tag
argocd-image-updater.argoproj.io/echoserver.update-strategy: latest
argocd-image-updater.argoproj.io/webserver.helm.image-name: image.echoWebServer.repository
argocd-image-updater.argoproj.io/webserver.helm.image-tag: image.echoWebServer.tag
argocd-image-updater.argoproj.io/webserver.update-strategy: latest
argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/git-creds
echoserver は、image-list 値内のイメージリポジトリアドレスに対するエイリアスです。複数のイメージアドレスはカンマ(,)で区切ります。実際のイメージリポジトリアドレスに置き換えてください。
上記のアノテーションは、Helm で管理されるアプリケーションに適用されます。Kustomize で管理されるアプリケーションについては、「Helm および Kustomize アプリケーション向けのアノテーション」をご参照ください。
Dev クラスターへのデプロイ
app-helm-dev.yaml を作成します。${url} を Dev クラスターのサーバー URL に置き換え(「ACK クラスターの GitOps による管理」を参照)、repoURL をご自身のデプロイメントリポジトリアドレスに置き換えてください。
syncPolicy は automated に設定されています。ACK One GitOps は、手動介入なしに Dev へ即座にイメージ更新を適用します。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-helm-dev
annotations:
argocd-image-updater.argoproj.io/image-list: echoserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-server,webserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-web-server
argocd-image-updater.argoproj.io/echoserver.helm.image-name: image.echoServer.repository
argocd-image-updater.argoproj.io/echoserver.helm.image-tag: image.echoServer.tag
argocd-image-updater.argoproj.io/echoserver.update-strategy: latest
argocd-image-updater.argoproj.io/webserver.helm.image-name: image.echoWebServer.repository
argocd-image-updater.argoproj.io/webserver.helm.image-tag: image.echoWebServer.tag
argocd-image-updater.argoproj.io/webserver.update-strategy: latest
argocd-image-updater.argoproj.io/write-back-method: git
spec:
destination:
namespace: app-helm-dev
# https://XX.XX.XX.XX:6443
server: ${url}
source:
path: manifests/helm/echo-server
repoURL: 'git@github.com:ivan-cai/gitops-demo.git'
targetRevision: stable-example
helm:
valueFiles:
- values-dev.yaml
project: default
syncPolicy:
automated: {}
syncOptions:
- CreateNamespace=true
ACK One Fleet インスタンスに接続して、デプロイします。
argocd app create -f app-helm-dev.yaml
ステージングおよび本番クラスターへのデプロイ
app-helm-staging.yaml および app-helm-production.yaml を作成します。Dev とは異なり、これらのアプリケーションでは syncPolicy: automated を設定しません。イメージ変更はデプロイメントリポジトリへ書き戻されますが、差分を確認した後に手動で同期を実行します。これにより、本番相当の環境へ変更が適用される前にゲートを設けることができます。
ステージングクラスター — app-helm-staging.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-helm-staging
annotations:
argocd-image-updater.argoproj.io/image-list: echoserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-server,webserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-web-server
argocd-image-updater.argoproj.io/echoserver.helm.image-name: image.echoServer.repository
argocd-image-updater.argoproj.io/echoserver.helm.image-tag: image.echoServer.tag
argocd-image-updater.argoproj.io/echoserver.update-strategy: latest
argocd-image-updater.argoproj.io/webserver.helm.image-name: image.echoWebServer.repository
argocd-image-updater.argoproj.io/webserver.helm.image-tag: image.echoWebServer.tag
argocd-image-updater.argoproj.io/webserver.update-strategy: latest
argocd-image-updater.argoproj.io/write-back-method: git
spec:
destination:
namespace: app-staging
# https://XX.XX.XX.XX:6443
server: ${url}
source:
path: manifests/helm/echo-server
repoURL: 'git@github.com:ivan-cai/gitops-demo.git'
targetRevision: stable-example
helm:
valueFiles:
- values-staging.yaml
project: default
syncPolicy:
syncOptions:
- CreateNamespace=true
本番クラスター — app-helm-production.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-helm-production
annotations:
argocd-image-updater.argoproj.io/image-list: echoserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-server,webserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-web-server
argocd-image-updater.argoproj.io/echoserver.helm.image-name: image.echoServer.repository
argocd-image-updater.argoproj.io/echoserver.helm.image-tag: image.echoServer.tag
argocd-image-updater.argoproj.io/echoserver.update-strategy: latest
argocd-image-updater.argoproj.io/webserver.helm.image-name: image.echoWebServer.repository
argocd-image-updater.argoproj.io/webserver.helm.image-tag: image.echoWebServer.tag
argocd-image-updater.argoproj.io/webserver.update-strategy: latest
argocd-image-updater.argoproj.io/write-back-method: git
spec:
destination:
name: ''
namespace: app-production
server: 'https://39.98.XX.XX:6443'
source:
path: manifests/helm/echo-server
repoURL: 'git@github.com:ivan-cai/gitops-demo.git'
targetRevision: test2
helm:
valueFiles:
- values-production.yaml
project: default
syncPolicy:
syncOptions:
- CreateNamespace=true
イメージ変更が検出されたら、デプロイメントリポジトリが更新されたことを確認し、ArgoCD UI で REFRESH をクリック、APP DIFF を確認し、SYNC をクリックして変更を適用します。
または、CLI から同期することも可能です。
argocd app sync argocd/app-helm-staging
argocd app sync argocd/app-helm-production
カナリアリリースを実行するには、「ACK One GitOps を基盤とした Kruise Rollout を使用したカナリアリリースの実装」をご参照ください。カナリアリリースを承認するには、以下を実行します。
kubectl-kruise rollout approve rollout/rollouts-demo --kubeconfig <path to kubeconfig file>
本チュートリアルでは、カナリアリリースに Kruise Rollouts を使用しています。Argo Rollouts を使用することも可能です。「ACK One GitOps および Argo Rollouts を使用したカナリアリリースの実行」をご参照ください。
ステップ 4:アプリケーションのロールバック
以前のバージョンへロールバックするには、デプロイメントリポジトリ内のイメージタグを元に戻し、ArgoCD でアプリケーションを同期します。
-
デプロイメントリポジトリで
manifests/helm/echo-server/.argocd-source-${appname}.yamlを編集し、イメージタグを以前のバージョンへ戻します。 -
変更をコミットし、デプロイメントリポジトリへプッシュします。
-
ArgoCD UI でアプリケーションページを開き、REFRESH をクリックした後、SYNC をクリックしてロールバックされたタグを適用します。または、CLI から同期することも可能です。
argocd app sync argocd/app-helm-staging argocd app sync argocd/app-helm-production
同期が完了すると、アプリケーションは以前のイメージバージョンへ復元されます。
ステップ 5:CI/CD パイプラインのテスト
パイプライン全体をエンドツーエンドで実行し、各ステージが期待通りの出力を生成することを検証します。
1.CI パイプラインをトリガーするタグをプッシュします。
Container Registry のビルドルールに一致するブランチをプッシュします。
git clone https://github.com/{xxx}/echo-web-server.git
cd echo-web-server
git push origin HEAD:release-v3
タグ名はご自身の命名規則に基づいて設定してください。タグはビルドルール内の release- プレフィックスに一致する必要があります。
2.コンテナイメージがビルドされたことを確認します。
-
Container Registry コンソール にログインします。
-
トップナビゲーションバーでリージョンを選択します。
-
左側のナビゲーションウィンドウで インスタンス をクリックします。
-
インスタンス ページで、Enterprise Edition インスタンスをクリックします。
-
左側のナビゲーションウィンドウで リポジトリ > リポジトリ一覧 を選択し、対象のイメージリポジトリをクリックします。
-
左側のナビゲーションウィンドウで ビルド をクリックします。ビルドログ セクションで、新規イメージがリスト表示されていることを確認します。
期待される結果: ビルドログに、ステータスが 成功 の新規イメージエントリが表示されます。
3.Image Updater が新規イメージを検出したことを確認します。
ビルドが完了した後、argocd-image-updater のログを確認します。
kubectl -nargocd logs argocd-server-<xxxxx> -c argocd-image-updater -f
期待される結果: 成功した更新では、次のような出力が生成されます。
time="2023-07-19T07:35:41Z" level=info msg="Successfully updated image 'demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-web-server:v1.0' to 'demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-web-server:v3-5a7147', but pending spec update (dry run=false)" alias=echowebserver application=echo-web-server
time="2023-07-19T07:35:41Z" level=info msg="Committing 1 parameter update(s) for application echo-web-server" application=echo-web-server
4.書き戻しコミットがデプロイメントリポジトリに反映されたことを確認します。
GitHub 上のデプロイメントリポジトリに manifests/helm/echo-server/.argocd-source-${appname}.yaml が作成されていることを確認します。各クラスター(Dev、Staging、Production)ごとに 1 つのファイルが作成されます。以下の図は Dev クラスターのファイルを示しています。
期待される結果: ファイルが存在し、更新されたイメージタグ(例: v3-5a7147)が含まれています。
5.ステージングおよび本番への同期
この時点で、Dev クラスターのデプロイメントは v3-5a7147 へ自動更新されています。ステージングおよび本番を手動で同期し、カナリアリリースを承認して、これらのクラスターも v3-5a7147 へ更新します。
期待される結果: 同期およびカナリアリリースの承認が完了すると、すべての 3 つのクラスターで新規イメージバージョンが実行されます。
自動イメージ更新の設定
監視対象のイメージの指定
自動更新対象のイメージを 1 つ以上指定するには、image-list アノテーションを追加します。
argocd-image-updater.argoproj.io/image-list: <image_spec_list>
image_spec_list は、以下の形式でカンマ区切りのイメージ仕様リストです。
[<alias_name>=]<image_path>[:<version_constraint>]
alias_name は、アノテーション内でのみ使用される文字列エイリアスです。例として、イメージに対してエイリアス echoserver を設定します。
argocd-image-updater.argoproj.io/image-list: echoserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-server:v1.0
イメージタグによるフィルタリング
正規表現に一致するタグのみを対象に更新を実行します。allow-tags アノテーションを regexp: プレフィックスとともに使用します。
argocd-image-updater.argoproj.io/<image_name>.allow-tags: regexp:^v[1-9].*
echoserver に対する例:
argocd-image-updater.argoproj.io/echoserver.allow-tags: regexp:^v[1-9].*
更新戦略の設定
4 種類の更新戦略が利用可能です。デフォルトは semver です。
| 更新戦略 | 説明 |
|---|---|
semver |
セマンティックにソートされたリストで最新バージョンに更新 |
latest |
作成時刻に基づいて最新バージョンへ更新(作成時刻はプッシュ時刻とは異なる場合があります) |
name |
アルファベット順に並べられたリストから最新バージョンへ更新 |
digest |
可変タグでプッシュされた最新バージョンへ更新 |
戦略を設定するには、以下を使用します。
argocd-image-updater.argoproj.io/<image_name>.update-strategy: <strategy>
例:
argocd-image-updater.argoproj.io/echoserver.update-strategy: semver
Helm および Kustomize アプリケーション向けのアノテーション
Helm アプリケーション
values.yaml にイメージリポジトリとタグを別々に定義している場合、helm.image-name および helm.image-tag の両方を指定します。
annotations:
argocd-image-updater.argoproj.io/image-list: echoserver=demo-test-registry.cn-hangzhou.cr.aliyuncs.com/cidemo/echo-server:v1.0
argocd-image-updater.argoproj.io/echoserver.helm.image-name: image.echoServer.repository
argocd-image-updater.argoproj.io/echoserver.helm.image-tag: image.echoServer.tag
argocd-image-updater.argoproj.io/echoserver.update-strategy: latest
argocd-image-updater.argoproj.io/write-back-method: git
Kustomize アプリケーション
Kustomize の場合、エイリアス(image-list)内にタグを含め、ベースイメージアドレス(タグなし)を kustomize.image-name を使用して指定します。
annotations:
argocd-image-updater.argoproj.io/image-list: <image_alias>=<image_name>:<image_tag>
argocd-image-updater.argoproj.io/<image_alias>.kustomize.image-name: <original_image_name>