Argo CDのApplicationSetは、1つの定義から複数のApplicationを自動で作るリソースです。クラスター3つにアプリ10個なら、手書きのApplicationは30本。ApplicationSetならジェネレーターとテンプレート1組で済みます。この記事では、List・Cluster・Git・Matrix・Mergeの各ジェネレーターの書き方を、Argo CD 3.5系(2026年10月時点の最新安定版はv3.5.5)の公式ドキュメントに沿ってYAML付きで示し、一括削除を防ぐ設定と段階同期、projectの権限の穴まで扱います。
まとめ:ApplicationSetのジェネレーター選びと事故を防ぐ3つの設定
ジェネレーターは、展開先の数がどこで決まるかで選びます。環境が固定ならList、Argo CDに登録したクラスターの数で決まるならCluster、Gitのディレクトリやファイルの数で決まるならGitです。「全クラスター×全アドオン」のように2つの軸を掛け合わせる場合はMatrix、一部のクラスターだけ値を変えたい場合はMergeを使います。
書き始める前に goTemplate: true と goTemplateOptions: ["missingkey=error"] を付けます。事故になりやすいのは削除で、ApplicationSetを消すと配下のDeploymentやServiceまで消えます。本番では preserveResourcesOnDeletion: true を入れ、projectは固定値で書いてください。
ApplicationSetがテンプレートからApplicationを生成する仕組み
Argo CD自体の仕組みとインストールはArgoCDとは?GitOpsの仕組みとインストール・Sync設定をコード付きで解説で扱いました。ここではApplicationSetコントローラーの動作を押さえます。
ジェネレーターの出力1件がApplication1本になる最小のYAML
ApplicationSetは generators と template の2つの部品でできています。ジェネレーターがパラメータの組を出し、コントローラーが組ごとにtemplateへ値を埋めてApplicationを作る流れです。List generatorの公式ページの例を、2環境に広げて書くと次のようになります。
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- list:
elements:
- cluster: dev
url: https://kubernetes.default.svc
- cluster: prod
url: https://prod-api.example.com:6443
template:
metadata:
name: '{{.cluster}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
targetRevision: HEAD
path: guestbook
destination:
server: '{{.url}}'
namespace: guestbook
適用すると dev-guestbook と prod-guestbook の2本が生成されます。elementsの値は文字列に限られ、展開先のクラスターはArgo CDに登録済みであることが前提です。
goTemplateとmissingkey=errorを最初から有効にすべき理由
Templateの公式ページは、ApplicationSetが使ってきたfasttemplateを、いずれGo Templateへ移行すると書いています。goTemplate: true を付けると、{{.path.basename}} のようなドット記法と、env など一部を除くSprig関数が使えるようになります。
Go Templateのページが推奨する設定は goTemplateOptions: ["missingkey=error"] です。これがないと、綴りを間違えたパラメータは空文字になり、-guestbook のような名前のApplicationが黙って作られます。後から有効にするとパラメータ名の書き方が変わるため、新規のApplicationSetでは最初から2行とも入れてください。
ListとClusterジェネレーターで複数クラスタへ同じアプリを配る設定
公式のGeneratorsの一覧には9種類が並びますが、複数クラスタへの展開で最初に使うのはListとClusterの2つです。違いは、展開先の一覧をYAMLに書くか、Argo CDに登録されたクラスターから読むかにあります。
List generatorで環境ごとのrevisionやnamespaceを渡す書き方
Listの要素には、cluster と url 以外の任意のキーも書けます。環境ごとにブランチや名前空間を変えたいなら、要素に足してtemplateで参照すれば済みます。
generators:
- list:
elements:
- env: stg
url: https://stg-api.example.com:6443
revision: develop
- env: prod
url: https://prod-api.example.com:6443
revision: release
template:
metadata:
name: 'shop-api-{{.env}}'
spec:
project: shop
source:
repoURL: https://git.example.com/org/shop-api-deploy.git
targetRevision: '{{.revision}}'
path: 'overlays/{{.env}}'
destination:
server: '{{.url}}'
namespace: 'shop-{{.env}}'
環境の数が2〜5程度で、増減が年に数回しかないなら、この形がいちばん読みやすい構成です。path で環境別のoverlaysを指す設計はKustomizeとは?base・overlaysの仕組みとHelmとの違い・導入判断を実装者目線で解説と組み合わせると無理がありません。
Cluster generatorのselectorで本番クラスターだけに配る設定
Argo CDは、登録したクラスターをラベル argocd.argoproj.io/secret-type: cluster 付きのSecretとして保存する仕組みです。Cluster generatorはこのSecretを読み、name・nameNormalized・server・project・metadata.labels.<key> などをパラメータとして渡します。Secretに付けたラベルで絞り込めば、本番クラスターだけを対象にできます。
apiVersion: v1
kind: Secret
metadata:
name: cluster-prod-tokyo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: cluster
env: prod
stringData:
name: prod-tokyo
server: https://prod-api.example.com:6443
---
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: monitoring-agent
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- clusters:
selector:
matchLabels:
env: prod
values:
revision: stable
template:
metadata:
name: '{{.nameNormalized}}-monitoring-agent'
spec:
project: platform
source:
repoURL: https://git.example.com/org/platform-addons.git
targetRevision: '{{.values.revision}}'
path: monitoring-agent
destination:
server: '{{.server}}'
namespace: monitoring
Secretの認証情報(config)は、この例では省略した状態です。values の値はtemplateから values. 付きの名前で参照します。新しいクラスターに env: prod を付けて登録すれば、ApplicationSetを書き換えずにエージェントが入ります。
Argo CDが動くクラスター自身(既定の in-cluster)にはSecretが無く、secret-type ラベルで選ぶselectorには一致しません。対象にしたいなら argocd cluster add <context> --in-cluster などでSecretを作ります。
Gitジェネレーターでディレクトリを足すだけでアプリを増やす構成
Git generatorは、リポジトリの中身からパラメータを作ります。ディレクトリの数を数えるdirectoriesと、設定ファイルの中身を読むfilesの2種類があります。
directoriesとexcludeでクラスターアドオンを一括展開する例
アドオンを1ディレクトリずつ置いたリポジトリを想定します。addons/* に一致したディレクトリごとにApplicationが1本でき、ディレクトリを追加してpushすれば新しいアプリが同期されます。
generators:
- git:
repoURL: https://git.example.com/org/platform-addons.git
revision: HEAD
directories:
- path: addons/*
- path: addons/experimental-*
exclude: true
template:
metadata:
name: '{{.path.basenameNormalized}}'
spec:
project: platform
source:
repoURL: https://git.example.com/org/platform-addons.git
targetRevision: HEAD
path: '{{.path.path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{.path.basenameNormalized}}'
syncPolicy:
syncOptions:
- CreateNamespace=true
excludeは記述の順番に関係なくincludeより優先されるため、addons/* をexcludeにして一部だけincludeに戻す書き方は効きません。path.basename はディレクトリ名そのままなので、アンダースコアを含む名前があるなら basenameNormalized を使ってください。
config.jsonを読むGit file generatorと3分間隔の検知
filesは、一致したJSONやYAMLの中身をフラットなキーに展開してパラメータにします。クラスターごとに cluster-config/prod/config.json を置く形がよく使われます。
{
"env": "prod",
"cluster": {
"name": "prod-tokyo",
"address": "https://prod-api.example.com:6443"
},
"replicas": "4"
}
このファイルからは env・cluster.name・cluster.address・replicas が生まれ、templateで {{.cluster.address}} のように参照できます。変更を拾う間隔は既定で3分で、requeueAfterSeconds による変更が可能です。待ち時間をなくすなら、APIサーバーとは別のApplicationSet用webhook(/api/webhook)をGitHubやGitLabに登録します。ClusterIPのServiceなので、専用のIngressが必要です。
MatrixとMergeでクラスター×アプリの直積と環境別の上書きを組む実装
「どのクラスターに」「どのアプリを」の2軸を掛け合わせるのがMatrix、一部だけ値を差し替えるのがMergeです。
Git directory×Clusterの直積で全クラスターに全アドオンを入れる例
Matrix generatorは、2つの子ジェネレーターの出力をすべて組み合わせます。アドオンが2つ、クラスターが2つなら4本のApplicationができます。
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: addons-all-clusters
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- matrix:
generators:
- git:
repoURL: https://git.example.com/org/platform-addons.git
revision: HEAD
directories:
- path: addons/*
- clusters:
selector:
matchLabels:
argocd.argoproj.io/secret-type: cluster
template:
metadata:
name: '{{.path.basenameNormalized}}-{{.nameNormalized}}'
spec:
project: platform
source:
repoURL: https://git.example.com/org/platform-addons.git
targetRevision: HEAD
path: '{{.path.path}}'
destination:
server: '{{.server}}'
namespace: '{{.path.basenameNormalized}}'
Application名には、両方の子のパラメータを必ず含めます。片方だけだと名前が衝突し、生成に失敗するためです。この例のようにGitの組を先に置けば、後ろのClusterのselectorで {{.path.basename}} を参照できます。たとえばディレクトリ名と同じラベルを持つクラスターだけに配る、といった絞り込みです。
子ジェネレーター2つ・ネスト1段など公式が定めるMatrixの制約
英語の解説記事には「3つ以上も組める」と書くものがありますが、v3.5.5時点の公式ドキュメントが示す制約は次のとおりです。
- Matrixの子ジェネレーターは2つまで
- MatrixやMergeの入れ子は1段まで(3段目は無効)
- 配列の1要素に書けるジェネレーターは1つだけ
- 両方の子がGitジェネレーターなら、片方以上に
pathParamPrefixが必要 - パラメータを使う子は、それを作る子より後ろに置く
- 子ジェネレーターに書いた
templateの上書きは処理されない
3軸目(たとえばリージョン)は、子にもう1つMatrixを入れる1段の入れ子で表します。配列の1要素に2つ書く誤りはKubernetesのAPI検証を通ってしまい、コントローラーのログで初めて分かります。
mergeKeysで特定クラスターの値だけ差し替えるMerge generator
Merge generatorは、最初の子を土台にし、mergeKeys が一致する組だけを後続の子の値で上書きします。全クラスターに既定値を配り、1台だけ設定を変える用途に向きます。
generators:
- merge:
mergeKeys:
- server
generators:
- clusters:
values:
redis: 'false'
- list:
elements:
- server: https://prod-api.example.com:6443
values.redis: 'true'
この例では、prodのクラスターだけ values.redis が 'true' になります。goTemplate: true のときは values.selector のような入れ子のキーをmergeKeysにできません。この点は公式ページの制約欄にも書かれています。
templatePatchと削除・同期の制御で生成済みApplicationの事故を防ぐ
ApplicationSetは更新も削除も自動で行うため、Gitの1コミットで本番のアプリがまとめて消えることもあります。
templatePatchで環境別にautomatedとvalueFilesを切替
templateで値を埋められるのは文字列のフィールドだけです。「devだけ自動同期」のように真偽値やリストを条件で変えるなら templatePatch を使います。
generators:
- list:
elements:
- env: dev
autoSync: true
valueFiles: ["values.yaml", "values-dev.yaml"]
- env: prod
autoSync: false
valueFiles: ["values.yaml", "values-prod.yaml"]
template:
metadata:
name: 'shop-web-{{.env}}'
spec:
project: shop
source:
repoURL: https://git.example.com/org/shop-web-chart.git
targetRevision: HEAD
path: chart
destination:
server: https://kubernetes.default.svc
namespace: 'shop-{{.env}}'
templatePatch: |
spec:
source:
helm:
valueFiles:
{{- range $f := .valueFiles }}
- {{ $f }}
{{- end }}
{{- if .autoSync }}
syncPolicy:
automated:
prune: true
{{- end }}
templatePatchは goTemplate: true のときだけ動き、spec.project は変更できません。中身が空の spec: を書くと既存のフィールドまで消えます。外部入力が入るパラメータは toJson を通すよう公式は注意しています。Helmの値の渡し方はArgoCDでHelm chartを使う方法:valueFiles・マルチソースの設定とargo-cd chartでのインストールで詳しく扱いました。
preserveResourcesOnDeletionで一括削除を止める設定
生成されたApplicationには親ApplicationSetへのownerReferenceが付きます。ApplicationSetを消すとApplicationが消え、削除用finalizerによってクラスター上のリソースまで消えます。Gitのディレクトリを誤って消した場合も同じです。
spec:
syncPolicy:
preserveResourcesOnDeletion: true
applicationsSync: create-update
preserveResourcesOnDeletion: true は削除用finalizerを付けない設定で、Applicationが消えてもDeploymentやServiceは残ります。リソース変更の制御のページによると、applicationsSync は許す操作を create-only・create-update・create-delete・sync(既定)から選ぶ項目で、create-update なら生成対象から外れたApplicationを消しません。コントローラーの起動引数 --policy があればそちらが優先され、ApplicationSet単位の指定には ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_POLICY_OVERRIDE での許可が要ります。
生成されるApplicationの一覧は、変更前にドライランで確かめられます。
argocd appset create --dry-run ./appset.yaml -o json | jq -r '.status.resources[].name'
ApplicationSetだけ消してアプリを残すなら kubectl delete applicationset <名前> --cascade=orphan を使います。Application側のfinalizerは残るので、後でApplicationを消せば配下のリソースも消えます。
RollingSyncでdevからprodへ段階的に同期する設定
全環境のApplicationを同時に更新する既定の動きを、ラベルの順に段階的に進める機能がProgressive Syncsです。v3.3.0からBetaの扱いで、コントローラーに --enable-progressive-syncs を渡すか、argocd-cmd-params-cm で applicationsetcontroller.enable.progressive.syncs: "true" を設定して有効にします。
spec:
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: env
operator: In
values: ["dev"]
- matchExpressions:
- key: env
operator: In
values: ["prod"]
maxUpdate: 25%
template:
metadata:
name: 'shop-web-{{.env}}'
labels:
env: '{{.env}}'
この設定では、devのApplicationがすべてHealthyになってから、prodを25%ずつ同期します。maxUpdate の既定は100%です。RollingSyncは生成されるApplicationの自動同期を強制的に無効にします。どのstepにも一致しないApplicationは同期されないため、templateの labels は全環境で埋まるようにしてください。
ApplicationSetを採用すべき規模と見送るべき場面、権限設計の基準
最後に、受託でGitOps基盤を組むときにApplicationSetをどこまで使うかの判断を言い切ります。
Gitへのpush権限がproject昇格につながるテンプレート化したproject
ApplicationSetのセキュリティのページは、ApplicationSetの作成・更新・削除を管理者だけに許すよう求めています。ApplicationSetは任意のprojectにApplicationを作れるからです。Argo CD自身のRBAC設定まで触れる default projectを選ばれると、Argo CDの乗っ取りにつながります。
特に危ないのは、project: '{{.path.basename}}' のようにprojectをテンプレートで埋める構成です。Gitジェネレーターの参照先にpushできる人が、権限の広いprojectのApplicationを作れてしまいます。projectは固定値で書くか、参照先リポジトリのマージに管理者の承認を必須にしてください。2026年10月にはArgo CD本体のCritical脆弱性も複数公表されており、経緯はArgo CDの脆弱性一覧と対処にまとめています。
手書きApplicationで足りる規模とApplicationSetへ切り替える目安
クラスター1つにアプリが数本、環境もdevとprodだけなら、ApplicationSetは使いません。手書きのほうが設定の出どころを追いやすく、テンプレートの1行で全環境が変わる性質は小規模では事故の元になります。
切り替えの目安は、同じ形のApplicationが10本を超えたときか、クラスターの追加・撤去が四半期に1回以上起きるときです。まずはListかClusterの単一ジェネレーターで始め、Matrixはアドオンとクラスターの両方が増え続けると分かってから入れれば足ります。Gitを正とする運用の前提はGitOpsとは:4原則とPush型との違い、Argo CD・Fluxの最小構成YAMLで整理しました。
複数クラスタへの展開設計や、既存のデプロイ手順をArgo CDとApplicationSetへ移す計画を相談したい場合は、DevOps・CI/CD導入支援で設計から運用の引き継ぎまで対応しています。
よくある質問
ApplicationSetを書き始めたときに出やすい疑問に、公式ドキュメントの記述をもとに答えます。
ApplicationSetとApp of Appsはどう使い分けますか?
App of Appsは、子Applicationのマニフェストを人がGitに書き、親Applicationでまとめて同期する方式です。ApplicationSetは、クラスターの一覧やディレクトリ構成からApplicationそのものを生成します。アプリごとに設定が大きく違うならApp of Apps、同じ形のアプリを多数の環境へ配るならApplicationSetが向きます。
ApplicationSetを削除すると本番のアプリも消えますか?
既定の設定では、削除の対象です。生成されたApplicationには親へのownerReferenceが付いており、ApplicationSetを消すとApplicationも削除される仕組みです。Applicationの削除用finalizerにより、DeploymentやServiceなどクラスター上のリソースも削除されます。残したい場合は syncPolicy.preserveResourcesOnDeletion: true を設定するか、kubectl delete に --cascade=orphan を付けて消します。
Git generatorがディレクトリの追加を検知しないのはなぜですか?
Gitジェネレーターは既定で3分ごとにリポジトリを確認するので、追加直後はまだ拾われていない可能性があります。加えて、ファイル一覧の取得経路はrepo-serverのキャッシュ経由です。キャッシュの有効期限がポーリング間隔より長いと、さらに遅れます。すぐ反映させたいときは、ApplicationSetに argocd.argoproj.io/application-set-refresh 注釈を付けると、キャッシュを通さずに再取得されます。
Matrix generatorに3つのジェネレーターを並べられますか?
並べられません。v3.5.5時点の公式ドキュメントでは、Matrixの子ジェネレーターは2つまでです。3軸が必要なら、子の1つをMatrixにする1段の入れ子で表します。入れ子は1段までで、それ以上はApplicationSetを軸ごとに分けます。
ApplicationSetで生成したApplicationの自動同期だけ一時的に止められますか?
止められます。そのまま生成済みApplicationのsyncPolicyを手で書き換えても、ApplicationSetコントローラーによってtemplateの値へ戻される仕組みです。ApplicationSetに ignoreApplicationDifferences を設定し、jsonPointers に /spec/syncPolicy を指定すると、その差分を無視させられます。障害対応で一部の環境だけ自動同期を切りたい場合に使う設定です。
関連記事
- ArgoCDとは?GitOpsの仕組みとインストール・Sync設定をコード付きで解説:Argo CDの仕組みとApplication・Sync設定の基本
- ArgoCDでHelm chartを使う方法:valueFiles・マルチソースの設定とargo-cd chartでのインストール【3.5系】:templateから参照するHelm chartとvaluesの渡し方
- GitOpsとは:4原則とPush型との違い、Argo CD・Fluxの最小構成YAML:ApplicationSetを使う前提となる運用モデル
- Kustomizeとは?base・overlaysの仕組みとHelmとの違い・導入判断を実装者目線で解説:環境別overlaysをpathで指す構成の土台
- Argo CDの脆弱性一覧と対処:2026年10月のCritical4件と修正版3.5.4・3.4.10・3.3.15への更新手順:ApplicationSetを動かすArgo CD本体の版の確認
- Argo Workflowsとは?DAG・WorkflowTemplate・CronWorkflowのYAML実装とArgo CDとの役割分担:同じArgoプロジェクトでジョブ実行を担う製品
- ArgoCD MCPの使い方:mcp-for-argocdでAIエージェントにSync・ログ調査を任せる設定と権限設計【v0.9.0】:MCP経由の変更とApplicationSetテンプレートの関係