コンテンツにスキップ

プラクティス集@ArgoCD

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. repo-server

可用性

Podを冗長化させることで、repo-serverの可用性を高める。


性能

▼ 問題

repo-serverは、リポジトリでコミットが更新されるたびにキャッシュを作成する。

Volumeの種類によるが、EmptyDir Volumeであれば、Podを再作成するたびにリポジトリをクローンする。

▼ レプリカ数

repo-serverの冗長化は、可用性だけでなく性能設計の改善にもつながる。

例えば、レプリカ数を3倍にすると、Sync時間が1/3になる。

▼ レプリカ当たりの処理効率の向上

repo-serverは、レプリカ当たり同時に1つの処理しかできない。

この時、リポジトリがモノリポジトリ (たくさんのHelmチャートが含まれる) であり、複数のApplicationがこの単一のモノリポジトリをポーリングしていると仮定する。

すると、各Applicationのマニフェスト作成処理はrepo-serverのレプリカ数に影響を受ける。

Applicationがポーリングするリポジトリのパス直下に.argocd-allow-concurrencyファイルを置いておくと並行処理をしてくれる。

▼ キャッシュ作成の頻度を下げる

repo-serverは、デプロイ対象のリポジトリにあるマニフェストのキャッシュを積極的に作成する

この時、リポジトリがモノリポジトリ (たくさんのHelmチャートが含まれる) であり、複数のApplicationがこの単一のモノリポジトリをポーリングしていると仮定する。

例えば、Applicationが500個でリポジトリが1個のような場合である。

すると、各Applicationでは、デプロイ対象のHelmチャートだけでなく、それ以外のHelmチャートの変更であっても、キャッシュを再作成することになる。

これが、パフォーマンスの問題になる。

そのため、モノリポジトリには注意が必要である。

Applicationのmetadata.annotationsキーにargocd.argoproj.io/manifest-generate-pathsキーを設定し、マニフェストのキャッシュ再作成のトリガーとするディレクトリを設定する。

これにより、argocd_app_reconcile_countargocd_git_request_totalのメトリクスを改善できる。


02. application-controller

可用性

Podを冗長化させることで、application-controllerの可用性を高める。

ArgoCDの場合、冗長化はapplication-controllerの性能設計の改善にもつながる。


性能

▼ 問題

テナントにいくつかの実行環境のApplicationを集約する場合に、Application数が増えがちになる。

application-controllerは、デフォルトだとレプリカ当たり400個のApplicationまでReconciliationできる。

  • --status-processorsは、application-controllerがデプロイ対象のClusterに対してヘルスチェックするためのプロセッサ数
  • --operation-processorsは、application-controllerがデプロイ対象のClusterに対して、差分確認 (kubectl diff) と Sync (kubectl apply) するためのプロセッサ数

▼ レプリカ当たりの処理効率の向上

application-controllerは、Reconciliation時にApplicationを一つずつ処理していく。

CPUの並列処理数を増やすと、レプリカ当たりの処理効率を上げられる。

Clusterのヘルスチェックの並列処理数は--status-processorsオプションで、Diff/Sync処理のそれは--operation-processorsオプションで変更できる。

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  controllers.status.processors: 50
  controllers.operation.processors: 25
  • Application1000個の場合、--status-processors50--operation-processors25を指定
  • Application400個の場合、--status-processors20--operation-processors10を指定 (デフォルト値)

Application数が多くなるほど、Reconciliationの処理キューを空にするのに時間がかかる。

大量のApplicationをReconciliationする場合、次のような対処方法がある。

▼ レプリカ当たりの負荷の低減

application-controllerは、デプロイ対象のClusterを処理する。

レプリカ数を単純に増やしても、application-controllerの各レプリカは全てのClusterに対する処理を実行してしまう。

例えば、ARGOCD_CONTROLLER_REPLICASをレプリカ数と同じ数値で設定すると、application-controllerのレプリカは、Clusterに対する処理を分業するようになる。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: argocd-application-controller
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: argocd-application-controller
          env:
            - name: ARGOCD_CONTROLLER_REPLICAS
              value: 2

なお、執筆時点 (2023/08/02) 時点で、単一のClusterの処理をapplication-controllerの異なるレプリカに分散できない。

▼ レプリカ当たりのReconciliation頻度の低減

application-controllerのReconciliationの頻度を設定する。

ArgoCDのカスタムリソースに対するReconcileの頻度が下がれば、平常時のapplication-controllerの負荷は下がる。

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  timeout.reconciliation: 180s

▼ 処理結果のキャッシュの更新頻度の低減

application-controllerは、クラスターの処理結果のキャッシュを定期的に削除する (デフォルトでは12時間) 。

キャッシュの削除時の間、SyncやRefreshの処理を実施できなくなる。

Application数が多いほど、キャッシュの削除時間が長くなる。

キャッシュの頻度を下げたり、無効化することにより、削除時間の長期化を低減できる。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: argocd-application-controller
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: argocd-application-controller
          env:
            - name: ARGOCD_CLUSTER_CACHE_RESYNC_DURATION
              value: 0


03. argocd-server

可用性

Podを冗長化させることで、argocd-serverの可用性を高める。

ArgoCDの場合、冗長化はargocd-serverの性能設計の改善にもつながる。


性能

▼ 問題

argocd-serverは、ステートレスで高負荷になりにくい。

念の為、他のコンポーネントの数に合わせて冗長化するとよい。

▼ レプリカ当たりの負荷の低減

ARGOCD_API_SERVER_REPLICAS変数で、argocd-serverの異なるレプリカへのリクエストを分散できる。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: argocd-server
          env:
            - name: ARGOCD_API_SERVER_REPLICAS
              value: 3


安全性

ArgoCDには、ダッシュボード上から特定のkubectlコマンド (kubectl logsコマンド、kubectl execコマンド) を実行できる機能がある。

ダッシュボードの操作者にその権限がない場合、権限を絞る必要がある。


04. ポーリング対象のClusterのデザインパターン

内部Clusterパターン

ArgoCDのApplicationと、ポーリング対象のClusterを同じClusterで管理する。

ApplicationとClusterを一括で管理できる。


外部Clusterパターン

ArgoCDのApplicationと、ポーリング対象のClusterを別々のClusterで管理する。

複数のClusterにデプロイするApplicationを管理しやすい。


05. リポジトリ構成規約

リポジトリ分割のメリット

リポジトリを分割することにより、以下のメリットがある。

  • 認可スコープをリポジトリ内に閉じられるため、運用チームを別に分けられる。


マニフェストリポジトリ

▼ マニフェストリポジトリとは

マニフェストやチャートを管理する。

GitOpsのベストプラクティスに則って、アプリケーションリポジトリとマニフェストリポジトリに分割する。

▼ アプリ領域

アプリ領域のマニフェストやチャートは、ArgoCDとは別に管理する。

# アプリ領域のマニフェスト
app-manifest-repository/
├── tes/
│   ├── deployment.yaml
│   ...

├── stg/
└── prd/

▼ インフラ領域

インフラ領域のマニフェストやチャートは、ArgoCDとは別に管理する。

# インフラ領域のマニフェスト
infra-manifest-repository/
├── tes/
│   ├── deployment.yaml
│   ...

├── stg/
└── prd/


アプリリポジトリ

アプリケーションのソースコードを管理する。

説明は省略する。


06. Applicationのデザインパターン

Appパターン (通常パターン)

ポーリング対象リポジトリごとにApplicationを作成し、これらを同じリポジトリで管理する。

この時、全てのApplicationには親Applicationが存在しない。

ポーリング対象リポジトリにはKubernetesリソースのマニフェストやhelmチャートが管理されている。

argocd-repository/
├── tes/
│   ├── app-application.yaml
│   └── infra-application.yaml

├── stg/
└── prd/
app-manifest-repository/ # マニフェストリポジトリまたはチャートリポジトリ
├── tes/
│   ├── deployment.yaml
│   ....

├── stg/
└── prd/
infra-manifest-repository/ # マニフェストリポジトリまたはチャートリポジトリ
├── tes/
│   ├── deployment.yaml
│   ...

├── stg/
└── prd/


App Of Appsパターン

▼ App Of Appsパターンとは

親Applicationで子Applicationをグループ化したように構成する。

Applicationの.resourceキー配下で、紐づく子Applicationを管理している。

root-application

▼ root-application (第1階層のApplication)

全てのApplicationをポーリングする最上位Applicationのこと。

root-applicationとAppProjectは同じNamespaceに所属する必要がある。

状態の影響範囲を加味して、デプロイ先のCluster (異なる実行環境も含む) を粒度として、root-applicationを作成する。

root-applicationは、defaultrootのAppProjectに配置する。

# 最上位Application
root-argocd-repository/
├── tes/
│   └── root-application.yaml

├── stg/
└── prd/

▼ parent-application (第2階層のApplication)

各AppProjectの子Applicationをポーリングする親Applicationのこと。

管理チームごとにApplication (app-parent-application、infra-parent-application) を作成すると良い。

parent-applicationは、実行環境名 (dev、stg、prd) のAppProjectに配置する。

# 親Application
parent-argocd-repository/
├── tes/
│   ├── app-parent-application.yaml # appのAppProjectをポーリングするapplication
│   └── infra-parent-application.yaml # infraのAppProjectをポーリングするapplication

├── stg/
└── prd/

▼ child-application (第3階層のApplication)

各AppProjectで、マニフェストリポジトリやチャートリポジトリをポーリングするApplicationのこと。

マイクロサービス単位のマニフェストやチャートごとに作成すると良い。

child-applicationは、そのマイクロサービスをデプロイする権限を持つチーム名のAppProjectに配置する。

child-applicationは、実行環境名 (dev、stg、prd) のAppProjectに配置する。

# 子Application
child-argocd-repository/
├── tes/
│   ├── app
│   │   ├── account-application.yaml
│   │   ├── customer-application.yaml
│   │   ├── orchestrator-application.yaml
│   │   ├── order-application.yaml
│   │   └── shared-application.yaml
│   │
│   └── infra
│       ├── fluentd-application.yaml
│       ├── grafana-application.yaml
│       ├── istio-application.yaml
│       ├── kiali-application.yaml
│       ├── prometheus-application.yaml
│       ├── shared-application.yaml
│       └── victoria-metrics-application.yaml

├── stg/
└── prd/

▼ grand-parent-application

記入中...


07. ディレクトリ構成規約

実行環境別 (必須)

必須の構成である。

実行環境別に、Applicationを異なるディレクトリで管理する。

Applicationでは、実行環境に対応するブランチのみをポーリングする。

repository/
├── tes/ # テスト環境
├── stg/ # ステージング環境
└── prd/ # 本番環境


08. 命名規則

Application

同じCluster内ではApplication名を一意にする必要がある。

また、GUI上での実行環境の選択ミスを予防するために、実行環境名をつける。

例えば、Application名にサービス名と実行環境名 (例:<サービス名>-<実行環境名>) で命名する。

執筆時点 (2023/03/08) で、ArgoCDのConfigMapに、親Applicationを指定するためのラベル名を設定できる。

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: argocd
  name: argocd-cm
  labels:
    app.kubernetes.io/part-of: argocd
data:
  application.instanceLabelKey: argocd.argoproj.io/instance

ArgoCDは、Kubernetesリソースの.metadata.labelsキーにこのラベル (ここではargocd.argoproj.io/instanceキー) を自動的に設定する。

AppProjectが異なる限り、同じCluster内にある同じargocd.argoproj.io/instanceキー値を持つApplicationは区別される。

一方で、同じAppProjectにあるApplicationは、たとえNamespaceが異なっていても区別できない。

そのため、Kubernetesリソースが複数のApplicationに紐づいてしまう。

これらの理由から、同じCluster内ではApplication名を一意にする必要がある。


AppProject

実行環境名 (dev、stg、prd) とする。

ArgoCDでは、認可スコープ (argocd-rbac-cm) とAppProjectを紐付けられるため、特定の実行環境のAppProjectに所属するArgoCD系リソースのみを操作できるようになる。


Namespace

プロダクト名とする。

同じCluster内に、複数のプロダクト用のArgoCDを配置できるようになる。


09. CDツールに関するテスト

脆弱性対策

▼ 公式側

対象のソースコードの脆弱性ではなく、CDツールに関するそれに対処する。

CDツール (例:ArgoCD、Fluxなど) によっては、公式リポジトリで脆弱性診断を実施してくれている。


認証/認可

▼ ArgoCDの操作ユーザーの場合

ArgoCDのデフォルトの認証方法は、Bearer認証である。

利便性のためSSOを採用しつつ、二要素認証を組み合わせて強度を高める。

そのために、認証フェーズを信頼性の高い外部サービス (Auth0、GitHub、GitLabなど) に委譲し、SSO (OAuth、SAML、OIDC) を採用する。

さらに、SSOと二要素認証を組み合わせ、上記の認証フェーズ時にPCやスマホのワンタイムパスワードを要求する。

認証/認可方法 二要素認証 推奨/非推奨
Bearer認証 (デフォルト) - 非推奨
OAuth あり 推奨
なし 非推奨
OIDC あり 推奨
なし 非推奨
SAML あり 推奨
なし 非推奨

▼ ArgoCD自体の場合

ArgoCDをServiceAccountで認証し、またClusterRoleで認可する。

期限 説明 方法 推奨/非推奨
恒久的 CDツールを恒久的に認証し、また同様に認可スコープを恒久的に付与する。 Kubernetes v1.21 以前では、ServiceAccountの認証用のトークンに期限がない。 非推奨
一時的 CDツールを一時的に認証し、また同様に認可スコープを一時的に付与する。 Kubernetes v1.22 以降では、BoundServiceAccountTokenVolumeにより、ServiceAccountのトークンに1時間の有効期限がある。kube-apiserverのクライアント側が特定のバージョンのclientパッケージを使用していれば、認証用のトークンが定期的に再作成されるようになっており、一時的な認証を実現できている。一方で、CDツールにClusterRoleの認可スコープ一時的に付与する方法は、調査した限り見つからなかったが、preSyncなどを使用すればできるかも。
参考:
https://github.com/argoproj/argo-cd/issues/9417#issuecomment-1162548782
https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume
推奨


機密な変数やファイルの管理

▼ Secretの変数の場合

記入中...


10. 事後処理

通知

CDパイプライン上で実行しているステップ (例:デプロイ、ロールバックなど) の結果が通知されるようにする。

通知があることと品質を高めることは直接的には関係ないが、開発者の作業効率が上がるため、間接的に品質を高めることにつながる。


11. エラー解決

AppProjectが見つからない

argocd-serverまたはapplication-controllerが、Applicationで指定されたAppProjectを見つけられず、以下のエラーを返すことがある。

Application referencing project foo-project which does not exist


削除できない系

▼ Applicationを削除できない

PruneによるKubernetesリソースの削除を有効化し、フォアグラウンドで削除した場合、Applicationが配下にリソースを持たないことにより、Applicationを削除できないことがある。

これらの場合には、以下の手順でApplicationを削除する。

(1)

Applicationの.spec.syncPolicy.allowEmptyキーを有効化する。

(2)

フォアグラウンドで削除すると、Applicationの.metadata.finalizersキーの値に削除中のリソースが設定される。

この配列を空配列に変更する。ArgoCDのUIからは変更できず、kubectl patchコマンドを使用する必要がある。

$ kubectl patch crd applications.argoproj.io \
    -p '{"metadata":{"finalizers":[]}}' \
    --type=merge
(3)

1つ目の.spec.syncPolicy.allowEmptyキーの変更を元に戻す。

▼ Namespaceを削除できない

$ kubectl patch ns argocd \
    -p '{"metadata":{"finalizers":[]}}' \
    --type=merge


Helmチャートが大きすぎるとArgoCDがフリーズする

今現在、Helmにはインストールしたチャートのキャッシュを作成する機能がない。

そのため、大きすぎるチャートをArgoCDで使用すると、毎回大きなチャートをインストールすることになり、ArgoCDが高負荷でフリーズすることがある。

Helmで、チャートのキャッシュ機能が実装されれば、ArgoCDのフリーズも解消できるはずである。


ConfigMapやSecretの設定変更が反映されない

ArgoCDを使用しない場合と同様にして、ConfigMapやSecretの設定変更を反映する場合、Deployment/StatefulSet/DaemonSetを再起動する必要がある。


すでに終了したPodがポーリングされ続ける

すでに終了したPodをポーリングし続けてしまうことがある。

この問題が起こった場合、以下のいずれかで解決する。

  • argocd-serverを再起動する。親になるリソースを削除する必要がなく、apply先のClusterには影響がないため、安全な方法である。ArgoCDの使用者に周知しさえすれば問題ない。
  • Workload (例:Deployment、DaemonSet、StatefulSet、Jobなど) を一度削除する。ただし、親になるリソースを削除する必要があるため、やや危険である。


Progressing状態でスタックする

Ingress、StatefulSet、DaemonSet、で特定の設定値を使用していると、ArgoCDのProgressing状態でスタックすることがある。


SyncしてもOutOfSyncステータスが解消されない

Sync後にKubernetesリソースの状態が変更されるような場合、SyncしてもSyncedステータスではなくOutOfSyncステータスになってしまう。


12. アーキテクチャ特性の担保

可用性の場合

可用性を高めるために、ArgoCDの各コンポーネントを冗長化する。


13. アップグレード

ArgoCD自体のアップグレード

▼ 対応バージョンについて

ArgoCDのアップグレードでは、ArgoCD自身が動くClusterと、デプロイ先Clusterの両方のバージョンを考慮する必要がある。

ArgoCDのコンポーネントのうちで、argocd-serverはclient-goパッケージを使用して、自身が動くClusterのkube-apiserverと通信する。

一方で、application-controllerも同様にclient-goパッケージ (gitops-engineがこれを持つ) を使用して通信する。

ArgoCDでは、CI上でClusterのバージョンをテストしており、CIの実行環境 (K3SやK3Dを使用している) のバージョンから、テスト済みのClusterのバージョンを確認できる。

このテストでは、CI上に特定のバージョンのKubernetes Clusterを作成し、またこのClusterに対してArgoCDの稼働や各種処理 (マニフェストデプロイ) を実行する。

例えば、ArgoCDのv2.7.3は、K3Sのv1.26.0/v1.25.4/v1.24.3/v1.23.3をサポートしているため、これらのバージョンのClusterで稼働しつつ、マニフェストをデプロイできることが保証されている。

▼ CRDについて

ArgoCD自体をArgoCDで管理することはできないため、手動やマニフェスト管理ツール (Helm、Kustomize) でArgoCDをアップグレードする必要がある。

特にCRDは、マニフェスト管理ツールで更新できない (作成はできる) 場合がある。

そのため、チャートリポジトリにある該当のディレクトリ配下のCRDのマニフェストを指定し、直接的に更新する。


ArgoCDを使用したツールのアップグレード

マニフェストリポジトリやチャートリポジトリの設計によっては、新バージョンのKubernetesリソース名にリビジョン番号がつくようになっていることがある (例:Istioのチャート) 。

この場合、Pruneを無効化した上で、既存のKubernetesリソースをそのままに、新バージョンを新しく作成する。

新バージョンの動作が問題なければ、旧バージョンのKubernetesリソースをPruneで削除する。


13-02. B/G式のアップグレード (AWS EKSの場合)

AWS Load Balancerコントローラーを採用している場合

▼ 新しくAWS ALBを作成する場合

  • 別のドメインでB/G Clusterに接続する方法。DNSレコードが異なる。一番簡単だが、ドメインを変更しないといけない。
  • B/G ClusterをAWS Route53で切り替える方法。DNSレコードは既存のものを使って、これに紐づくAWS ALBが異なる。DNSキャッシュに注意する。

▼ 既存のAWS ALBを使用する場合

  • TargetGroupBindingを新しく採用し、ALBの振り分けの重みづけでB/G Clusterを切り替える方法。ArgoCDが複数のプロダクトを管理している場合、プロダクトごとに切り替えられない。


AWS ALB、Nginxコントローラーを採用している場合

AWS ALBのターゲットグループでB/G Clusterを切り替える方法。


13-03. インプレース

ArgoCDと同時にKubernetesもアップグレードする場合、問題を切り分けやすいように、別々にアップグレードする。

検証時は1バージョンずつアップグレードし、最終的な設定方法を探る。

検証後は、最終的な設定方法で一気にアップグレードすると良い。


14. Prometheusによる監視

メトリクスの種類

ArgoCDはデータポイントを作成し、これをPrometheusで収集できる。

Prometheusのメトリクス メトリクスの種類 説明
argocd_app_info Gauge Applicationの状態を表す。
argocd_app_k8s_request_total Counter 差分の検出時に、Applicationからポーリング対象Clusterに送信されたリクエスト数を表す。
argocd_app_labels Gauge 記入中...
argocd_app_reconcile Histogram Applicationの性能を表す。
argocd_app_sync_total Counter ApplicationのSync数を表す。
argocd_cluster_api_resource_objects Gauge ポーリング対象Clusterに関して、キャッシュしているKubernetesリソースのマニフェスト数を表す。
argocd_cluster_api_resources Gauge ポーリング対象Clusterに関して、検知しているKubernetesリソースのマニフェスト数を表す。
argocd_cluster_cache_age_seconds Gauge ポーリング対象Clusterに関して、キャッシュの有効期間を表す。
argocd_cluster_connection_status Gauge ポーリング対象Clusterに関して、現在の接続状態を表す。
argocd_cluster_events_total Counter ポーリング対象Clusterに関して、イベントの合計数を表す。
argocd_cluster_info Gauge ポーリング対象Clusterの状態を表す。
argocd_kubectl_exec_pending Gauge ArgoCDのexecのPending数を表す。
argocd_kubectl_exec_total Counter ArgoCDのexecの合計数を表す。
argocd_redis_request_duration Histogram Redisへのリクエストのレイテンシーを表す。
argocd_redis_request_total Counter Redisへのリクエスト数を表す。
app_reconciliation_queue Counter application-controllerはカスタムリソースのReconciliation処理をキューに格納する。これの処理数を表す。
app_operation_processing_queue Counter application-controllerはSync処理をキューに格納する。これの処理数を表す。
argocd_git_request_total Counter repo-serverのgit ls-remoteコマンドやgit fetchコマンドの実行数を表す。これらは、request_typeラベルでls-remotefetchという値で取得できる。キャッシュが更新される頻度が高いとgit fetchコマンドの実行頻度も高くなる。


Grafanaダッシュボード

▼ 性能ヒートマップ

縦軸でReconciliationの秒数、横軸で色でReconciliationの処理数、を表現する。

グラフの上部にたくさんの処理が分布するほど、Reconciliationの性能が低いことがわかる。


必要なKubernetesリソース

▼ ServiceMonitor

ServiceMonitorを作成し、ArgoCDのコンポーネントのPodを監視する。

ServiceMonitorは、ArgoCDのコンポーネントがテナントごとにあっても、1つ作成すれば良い。

# application-controllerのPodを監視する
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-application-controller
  namespace: prometheus
spec:
  endpoints:
    - port: http-metrics
  namespaceSelector:
    any: "true"
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
---
# redisのPodを監視する
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-redis
  namespace: prometheus
spec:
  endpoints:
    - port: http-metrics
  namespaceSelector:
    any: "true"
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-redis
---
# repo-serverのPodを監視する
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-repo-server
  namespace: prometheus
spec:
  endpoints:
    - port: http-metrics
  namespaceSelector:
    any: "true"
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-repo-server-metrics
---
# argocd-serverのPodを監視する
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-server
  namespace: prometheus
spec:
  endpoints:
    - port: http-metrics
  namespaceSelector:
    any: "true"
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-server-metrics

▼ Service

スクレイピング専用のServiceを作成し、ServiceMonitorからリクエストを受信できるようにする。

# application-controller用のServiceMonitorからリクエストを受信する
apiVersion: v1
kind: Service
metadata:
  name: foo-argocd-application-controller-metrics
  namespace: foo
spec:
  type: ClusterIP
  ports:
    - name: http-metrics
      protocol: TCP
      port: 8082
      targetPort: metrics
  selector:
    app.kubernetes.io/name: argocd-application-controller
    app.kubernetes.io/instance: foo
---
# redis用のServiceMonitorからリクエストを受信する
apiVersion: v1
kind: Service
metadata:
  name: foo-argocd-redis-metrics
  namespace: foo
spec:
  type: ClusterIP
  clusterIP: None
  ports:
    - name: http-metrics
      protocol: TCP
      port: 9121
      targetPort: metrics
  selector:
    app.kubernetes.io/name: argocd-redis
    app.kubernetes.io/instance: foo
    app.kubernetes.io/component: redis
---
# repo-server用のServiceMonitorからリクエストを受信する
apiVersion: v1
kind: Service
metadata:
  name: foo-argocd-repo-server-metrics
  namespace: foo
spec:
  type: ClusterIP
  ports:
    - name: http-metrics
      protocol: TCP
      port: 8084
      targetPort: metrics
  selector:
    app.kubernetes.io/name: argocd-repo-server
    app.kubernetes.io/instance: foo
---
# argocd-server用のServiceMonitorからリクエストを受信する
apiVersion: v1
kind: Service
metadata:
  name: foo-argocd-server-metrics
  namespace: foo
spec:
  type: ClusterIP
  ports:
    - name: http-metrics
      protocol: TCP
      port: 8083
      targetPort: metrics
  selector:
    app.kubernetes.io/name: argocd-server
    app.kubernetes.io/instance: foo


15. マルチテナント

ArgoCDでテナント分割が必要な理由

異なるClusterをデプロイ先とするArgoCDを同じClusterで管理する場合、ArgoCDはNamespace単位でテナント分割できない。

ArgoCDのコンポーネント (特に、application-controller、argocd-server) には、ClusterスコープなKubernetesリソース (例:ClusterRoleの認可スコープを紐づける) が必要である。

そのため、NamespaceごとにArgoCDのコンポーネントを分割したとしても、argocd-serverが異なるNamespaceのapplication-controllerの処理結果を取得してしまい、想定外のエラーが起こる。

そこで、異なるCluster用のArgoCDを単一のClusterで管理する場合、以下方法でマルチテナントを実現する。


AppProjectを使用する場合

単一Cluster上に複数のAppProjectを作成し、これを単位としてArgoCDを作成する。

各テナントは、ArgoCDを共有する。

この場合、レプリカ数やCPU数を増やすことにより、並列処理数を増やす必要がある。


仮想Cluster単位の場合

単一Cluster内に仮想Cluster (例:vcluster) を構築し、これを単位としてArgoCDを作成する。

各テナントは、ArgoCDを共有しない。


実Cluster単位の場合

テナントごとに異なる実Clusterを作成し、これを単位としてArgoCDを作成する。

各テナントは、ArgoCDを共有しない。


16. アクセスを制御する

ローカルマシン → (アクセス制御) → ArgoCD の部分

ローカルマシン
⬇︎
(アクセス制御)
⬇︎
ArgoCD
⬇︎
(アクセス制御)
⬇︎
Cluster
  • ArgoCDのダウンストリームのALBにWAFを紐づけ、特定のIPアドレス以外を 403ステータス (認可エラー) にする。
  • ArgoCDのログインにSSOを使用し、利用者以外を 401ステータス (認証エラー) にする

ArgoCD → (アクセス制御) → Cluster の部分

ローカルマシン
⬇︎
(アクセス制御)
⬇︎
ArgoCD
⬇︎
(アクセス制御)
⬇︎
Cluster
  • policy.csvファイルでArgoCD上の認可スコープを定義し、 403 (認可エラー) にする。 ただし、SSOが成功すればArgoCDの閲覧は可能とする。
  • Cluster側でArgoCDの送信元IPアドレス (AWSならNAT Gateway) を許可し、特定のArgoCD以外を 403 (認可エラー) にする。
  • EKSクラスターのARNを登録しない場合は、404にする。 (これは、ArgoCDがcluster 'https://*****.gr7.ap-northeast-1.eks.amazonaws.com' has not been configuredを返却してくれる)