grasys blog

ゼロから始めるGitOps:Argo CD、Image Updater、Rolloutsの検証

どうも、ライアンでございます。

この記事では、以下のツールを用いてローカルマシンに「GitOpsワークフロー」を構築する方法を解説します。

  1. Argo CDサーバーとArgo CD Image Updaterの連携
    • 新しいイメージがリポジトリにプッシュされる Docker Hub ArgoCD Image Updater Github ArgoCD k8sリソースへ自動デプロイ
    • リポジトリに新バージョンのイメージがアップロードされると、Argo CD Image Updaterが自動的にGitブランチのタグを更新し、その変更をトリガーとしてArgo CDがKubernetesリソースの同期・デプロイを自動実行します。
  2. Argo Rollout
    • Argo RolloutsによるBlue/Greenデプロイメントの容易さを実際に検証します。

技術単語

GitOps

  • Gitリポジトリをアプリケーションの理想状態の唯一のソースとして利用することで、従来の継続的デプロイメント戦略を短縮する手法。

ArgoCD

  • GitリポジトリとKubernetesクラスター間の状態の同期を自動化する、Kubernetes向けのGitOpsツール。

ArgoCD Image updater

  • Docker Hubなどのコンテナイメージレジストリから最新のイメージタグを自動的に検知し、Gitリポジトリを更新するツール。

ArgoCD rollout

  • デフォルトのRolling Updateよりも安全で制御されたデプロイメント(例:Blue/Green、Canary)を提供する、Kubernetesのコントローラー。

minikube

  • ローカルマシン上に単一ノードのKubernetesクラスターを素早く構築・実行するためのツール。

kustomize

  • テンプレートを使わずに、ベースとなるYAMLファイルを維持したまま、デプロイされるリソースを環境ごとにカスタマイズできるツール。

前提条件

  • ローカル環境構築:Docker, kubectl, minikubeは導入済みです。
  • Gitリポジトリ:プライベートなGitHubリポジトリの作成が完了しています。
  • コンテナイメージ:Docker Hubリポジトリへのイメージバージョンのアップロードも済んでいます。

ワークフローの概要

Stagingワークフロー

Argo CD Image Updaterは、イメージレジストリ内のタグの変更を常時監視しており、新しいタグが発見されると、その変更を自動的にGitブランチにコミットします。

その後、そのブランチを監視しているArgo CDが、コミットされた変更を検知し、Kubernetesリソースを自動で更新・デプロイします。

Productionワークフロー

これから、Argo Rolloutsの機能を利用して、新しいバージョンへのデプロイを手動Blue/Greenデプロイメントの形式で進めます。

Stagingワークフローの設定

Argo CDサーバーの起動

Minikubeを起動します。(Dockerエンジンが動作している)

minikube start --insecure-registry="registry-1.docker.io"

Argo CDリソースをargocd名前空間にインストールします。

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Argo CD CLIをインストールします。

brew install argocd

ポートフォワードを設定し、Argo CDのUIにアクセス可能にします。

kubectl port-forward svc/argocd-server -n argocd 8080:443

自動生成された初期パスワードを取得します。

argocd admin initial-password -n argocd

ユーザー名 adminと取得したパスワードを使って、CLIからArgo CDサーバーにログインします。

argocd login localhost:8080

パスワードを変更します。

argocd account update-password

これで、先ほど設定した新しい認証情報を使ってArgo CDサーバーのUIにログインできるようになりました。

しかし、その前に、GitHubリポジトリをArgo CDサーバーに接続する必要があります。

UIを使ってGitHubをArgo CDサーバーに接続する

今回はSSH接続を利用するため、まずSSHキーペアを作成します。

ssh-keygen -t ed25519 -C "your_email@example.com"

作成したGitHubのプライベートリポジトリに、作成済みの公開鍵をデプロイキーとして登録します。設定は以下の図の通りにしてください。

次に、作成した秘密鍵をArgo CDサーバーのUI上で認証情報(Credentials)としてGitHubリポジトリに追加します。

アプリケーションのデプロイ準備

Application CRDをデプロイする前に、まず、隔離(アイソレーション)のベストプラクティスに基づき、base、stg、prd環境それぞれに独立した名前空間を作成します。

kubectl create namespace base
kubectl create namespace stg
kubectl create namespace prd

フォルダ構成は以下の通りです。コード全体を確認するには、こちらを押してください。

> tree
.
├── argocd
│   ├── applications
│   │   ├── app_base.yaml
│   │   ├── app_prd.yaml
│   │   └── app_stg.yaml
├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   ├── service.yaml
├── configmap
│   └── docker-access
│       └── argocd-img-updater-credentials.yaml
└── env
    ├── prd
    │   ├── rollout.yaml
    │   └── service.yaml
    └── stg
        ├── kustomization.yaml
        └── replica_count.yaml

ベースとなるリソースなしにオーバーレイをデプロイすることはできないため、まずKustomizeのベースとなるアプリケーションマニフェストを展開します。

Argo CDは「stg」ブランチの変更を監視し、このKubernetesリソースをbase名前空間へ自動的にデプロイします。

app_base.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: git@github.com:<github-url>
    targetRevision: stg
    path: base
  destination: 
    server: https://kubernetes.default.svc
    namespace: base

  syncPolicy:
    syncOptions:
    - CreateNamespace=true
    - Validate=true
    - PrunePropagationPolicy=foreground
    - PruneLast=true

    automated:
      selfHeal: true
      prune: true
      allowEmpty: false

アプリケーションマニフェストを適用します。

kubectl apply -f app_base.yaml

ご覧のように、Argo CDは最新のGitブランチへのコミット変更を検知し、Kubernetesリソースへ自動的に同期します。

ArgoCD Image Updaterの設定

Argo CD Image Updaterをインストールします。

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

Argo CD Image UpdaterにDockerレジストリへのアクセス権を付与します。認証情報はSecretに安全に保存し、ConfigMapを経由して参照するように設定します。

argocd-img-updater-credentials.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-image-updater-config
  namespace: argocd
data:
  registries.conf: |
    registries:
    - name: Docker Hub
      api_url: https://registry-1.docker.io
      prefix: docker.io
      credentials: secret:argocd/dockerhub-credentials

Docker Hubにログインするための認証情報をKubernetesのSecretとして作成します。

kubectl create secret docker-registry dockerhub-credentials --namespace argocd --docker-server=docker.io --docker-username=<username> --docker-password=<password>

Image Updaterのアノテーションはまだ適用せず、まずはステージング環境にアプリケーションをデプロイします。

これにより、アプリがNginxアプリケーション(イメージ:<dockerhub-url>/nginx-demo:1.0.0)として確実に起動することを確認します。

app_stg.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-stg
  namespace: argocd
spec:
  project: default
  source:
    repoURL: git@github.com:<github-url>
    targetRevision: stg
    path: env/stg
  destination: 
    server: https://kubernetes.default.svc
    namespace: stg

  syncPolicy:
    syncOptions:
    - CreateNamespace=true
    - Validate=true
    - PrunePropagationPolicy=foreground
    - PruneLast=true

    automated:
      selfHeal: true
      prune: true
      allowEmpty: false

マニフェストを適用します。

kubectl apply -f app_stg.yaml

デモ:最新イメージへの自動デプロイを検証

ここからは、実際に最新イメージへの自動デプロイを検証します。

まずは、現在デプロイされているステージングサービスへアクセスできるよう、ポートフォワーディングを使って公開します。

kubectl port-forward svc/myapp-service-stg -n stg 8086:80

初期バージョンである 1.0.0 は、Nginxのイメージです。

❯ kubectl describe deployment myapp-stg -n stg | grep Image
Image: <dockerhub-url>/nginx-demo:1.0.0

Argo CD Image Updaterは、デプロイするイメージタグを決定する際、デフォルトでセマンティックバージョニング(SemVer)戦略を使用します。

ここで、ステージングアプリケーションに以下のアノテーションを追加します。

この設定により、Image Updaterは利用可能なタグの中から数値的に最も新しい(高い)バージョンを選択します。 例えば、現在の1.0.0から、タグ2.0.0に自動的に更新されます。

app_stg.yaml

....
  namespace: argocd
  annotations:
  # image-list: The tag X means the image updater will update the image to the latest version.
    argocd-image-updater.argoproj.io/image-list: <dockerhub-url>/nginx-demo:X
    argocd-image-updater.argoproj.io/write-back-method: git
    argocd-image-updater.argoproj.io/pull-secret: argocd:dockerhub-credentials
....

更新したマニフェストを再適用します。

kubectl apply -f app_stg.yaml

イメージの更新が成功したかどうかは、主に以下の3つの方法で検証できます。

まず、Image Updater podのログを確認します。

> kubectl get pods -n argocd
> kubectl logs -n argocd argocd-image-updater-57878df448-bxgc8

time="2025-09-23T11:23:22Z" level=info msg="Setting new image to <dockerhub-url>/nginx-demo:2.0.0" alias= application=myapp-stg image_name=<dockerhub-url>/nginx-demo image_tag=1.0.0 registry=
time="2025-09-23T11:23:22Z" level=info msg="Successfully updated image '<dockerhub-url>/nginx-demo:1.0.0' to '<dockerhub-url>/nginx-demo:2.0.0', but pending spec update (dry run=false)" alias= application=myapp-stg image_name= <dockerhub-url>/nginx-demo image_tag=1.0.0 registry=

次は、GitHubリポジトリのコミット履歴を確認します。イメージの更新は自動的にコミットされており、通常、そのファイル名は .argocd-source-<アプリケーション名>.yaml といった形式になっています。

最後に、ブラウザでアクセスして確認します。

以前のNginxのホーム画面が、ご覧の通りApacheのホーム画面に切り替わっていることを確認できます。

以前のコミットへのロールバック手順

Argo CDのUI上では、以下の手順で簡単に前のコミットへロールバックできます。

  1. 対象のApplication CRDを選択します。
  2. 画面上部の History and Rollback タブをクリックします。
  3. ロールバックしたいコミット履歴の右側にある三点リーダー(︙)ボタンを押します。
  4. 最後に Rollback ボタンを押して実行します。

メモ:以前のコミットにロールバックを実行した場合、自動同期(Auto Sync)は自動的に無効になります。

Productionワークフローの設定

Argo RolloutsではカナリアデプロイやBlue/Greenデプロイなど多様な戦略が提供されていますが、本記事ではBlue/Greenデプロイのみを実行します。

Argo Rolloutsの設定

まず、argo-rollout名前空間にargo-rolloutsコントローラーをインストールします。

kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

kubectlのArgo RolloutsプラグインCLIをインストールします。

brew install argoproj/tap/kubectl-argo-rollouts

Rolloutマニフェストの手動デプロイ

ここでは、Argo CDの管理外で、Rolloutマニフェストを手動でデプロイします。

これは、Blue/Green戦略の動作確認のための一時的なデプロイ手順となります。

env/prd/rollout.yaml

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app-rollout
  namespace: prd
spec:
  replicas: 2
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: my-app-rollout
  template:
    metadata:
      labels:
        app: my-app-rollout
    spec:
      containers:
      - name: my-app-rollout
        image: argoproj/rollouts-demo:blue
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  strategy:
    blueGreen: 
      activeService: my-app-active
      previewService: my-app-preview
      autoPromotionEnabled: false

Rolloutマニフェストを適用します。

kubectl apply -f env/prd/rollout.yaml

Serviceマニフェストのデプロイ

RolloutのBlue/Green戦略に必須となる、preview用とactive用、両方のServiceマニフェストも同様に適用します。

これらのserviceが、デプロイ時にトラフィックの振り分けを担います。

env/prd/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-app-active
  namespace: prd
spec:
  selector:
    app: my-app-rollout
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-preview
  namespace: prd
spec:
  selector:
    app: my-app-rollout
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

Serviceマニフェストを適用します。

> kubectl apply -f env/prd/service.yaml

service/my-app-active created
service/my-app-preview created

デプロイされたServiceリソースが正しく作成されているか確認します。

❯ kubectl get svc -n prd

NAME             TYPE        CLUSTER-IP      EXTERNAL
-IP   PORT(S)    AGE
my-app-active    ClusterIP   10.109.32.210   <none>
      8080/TCP   143m
my-app-preview   ClusterIP   10.105.20.40    <none>
      8080/TCP   142m

現在のデプロイ状況を可視化するために、ターミナルで以下のコマンドを実行します。

初期状態では、イメージタグは 「blue」 と表示されます。

> kubectl argo rollouts get rollout my-app-rollout -n prd --watch

Name:            my-app-rollout
Namespace:       prd
Status:          ✔ Healthy
Strategy:        BlueGreen
Images:          argoproj/rollouts-demo:blue (stable, active)
Replicas:
  Desired:       2
  Current:       2
  Updated:       2
  Ready:         2
  Available:     2

NAME                                        KIND        STATUS     AGE  INFO
⟳ my-app-rollout                            Rollout     ✔ Healthy  21m
└──# revision:1
   └──⧉ my-app-rollout-57bf9c5889           ReplicaSet  ✔ Healthy  19m  stable,active
      ├──□ my-app-rollout-57bf9c5889-487gx  Pod         ✔ Running  19m  ready:1/1
      └──□ my-app-rollout-57bf9c5889-bzlxs  Pod         ✔ Running  19m  ready:1/1

Rolloutのプレビュー開始

ここから、新しい 「green」 イメージバージョンへのロールアウトを開始し、my-app-previewサービスにルーティングします。

kubectl argo rollouts set image my-app-rollout -n p
rd my-app-rollout=argoproj/rollouts-demo:green

現在、新しい「green」イメージバージョンは一時停止(Pause)状態にあり、previewサービスにのみルーティングされており、activeサービスでは提供されていません。

Name:            my-app-rollout
Namespace:       prd
Status:          ॥ Paused
Message:         BlueGreenPause
Strategy:        BlueGreen
Images:          argoproj/rollouts-demo:blue (stable, active)
                 argoproj/rollouts-demo:green (preview)
Replicas:
  Desired:       2
  Current:       4
  Updated:       2
  Ready:         2
  Available:     2

NAME                                        KIND        STATUS     AGE   INFO
⟳ my-app-rollout                            Rollout     ॥ Paused   104m
├──# revision:2
│  └──⧉ my-app-rollout-f75f67d6d            ReplicaSet  ✔ Healthy  64m   preview
│     ├──□ my-app-rollout-f75f67d6d-552dc   Pod         ✔ Running  64m   ready:1/1
│     └──□ my-app-rollout-f75f67d6d-zggsf   Pod         ✔ Running  64m   ready:1/1
└──# revision:1
   └──⧉ my-app-rollout-57bf9c5889           ReplicaSet  ✔ Healthy  102m  stable,active
      ├──□ my-app-rollout-57bf9c5889-487gx  Pod         ✔ Running  102m  ready:1/1
      └──□ my-app-rollout-57bf9c5889-bzlxs  Pod         ✔ Running  102m  ready:1/1

以下のコマンドを使ってポートフォワーディングを行い、previewサービス経由で新しい「green」イメージバージョンにアクセスできるようにします。

kubectl port-forward svc/my-app-preview -n prd 8082:8080

こちらが、現在デプロイされているアクティブサービスです。初期の 「blue」イメージバージョンがトラフィックを処理している状態を確認できます。

kubectl port-forward svc/my-app-active -n prd 8081:8080

Preview中のRolloutをActiveへ昇格(プロモート)

新しいイメージバージョンを本番環境へ切り替える(プロモート)には、そのトラフィックをmy-app-activeサービスが受け持つようにする必要があります。

この切り替えは、以下のpromoteコマンドで実行できます。

> kubectl argo rollouts promote my-app-rollout -n prd
rollout 'my-app-rollout' promoted

このコマンドの実行により、以前の 「blue」 イメージバージョンのPodリソースも削除されます

Name:            my-app-rollout
Namespace:       prd
Status:          ✔ Healthy
Strategy:        BlueGreen
Images:          argoproj/rollouts-demo:green (stable, active)
Replicas:
  Desired:       2
  Current:       2
  Updated:       2
  Ready:         2
  Available:     2

NAME                                       KIND        STATUS        AGE   INFO
⟳ my-app-rollout                           Rollout     ✔ Healthy     159m
├──# revision:2
│  └──⧉ my-app-rollout-f75f67d6d           ReplicaSet  ✔ Healthy     119m  stable,active
│     ├──□ my-app-rollout-f75f67d6d-552dc  Pod         ✔ Running     119m  ready:1/1
│     └──□ my-app-rollout-f75f67d6d-zggsf  Pod         ✔ Running     119m  ready:1/1
└──# revision:1
   └──⧉ my-app-rollout-57bf9c5889          ReplicaSet  • ScaledDown  157m

ポートフォワーディングを使って、my-app-activeサービスが更新されたことを確認できます。

kubectl port-forward svc/my-app-active -n prd 8081:8080

学びの要点

このチュートリアルを通して得られた学びの要点は以下の通りです。

  • Minikubeの動作環境について: Minikubeを起動するには、DockerやOrbStackといったコンテナドライバーが必須である。
  • Argo CDのApplication CRD (カスタムリソース定義)こそが、Gitブランチのディレクトリと、Kubernetesリソースのライブ状態を同期させるための設定そのものである。
  • Image Updaterの前提条件: コンテナイメージの自動更新対象とするアプリケーションは、必ずArgo CDによって管理されている必要がある。
  • Image Updaterの対応フォーマット: Argo CD Image Updaterがコンテナイメージを更新できるのは、アプリケーションマニフェストがKustomizeまたはHelmによってレンダリングされている場合に限られる。

まとめ

この記事では、Argo CDを使ったGitOpsの基本的な構成について、しっかりとした基礎を固めることができました。

特にArgo CDとImage Updaterは、リソースデプロイを効率化してくれる非常に便利なツールだと実感しています。

ただし、Argo Rollouts自体は強力な高度なデプロイ機能を提供してくれるものの、コアとなるArgo CDのワークフローと統合し、シームレスな更新を実現する点では、少々課題に直面しました。

統合時のつまずきはありましたが、このデバッグの過程こそが最高の学習機会でした。一つ一つ問題を解決していく中で、Argo CDがどのように動作しているのかを深く、実践的に理解できたからです。

GitOpsを体感したい方には、ぜひこのハンズオンでのアプローチを強くお勧めします!


採用情報
お問い合わせ