Argo CD

CI/CDArgo CDGitOpsKubernetesデプロイメント継続的デリバリーApplicationSet宣言的

CI/CDツール

Argo CD

概要

Argo CDはKubernetes向けの宣言型GitOps継続的デリバリーツールです。Gitリポジトリの設定変更を監視し、自動的にKubernetesクラスターにデプロイメントを実行する、現代的なクラウドネイティブ運用を実現します。

詳細

Argo CD(アルゴシーディー)は、Kubernetes環境におけるGitOps手法を実装する宣言型継続的デリバリーツールとして、CNCF(Cloud Native Computing Foundation)の卒業プロジェクトです。2024-2025年には、ApplicationSetの強化により複数アプリケーション・マルチクラスター管理が大幅に改善され、大規模企業での採用が加速しています。GitOpsの中核原則に従い、アプリケーション定義、設定、環境を宣言的かつバージョン管理し、デプロイメントとライフサイクル管理を自動化・監査可能・理解しやすい形で実現します。Kubernetes設定(マニフェストファイル)にGitでの変更が発生した場合、Argo CDがユーザーに通知し望ましい状態との同期を促します。本番システム設定にドリフト(設定乖離)が発生した場合、Argo CDが変更を検知しGitで定義された望ましい状態に自動復旧します。単一のGitリポジトリから単一クラスター・名前空間へのデプロイを行うArgo CD Applicationリソースを拡張し、ApplicationSetによりテンプレートベースの自動化で複数のArgo CDアプリケーションを同時に作成・変更・管理します。YAML、Helmチャート、Jsonnet、Kustomizeといった設定管理・テンプレート化ツールをサポートし、Canary・Blue-Greenデプロイメント戦略をArgo Rolloutsと組み合わせて実装可能です。OIDC、OAuth2、LDAP、SAML 2.0、GitHub、GitLab、Microsoft、LinkedInなどのSSO プロバイダーとの統合により、エンタープライズレベルのセキュリティとマルチテナンシーを提供します。

メリット・デメリット

メリット

  • 宣言型GitOps: Git真実の源泉による設定管理と自動同期
  • Kubernetes完全統合: K8sネイティブな設定とCRDサポート
  • ApplicationSet: 複数アプリ・マルチクラスター一括管理
  • 視覚的UI: 直感的なWebUIによるデプロイ状況監視
  • 自動復旧: 設定ドリフト検知と自動的な望ましい状態復元
  • マルチテナンシー: プロジェクト単位での権限・リソース分離
  • 豊富な統合: Helm、Kustomize、Jsonnet対応
  • SSO対応: エンタープライズ認証システム統合
  • ロールバック機能: Git履歴による簡単な前バージョン復旧

デメリット

  • Kubernetes専用: 他のプラットフォームには非対応
  • 学習コスト: GitOps概念とKubernetes知識が必要
  • Git依存: Git障害時のデプロイメント影響
  • 設定複雑性: 大規模環境での ApplicationSet設定管理
  • リアルタイム制限: polling間隔による同期遅延
  • デバッグ難易度: 複雑なマニフェスト問題の特定困難
  • 権限管理: 細かいRBAC設定の運用負荷

主要リンク

書き方の例

基本的なArgo CDインストール

# Argo CD名前空間作成
kubectl create namespace argocd

# Argo CD安定版インストール
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# サービス公開(LoadBalancer)
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

# 初期パスワード取得
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

# Argo CD CLI インストール
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

# CLI ログイン
argocd login <ARGOCD_SERVER>

基本的なApplicationリソース定義

# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: guestbook
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

ApplicationSetによるマルチアプリケーション管理

# applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-addons
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - clusters:
      selector:
        matchLabels:
          argocd.argoproj.io/secret-type: cluster
  - git:
      repoURL: https://github.com/example/cluster-addons.git
      revision: HEAD
      directories:
      - path: "cluster-addons/*"
  template:
    metadata:
      name: '{{.path.basename}}-{{.name}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/cluster-addons.git
        targetRevision: HEAD
        path: '{{.path.path}}'
      destination:
        server: '{{.server}}'
        namespace: '{{.path.basename}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

Helmチャート統合とValueファイル管理

# helm-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: prometheus
    targetRevision: 25.27.0
    helm:
      valueFiles:
      - values-production.yaml
      parameters:
      - name: server.persistentVolume.size
        value: 100Gi
      - name: server.replicaCount
        value: "2"
  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Kustomize統合とオーバーレイ管理

# kustomize-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: webapp-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/webapp-config.git
    targetRevision: HEAD
    path: overlays/production
    kustomize:
      images:
      - webapp:v1.2.3
      patches:
      - target:
          kind: Deployment
          name: webapp
        patch: |-
          - op: replace
            path: /spec/replicas
            value: 5
  destination:
    server: https://kubernetes.default.svc
    namespace: webapp-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
    - RespectIgnoreDifferences=true
  ignoreDifferences:
  - group: apps
    kind: Deployment
    jsonPointers:
    - /spec/replicas

Matrix GeneratorによるEnvironment × Cluster デプロイ

# matrix-applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: webapp-environments
  namespace: argocd
spec:
  goTemplate: true
  generators:
  - matrix:
      generators:
      - git:
          repoURL: https://github.com/example/app-config.git
          revision: HEAD
          files:
          - path: "environments/*/config.json"
      - clusters:
          selector:
            matchLabels:
              environment: '{{.path.basename}}'
  template:
    metadata:
      name: 'webapp-{{.path.basename}}-{{.name}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/webapp.git
        targetRevision: HEAD
        path: k8s
        kustomize:
          images:
          - webapp:{{.config.image.tag}}
      destination:
        server: '{{.server}}'
        namespace: webapp-{{.path.basename}}
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

Progressive Rollout Strategy(段階的ロールアウト)

# progressive-rollout-applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: webapp-rollout
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - cluster: dev-cluster
        env: dev
        priority: "1"
      - cluster: staging-cluster
        env: staging
        priority: "2"
      - cluster: prod-us-west
        env: production
        priority: "3"
      - cluster: prod-eu-west
        env: production
        priority: "3"
      - cluster: prod-asia
        env: production
        priority: "4"
  strategy:
    type: RollingUpdate
    rollingUpdate:
      steps:
      - matchExpressions:
        - key: priority
          operator: In
          values: ["1"]
        maxUpdate: 0  # 全て同時更新
      - matchExpressions:
        - key: priority
          operator: In
          values: ["2"]
        maxUpdate: 1  # 1つずつ更新
      - matchExpressions:
        - key: priority
          operator: In
          values: ["3"]
        maxUpdate: 50%  # 50%ずつ更新
      - matchExpressions:
        - key: priority
          operator: In
          values: ["4"]
  template:
    metadata:
      name: 'webapp-{{.cluster}}'
      labels:
        env: "{{.env}}"
        priority: "{{.priority}}"
    spec:
      project: default
      source:
        repoURL: https://github.com/example/webapp.git
        targetRevision: HEAD
        path: k8s/{{.env}}
      destination:
        server: '{{.cluster}}'
        namespace: webapp
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

プライベートリポジトリとシークレット管理

# private-repo-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/company/private-repo.git
  username: deployment-bot
  password: $GITHUB_TOKEN
  project: webapp-project

---
# cluster-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
stringData:
  name: production-cluster
  server: https://production-k8s.company.com
  config: |
    {
      "bearerToken": "$CLUSTER_TOKEN",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "$CA_DATA"
      }
    }

---
# app-project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: webapp-project
  namespace: argocd
spec:
  description: "Web Application Project"
  sourceRepos:
  - 'https://github.com/company/*'
  - 'https://helm-charts.company.com/*'
  destinations:
  - namespace: 'webapp-*'
    server: '*'
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  namespaceResourceWhitelist:
  - group: apps
    kind: Deployment
  - group: ''
    kind: Service
  - group: ''
    kind: ConfigMap
  - group: ''
    kind: Secret
  roles:
  - name: webapp-admin
    description: Admin access to webapp project
    policies:
    - p, proj:webapp-project:webapp-admin, applications, *, webapp-project/*, allow
    - p, proj:webapp-project:webapp-admin, repositories, *, *, allow
    groups:
    - company:webapp-team