ArgoCDによるGitOps — Gitからの自動デプロイ

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

手動デプロイの苦痛

現代のソフトウェア開発におけるアプリケーションのデプロイは、綱渡りのように感じられることがよくあります。CI/CDパイプラインを導入していても、従来の手動デプロイ方法では頻繁に次のような問題に直面します。

  • 構成のずれ(Configuration Drift):時間が経つにつれて、環境はしばしば乖離していきます。これが開発、ステージング、本番環境間での不整合を引き起こします。開発者がローカルで機能をテストし、完璧に動作したとしても、少し異なるデータベースバージョンや未適用構成が原因でステージング環境では失敗するといった状況を想像してみてください。
  • 手動によるエラー:デプロイプロセスにおける人間の介入は、頻繁に間違いの原因となります。これは停止や予期せぬアプリケーションの動作につながる可能性があります。
  • 遅いロールバック:インシデント発生時、以前の安定した状態に戻すのは面倒で時間のかかる作業です。これによりダウンタイムが長引きます。
  • 監査性の欠如:明確で一元化された記録がなければ、誰が何を、いつ、なぜ変更したのかを理解するのは困難になります。

Continuous Integration (CI)とContinuous Delivery (CD)パイプラインは、ビルドとテストを自動化します。しかし、多くの場合は依然としてプッシュベースのモデルを使用してアーティファクトをターゲット環境にデプロイしています。このアプローチでは、デプロイされた状態が意図した構成と完全に一致することを本質的に保証するものではありません。まさにここに、GitOpsがこれらの頻繁なデプロイの課題に対して堅牢なソリューションを提供します。

GitOpsの登場:真実の唯一の情報源

GitOpsは運用フレームワークです。バージョン管理、コラボレーション、コンプライアンス、CI/CDなどのDevOpsのベストプラクティスをインフラストラクチャの自動化にまで拡張します。基本的に、GitOpsはGitを真実の唯一の情報源として確立し、アプリケーションとインフラストラクチャの両方の望ましい状態を定義します。

この哲学は4つの核となる原則に基づいています。

  1. 宣言的(Declarative):インフラストラクチャ、アプリケーション、および構成はすべてコードとして宣言的に記述され、保存されます。これは、どのように実現するかではなく、何を実現したいかを定義することを意味します。例えば、Kubernetesマニフェストは宣言的な構成を完璧に体現しています。

  2. バージョン管理され不変(Versioned and Immutable):望ましい状態はGitに保存され、堅牢なバージョン管理を提供します。これにより、変更の追跡、ロールバック、監査が容易になります。各変更は新しいコミットを生成し、完全な履歴記録を作成します。

  3. 自動的にプル(Pulled Automatically):CI/CDパイプラインが変更をクラスターにプッシュするのとは異なり、自動オペレーター(ArgoCDなど)はGitから望ましい状態を継続的にプルして適用します。このプルベースのメカニズムは、CIパイプライン自体にクラスター認証情報を必要としないため、セキュリティを大幅に向上させます。

  4. 継続的な調整(Continuously Reconciled):オペレーターは、実際のインフラストラクチャの状態とGitで定義された望ましい状態を常に比較します。例えば、Podが手動で削除された場合など、不一致が発生すると、オペレーターはクラスターを自動的に調整します。これにより、クラスターが常にGitリポジトリの定義と一致することが保証されます。

GitOpsを採用することで、チームは大幅なメリットを享受できます。これには、より速く、より頻繁なデプロイ、より簡単で安全なロールバック、セキュリティ体制の改善、そしてすべての変更に対する明確な監査証跡が含まれます。最終的には、これがより優れた運用安定性につながります。

ArgoCD:GitOpsの執行者

Gitが真実の唯一の情報源であるとすれば、ArgoCDは、その真実がKubernetesクラスター内で一貫して維持されることを保証する用心深い守護者として機能します。ArgoCDは、Kubernetes専用に構築された宣言型GitOps継続的デリバリーツールです。クラスター内でのアプリケーションのデプロイ、監視、管理を自動化します。これらのすべての操作は、Gitに保存された構成によって推進されます。

通常、ArgoCDは次のように動作します。

  • まず、ArgoCDはGitリポジトリを継続的に監視します。Kubernetes YAMLファイル、Helmチャート、Kustomize構成など、アプリケーションマニフェストへの変更を探します。
  • 同時に、Kubernetesクラスター内で実行されているアプリケーションのライブ状態を監視します。
  • ArgoCDがGitの望ましい状態とクラスターの実際の状態との間に相違を検出すると、これを「同期外れ(out of sync)」状態としてフラグを立てます。
  • 自動同期が有効になっている場合、ArgoCDはこれらの相違を自動的に調整します。Gitで定義された状態をクラスターに適用し、構成のずれを効果的に「修復」します。

いくつかの主要な機能がArgoCDを際立たせています。これらには、デプロイメントを視覚化するための直感的なウェブUI、自動化のための強力なCLI、さまざまなマニフェスト管理ツールへのサポート、堅牢なロールベースアクセス制御(RBAC)が含まれます。

ハンズオン:ArgoCDでデプロイを自動化する

ここでは、ArgoCDを設定して、シンプルなNginxアプリケーションをKubernetesクラスターに自動デプロイする方法を見ていきます。

前提条件

始める前に、以下の準備が整っていることを確認してください。

  • 稼働中のKubernetesクラスターが必要です。MinikubeやKindはローカルテストに最適で、GKE、EKS、AKSのようなクラウドマネージドクラスターを使用することもできます。
  • kubectlがインストールされ、クラスターと対話できるように構成されている必要があります。
  • GitとKubernetes YAMLマニフェストの基本的な理解があることを推奨します。

ステップ1:ArgoCDのインストール

# ArgoCD用の新しい名前空間を作成
kubectl create namespace argocd

# 'argocd'名前空間にArgoCDをインストール
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# ArgoCDのPodが準備完了になるまで待機
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=argocd-server -n argocd --timeout=300s

# ローカルアクセス用にポートフォワーディングを使用してArgoCD UIを公開。
# 本番環境では、通常IngressまたはLoadBalancerサービスを使用します。
kubectl port-forward svc/argocd-server -n argocd 8080:443 &

# 初期管理者パスワードを取得。
# このパスワードは動的に生成され、Kubernetesシークレットとして保存されます。
ARGOCD_SERVER_POD=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $ARGOCD_SERVER_POD -n argocd -- argocd admin initial-password

# このパスワードを将来のために保存してください。デフォルトのユーザー名は「admin」です。

インストール後、ブラウザでhttps://localhost:8080にアクセスしてArgoCD UIを開きます。ユーザー名adminと、以前に取得したパスワードを使用してログインしてください。

ステップ2:アプリケーションリポジトリの準備

次に、ArgoCDが監視するシンプルなGitリポジトリを作成します。このリポジトリには、アプリケーションのKubernetesマニフェストが格納されます。このチュートリアルでは、基本的なNginxデプロイメントとそれに対応するサービスを定義します。

# アプリケーションマニフェスト用の新しいディレクトリを作成
mkdir my-nginx-app
cd my-nginx-app

# deployment.yamlファイルを作成
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.6-alpine # これは後で更新します
        ports:
        - containerPort: 80
EOF

# service.yamlファイルを作成
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP
EOF

# Gitリポジトリを初期化し、リモートにプッシュ(例:GitHub, GitLab)
# <YOUR_GIT_REPO_URL>を実際のリポジトリURLに置き換えてください。
git init
git add .
git commit -m "Initial Nginx app manifests" # 初期Nginxアプリケーションマニフェスト
git branch -M main
git remote add origin <YOUR_GIT_REPO_URL>
git push -u origin main

Gitリポジトリが公開されているか、プライベートリポジトリの場合はArgoCDがアクセスするための適切な認証情報を持っていることを確認してください。

ステップ3:ArgoCDアプリケーションの作成

KubernetesクラスターでArgoCDが稼働し、アプリケーションマニフェストがGitに存在します。次のステップは、ArgoCDにアプリケーションについて知らせることです。ArgoCDアプリケーションリソースを定義します。このリソースは、Gitリポジトリを指し、クラスター内のどこにアプリケーションをデプロイするかを指定します。

ArgoCD CLIを利用します。ArgoCDのウェブサイトの指示に従ってインストールできます(例:macOSではbrew install argocd、Linux/Windowsでは直接ダウンロード)。その後、ArgoCD CLIにログインします。

# CLIをArgoCDサーバーに接続
argocd login localhost:8080
# 'admin'と以前に取得したパスワードを使用してください

次に、ArgoCDアプリケーションを作成します。

# Gitリポジトリを指すArgoCDアプリケーションを作成
# <YOUR_GIT_REPO_URL>をリポジトリのURLに置き換えてください
argocd app create my-nginx-app \
  --repo <YOUR_GIT_REPO_URL> \
  --path . \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace default \
  --sync-policy automated \
  --auto-prune \
  --self-heal

これらのフラグについて詳しく見ていきましょう。

  • --repo: GitリポジトリのURLです。
  • --path: リポジトリ内のマニフェストが配置されているサブディレクトリです。ルートディレクトリの場合は.を使用します。
  • --dest-server: KubernetesクラスターのAPIサーバーURLです。https://kubernetes.default.svcはクラスター内デプロイメントの一般的な選択肢です。
  • --dest-namespace: アプリケーションがデプロイされるKubernetesの名前空間です。
  • --sync-policy automated: このフラグはGitOpsにとって不可欠です!Gitとクラスター間で検出された変更をArgoCDが自動的に同期するように指示します。
  • --auto-prune: Gitで定義されなくなったリソースをクラスターから削除することをArgoCDに許可します。
  • --self-heal: クラスター内でリソースが手動で変更または削除された場合、ArgoCDは自動的にGitで定義された状態に復元します。

あるいは、このArgoCDアプリケーションをKubernetesマニフェストとして定義し、直接適用することもできます。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-nginx-app
  namespace: argocd
spec:
  destination:
    namespace: default
    server: https://kubernetes.default.svc
  project: default
  source:
    path: .
    repoURL: <YOUR_GIT_REPO_URL> # リポジトリのURLに置き換えてください
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

この設定をargocd-app.yamlとして保存します。その後、kubectl apply -n argocd -f argocd-app.yamlを使用して適用します。

ステップ4:自動デプロイと同期の観察

ArgoCDアプリケーションを作成すると、すぐにArgoCD UIに表示されます。最初はOutOfSyncと表示される可能性が高いです。その後、KubernetesクラスターにNginxマニフェストが適用されるにつれて、Syncingに移行し、最終的にHealthyおよびSyncedになります。

CLIを使用してそのステータスを確認することもできます。

# すべてのアプリケーションをリスト表示
argocd app list

# アプリケーションの詳細ステータスを取得
argocd app get my-nginx-app

NginxデプロイメントがKubernetesで実行されていることを確認します。

kubectl get deployments -n default
kubectl get pods -n default -l app=nginx
kubectl get services -n default

自己修復の確認

自己修復を観察するために、構成のずれをシミュレートしてみましょう。NginxのPodを1つ手動で削除します。

# Nginx Podのいずれかの名前を取得
NGINX_POD=$(kubectl get pods -n default -l app=nginx -o jsonpath='{.items[0].metadata.name}')

# Podを手動で削除
kubectl delete pod $NGINX_POD -n default

ArgoCD UIを監視するか、argocd app get my-nginx-appを実行してください。アプリケーションが一時的にOutOfSyncに移行するのが確認できます。ほぼ同時に、ArgoCDは不一致を検出し、削除されたPodを再作成します。このアクションにより、アプリケーションはHealthyおよびSynced状態に復元されます。この継続的な調整は、GitOpsの基本的な原則です。

Gitからの自動更新

次に、Nginxアプリケーションを更新してみましょう。my-nginx-app/deployment.yamlファイルを変更して、より新しいNginxイメージを指定します。

# ... (以前の行)
      containers:
      - name: nginx
        image: nginx:1.21.6-alpine # これは後で更新します
        ports:
        - containerPort: 80
EOF

# service.yamlファイルを作成
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP
EOF

# Gitリポジトリを初期化し、リモートにプッシュ(例:GitHub, GitLab)
# <YOUR_GIT_REPO_URL>を実際のリポジトリURLに置き換えてください。
git init
git add .
git commit -m "Initial Nginx app manifests" # 初期Nginxアプリケーションマニフェスト
git branch -M main
git remote add origin <YOUR_GIT_REPO_URL>
git push -u origin main

この変更をコミットし、Gitリポジトリにプッシュします。

cd my-nginx-app # すでにディレクトリ内にいない場合
git add deployment.yaml
git commit -m "Update Nginx image to 1.23.4-alpine" # Nginxイメージを1.23.4-alpineに更新
git push origin main

数秒以内 — 正確な時間はArgoCDの同期間隔(デフォルトは3分)またはWebhookが構成されている場合は即時 — に、ArgoCDはGitリポジトリの変更を検出し、アプリケーションをOutOfSyncとしてマークします。その後、新しいNginxイメージバージョンをKubernetesクラスターに自動的にデプロイします。ArgoCD UIおよびkubectl get deployments -n defaultを実行することで、デプロイメントのロールアウトを観察できます。

本番環境では、このアプローチは常に安定した結果をもたらします。バージョン管理システムと環境が連携しているという安心感を提供し、ロールバックを容易にし、構成の問題のデバッグを簡素化します。

結論:CDの未来はGitOpsにある

ArgoCDのようなツールによって強化されたGitOpsは、Kubernetesの継続的デリバリーに対する革新的なアプローチを提示します。Gitを真実の唯一の情報源として確立し、継続的な調整を可能にすることで、チームは高度に自動化され、信頼性が高く、監査可能なデプロイメントを実現できます。

この方法論は、運用の簡素化と手動エラーの最小化だけでなく、開発チームがデプロイメントをより詳細に制御できるようになり、真に協力的な効率的なDevOps文化を育みます。ArgoCDと共にGitOpsを導入することは、インフラストラクチャとアプリケーションのデプロイメントが予測可能で、透明性があり、一貫して安定している未来へと進むことを意味します。

Share: