Argo CD ApplicationSetを削除するとpolicyによらずApplicationが削除される
この記事は Kubernetes Advent Calendar 2023 の 11日目の記事です。
12/11時点で最新のv2.9.3でも修正されていない(=どのバージョンでも発生する)、ApplicationSetに関する不具合について書いています。
ApplicationSet
ApplicationSetはApplicationを抽象化することで、Applicationの作成で楽ができるかもしれないカスタムリソースです。
-
spec.source
を抽象化-
source
を抽象化すると、単一のApplicationSetからリポジトリ内の複数の異なるファイルまたはディレクトリを指したApplicationを生み出したり、複数の異なるrepoURL
を指すApplicationを生み出すことができます。
-
-
spec.destination
を抽象化-
destination
を抽象化すると、単一のApplicationSetから複数のクラスター宛のApplicationを生み出すことができます。
-
基本はsource
とdestination
の抽象化で、アプローチの違いにより何種類ものgeneratorがあります。
ApplicationSet (Controller) のpolicy
applicationset-controllerには4種類のpolicy
のいずれかを設定することができます。
各policy
の説明は現時点(2023/12/11)のstable版ドキュメントに基づき和訳しています。
-
create-only
: ApplicationSet コントローラーがアプリケーションを変更または削除できないようにします。 -
create-update
: ApplicationSet コントローラーがアプリケーションを削除できないようにします。更新は許可されています。 -
create-delete
: ApplicationSet コントローラーがアプリケーションを変更できないようにします。削除は許可されています。 -
sync
: 更新と削除が許可されます。
policy
はコントローラーの引数で指定するか、argocd-cmd-params-cm
ConfigMapのapplicationsetcontroller.policy
で制定します。
公式Helmチャートではconfigs.params."applicationsetcontroller.policy"
valueで指定できます(デフォルトはsync
)。
「削除できない」policyでもApplicationが削除される?
policy
をcreate-only
かcreate-update
に設定したうえでApplicationSetを削除すると、そこから生まれたApplicationは削除されてしまいます。
現在のpolicyの意味
現在のpolicy
はあくまで 「ApplicationSetコントローラーが」 アプリケーションを削除するかどうかを制御できます。
「ApplicationSetコントローラーによる」Applicationの削除
ApplicationSetコントローラーがApplicationを削除するのは 「ApplicationSetの削除以外」 で必要ができたときに限られます。
Git generatorを使ったApplicationSetの例で考えます。
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
directories:
- path: applicationset/examples/git-generator-directory/cluster-addons/*
cluster-addonsを覗くと2つのディレクトリがあります。
そのため、このApplicationSetからは2つのApplicationが生み出され、それぞれのspec.source.path
は以下のようになります。
applicationset/examples/git-generator-directory/cluster-addons/argo-workflows
applicationset/examples/git-generator-directory/cluster-addons/prometheus-operator
ここから、以下のような場合にApplicationを削除する必要が生じます。
リポジトリが変更されたとき
prometheus-operator
ディレクトリを削除した場合、ApplicationSetからApplicationを生成しなおすとargo-workflows
ディレクトリに対応した1個だけになります。
一方クラスターにはprometheus-operator
ディレクトリに対応するApplicationが残っているため、ApplicationSetコントローラーはこれを削除することになります。
ApplicationSetが変更されたとき
prometheus-operator
ディレクトリを除外する条件をgeneratorに書き足した場合も、ApplicationSetからApplicationを生成しなおすとargo-workflows
ディレクトリに対応した1個だけになるため、Applicationの削除が起こります。
directories:
- path: applicationset/examples/git-generator-directory/cluster-addons/*
- path: applicationset/examples/git-generator-directory/cluster-addons/prometheus-operator
exclude: true
ApplicationSetを削除したとき、Applicationを削除しているのは誰?
Applicationコントローラーが削除しています。
ApplicationSetから生み出されたApplicationにはmetadata.ownerReferences
フィールドが書き込まれており、Kubernetesのガベージコレクションの仕組みにしたがって削除されます。
policy
はこれには影響がありません。
Applicationを残してApplicationSetを削除する方法
ownerReferences
を使ったガベージコレクションの仕組みに則っているため、削除リクエストのcascade
オプションを入力すればApplicationを残してApplicationSetを削除することが可能です。
kubectl delete appset foobar --cascade=orphan
とはいえ、ややこしい…
policy
によって制御される「削除」と制御されない「削除」があるということは、それぞれの削除が発生する経緯を紐解いていくとわかるのですが、ややこしく感じます(GitHubでissueを起票した時点では私も正確に理解していませんでした)。
結局、この動作は仕様ではなく不具合であると認定され、正しい動作は
「ApplicationSetの削除時も、policy
がcreate-only
/create-update
の場合はApplicationを削除しないようにする」であると定義されました。
policyの適用範囲をApplicationSetの削除にも広げる
正しい動作をさせるためには、ApplicationSetの削除時にpolicy
を参照し、create-only
またはcreate-update
の場合にはApplicationからownerReferences
フィールドを削除する必要があります。
以下のプルリクエストでその修正を行いました。
Discussion