ApplicationSet 컨트롤러가 `Application` 리소스를 수정하는 것을 제어

ApplicationSet 컨트롤러가 Application 리소스를 수정하는 것을 제어 (Controlling if/when the ApplicationSet controller modifies Application resources)

ApplicationSet 컨트롤러는 생성된 Application에 변경을 가하는 것을 제한하는 여러 설정을 지원해요. 예를 들어 컨트롤러가 하위 Application을 삭제하지 못하게 할 수 있어요. dry-run, --policy(create-only/create-update/create-delete/sync), ignoreApplicationDifferences, preserveResourcesOnDeletion, preservedFields 등으로 Application과 그 클러스터 리소스에 변경이 언제·어떻게 가해질지 제어할 수 있어요.

출처: 문서

본문

ApplicationSet 컨트롤러는 생성된 Application에 변경을 가하는 능력을 제한하는 여러 설정을 지원해요. 예를 들어 컨트롤러가 하위 Application을 삭제하지 못하게 하는 것처럼요.

이 설정들은 Application과 그에 대응하는 클러스터 리소스(Deployments, Services 등)에 변경이 언제, 어떻게 가해지는지 제어할 수 있게 해요.

다음은 ApplicationSet 컨트롤러의 리소스 처리 동작을 바꾸기 위해 수정할 수 있는 컨트롤러 설정 중 일부예요.

Dry run: ApplicationSet이 모든 Application 생성·수정·삭제를 못 하게 하기

ApplicationSet 컨트롤러가 어떤 Application 리소스도 생성·수정·삭제하지 못하게 하려면 dry-run 모드를 활성화할 수 있어요. 이는 본질적으로 컨트롤러를 "읽기 전용(read only)" 모드로 전환해요. Reconcile 루프는 실행되지만 어떤 리소스도 수정되지 않아요.

dry-run을 활성화하려면 ApplicationSet Deployment의 컨테이너 시작 파라미터에 --dryrun true를 추가하세요.

이 파라미터를 컨트롤러에 추가하는 자세한 단계는 아래 'ApplicationSet 컨테이너 파라미터 수정 방법'을 참고하세요.

관리 Application 수정 정책 (Managed Applications modification Policies)

ApplicationSet 컨트롤러는 시작 시(컨트롤러 Deployment 컨테이너 안에서) 지정되는 --policy 파라미터를 지원하며, 이것은 관리되는 Argo CD Application 리소스에 어떤 유형의 수정을 가할지 제한해요.

--policy 파라미터는 sync, create-only, create-delete, create-update 네 가지 값을 받아요. (sync가 기본값이며 --policy 파라미터를 지정하지 않으면 사용돼요. 나머지 정책은 아래 설명.)

이 정책을 ApplicationSet마다 설정하는 것도 가능해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  # (...)
  syncPolicy:
    applicationsSync: create-only # create-update, create-delete sync
  • 정책 create-only: ApplicationSet 컨트롤러가 Application을 수정하거나 삭제하지 못하게 해요. 경고: ApplicationSet을 삭제할 때 Application 컨트롤러가 ownerReferences에 따라 Application을 삭제하는 것을 막지는 않아요.
  • 정책 create-update: ApplicationSet 컨트롤러가 Application을 삭제하지 못하게 해요. 업데이트는 허용돼요. 경고: ApplicationSet을 삭제할 때 Application 컨트롤러가 ownerReferences에 따라 Application을 삭제하는 것을 막지는 않아요.
  • 정책 create-delete: ApplicationSet 컨트롤러가 Application을 수정하지 못하게 해요. 삭제는 허용돼요.
  • 정책 sync: 생성, 업데이트, 삭제 모두 허용돼요.

컨트롤러 파라미터 --policy가 설정되면 applicationsSync 필드보다 우선해요. 변수 ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_POLICY_OVERRIDE를 argocd-cmd-params-cm applicationsetcontroller.enable.policy.override로 설정하거나 컨트롤러 파라미터 --enable-policy-override로 직접 설정(기본값 false)해 ApplicationSet별 sync 정책을 허용할 수 있어요.

정책 - create-only: ApplicationSet 컨트롤러가 Application을 수정·삭제하지 못하게 하기

ApplicationSet 컨트롤러가 Application 리소스를 생성하도록 허용하되, 삭제나 Application 필드 수정 같은 추가 변경은 막으려면 ApplicationSet 컨트롤러에 이 파라미터를 추가하세요.

경고: "deletion"은 생성된 Application을 이전과 이후로 비교한 결과 존재하지 않게 된 Application의 경우를 나타내요. ownerReferences에 따라 ApplicationSet으로 Application이 삭제되는 경우는 나타내지 않아요. ApplicationSet 삭제 시 Application 컨트롤러가 Application을 삭제하지 못하게 하는 방법을 참고하세요.

--policy create-only

ApplicationSet 레벨에서:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  # (...)
  syncPolicy:
    applicationsSync: create-only

정책 - create-update: ApplicationSet 컨트롤러가 Application을 삭제하지 못하게 하기

ApplicationSet 컨트롤러가 Application 리소스를 생성·수정하도록 허용하되, Application 삭제는 막으려면 ApplicationSet 컨트롤러 Deployment에 다음 파라미터를 추가하세요.

경고: "deletion"은 생성된 Application을 이전과 이후로 비교한 결과 존재하지 않게 된 Application의 경우를 나타내요. ownerReferences에 따라 ApplicationSet으로 Application이 삭제되는 경우는 나타내지 않아요. ApplicationSet 삭제 시 Application 컨트롤러가 Application을 삭제하지 못하게 하는 방법을 참고하세요.

--policy create-update

이것은 컨트롤러가 생성한 Application의 삭제에 대한 추가 보호를 원하는 사용자에게 유용할 수 있어요.

ApplicationSet 레벨에서:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  # (...)
  syncPolicy:
    applicationsSync: create-update

ApplicationSet 삭제 시 Application 컨트롤러가 Application을 삭제하지 못하게 하는 방법 (How to prevent Application controller from deleting Applications when deleting ApplicationSet)

기본적으로 create-onlycreate-update 정책은 ApplicationSet 삭제 시 Application 삭제를 막는 데 효과적이지 않아요. 그런 경우 삭제를 막으려면 ApplicationSet에 finalizer를 설정하고 background 계단식 삭제(cascading deletion)를 사용해야 해요. foreground 계단식 삭제를 사용하면 애플리케이션 보존이 보장되지 않아요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  # (...)

Application의 특정 변경 무시 (Ignore certain changes to Applications)

ApplicationSet spec에는 ignoreApplicationDifferences 필드가 있어요. 이를 통해 Application을 비교할 때 ApplicationSet의 어떤 필드를 무시할지 지정할 수 있어요.

이 필드는 여러 ignore 규칙을 지원해요. 각 ignore 규칙은 무시할 jsonPointers 또는 jqPathExpressions 목록 중 하나를 지정할 수 있어요.

선택적으로 name을 지정해 특정 Application에 ignore 규칙을 적용하거나, name을 생략해 모든 Application에 ignore 규칙을 적용할 수 있어요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  ignoreApplicationDifferences:
    - jsonPointers:
        - /spec/source/targetRevision
    - name: some-app
      jqPathExpressions:
        - .spec.source.helm.values

auto-sync 임시 토글 허용 (Allow temporarily toggling auto-sync)

차이를 무시하는 가장 흔한 사용 사례 중 하나는 Application의 auto-sync를 임시로 토글하는 것을 허용하는 것이에요.

예를 들어 Application을 자동으로 sync하도록 구성된 ApplicationSet이 있다면, 특정 Application의 auto-sync를 임시로 비활성화하고 싶을 수 있어요. spec.syncPolicy.automated 필드에 대한 ignore 규칙을 추가하면 됩니다.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  ignoreApplicationDifferences:
    - jsonPointers:
        - /spec/syncPolicy

ignoreApplicationDifferences의 한계 (Limitations of ignoreApplicationDifferences)

ApplicationSet이 재조정될 때 컨트롤러는 ApplicationSet spec과 관리하는 각 Application의 spec을 비교해요. 차이가 있으면 컨트롤러는 Application을 ApplicationSet spec과 일치하도록 업데이트하는 패치를 생성해요.

생성된 패치는 MergePatch예요. MergePatch 문서에 따르면 "목록에 변경이 있을 때 기존 목록은 새 목록으로 완전히 교체됩니다."

이것은 무시되는 필드가 목록 안에 있을 때 ignoreApplicationDifferences의 효과를 제한해요. 예를 들어 소스가 여러 개인 Application이 있고 그 중 한 소스의 targetRevision 변경을 무시하고 싶다면, 다른 필드나 다른 소스의 변경은 sources 목록 전체를 교체하게 하고 targetRevision 필드가 ApplicationSet에 정의된 값으로 재설정돼요.

예를 들어 다음 ApplicationSet을 생각해 보세요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  ignoreApplicationDifferences:
    - jqPathExpressions:
        - .spec.sources[] | select(.repoURL == "https://git.example.com/org/repo1").targetRevision
  template:
    spec:
      sources:
      - repoURL: https://git.example.com/org/repo1
        targetRevision: main
      - repoURL: https://git.example.com/org/repo2
        targetRevision: main

repo1 소스의 targetRevision은 자유롭게 바꿀 수 있고, ApplicationSet 컨트롤러는 그 변경을 덮어쓰지 않아요.

apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  sources:
  - repoURL: https://git.example.com/org/repo1
    targetRevision: fix/bug-123
  - repoURL: https://git.example.com/org/repo2
    targetRevision: main

하지만 repo2 소스의 targetRevision을 바꾸면 ApplicationSet 컨트롤러가 sources 필드 전체를 덮어써요.

apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  sources:
  - repoURL: https://git.example.com/org/repo1
    targetRevision: main
  - repoURL: https://git.example.com/org/repo2
    targetRevision: main

참고ApplicationSet 컨트롤러의 미래 개선이 이 문제를 없앨 수도 있어요. 예를 들어 ref 필드가 merge key로 만들어져 ApplicationSet 컨트롤러가 MergePatch 대신 StrategicMergePatch를 생성·사용할 수 있게 될 수 있어요. 그러면 특정 소스를 ref로 지정하고, 그 소스의 한 필드 변경을 무시하며, 다른 소스의 변경이 무시된 필드를 덮어쓰지 않게 할 수 있어요.

부모 Application이 삭제될 때 Application의 하위 리소스 삭제 방지 (Prevent an Application's child resources from being deleted, when the parent Application is deleted)

기본적으로 Application 리소스가 ApplicationSet 컨트롤러에 의해 삭제되면 Application의 모든 하위 리소스(Application의 모든 Deployments, Services 등)도 함께 삭제돼요.

부모 Application이 삭제될 때 Application의 하위 리소스가 삭제되는 것을 막으려면 ApplicationSet의 syncPolicypreserveResourcesOnDeletion: true 필드를 추가하세요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  # (...)
  syncPolicy:
    preserveResourcesOnDeletion: true

preserveResourcesOnDeletion의 구체적인 동작과 ApplicationSet 컨트롤러 및 Argo CD 전반의 삭제에 대한 자세한 내용은 Application Deletion 페이지에서 찾을 수 있어요.

Application의 하위 리소스 수정 방지 (Prevent an Application's child resources from being modified)

ApplicationSet에 가해진 변경은 ApplicationSet이 관리하는 Application으로 전파되고, Argo CD가 Application 변경을 기본 클러스터 리소스로 전파해요(Argo CD Integration 참고).

Application 변경이 클러스터로 전파되는 것은 ApplicationSet template 필드에서 참조되는 자동 sync 설정이 관리해요.

  • spec.template.syncPolicy.automated: 활성화되면 Application 변경이 자동으로 클러스터의 클러스터 리소스로 전파돼요.
    • Application 리소스가 관리하는 클러스터 리소스 업데이트를 '일시 중지'하려면 ApplicationSet 템플릿에서 이것을 설정 해제하세요.
  • spec.template.syncPolicy.automated.prune: 기본적으로 Automated sync는 Argo CD가 리소스가 더 이상 Git에 정의되지 않았음을 감지하면 리소스를 삭제하지 않아요.
    • 추가 안전을 위해 이것을 false로 설정해 백킹 Git 저장소의 예상치 못한 변경이 클러스터 리소스에 영향을 주는 것을 방지할 수 있어요.

ApplicationSet 컨테이너 시작 파라미터 수정 방법 (How to modify ApplicationSet container launch parameters)

위 설정들을 활성화하기 위해 ApplicationSet 컨테이너 파라미터를 수정하는 방법은 몇 가지가 있어요.

A) kubectl edit로 클러스터의 deployment 수정

클러스터의 applicationset-controller Deployment 리소스를 편집하세요.

kubectl edit deployment/argocd-applicationset-controller -n argocd

.spec.template.spec.containers[0].command 필드를 찾아 필요한 파라미터를 추가하세요.

spec:
    # (...)
  template:
    # (...)
    spec:
      containers:
      - command:
        - entrypoint.sh
        - argocd-applicationset-controller
        # Insert new parameters here, for example:
        # --policy create-only
    # (...)

저장하고 편집기를 종료하세요. 업데이트된 파라미터를 담은 새 Pod가 시작될 때까지 기다리세요.

또는, B) install.yaml 매니페스트 편집 (ApplicationSet 설치용)

클러스터 리소스를 직접 편집하는 대신 ApplicationSet 컨트롤러를 설치하는 데 사용되는 설치 YAML을 수정할 수도 있어요.

적용 대상: applicationset 버전 0.4.0 미만.

# Clone the repository

git clone https://github.com/argoproj/applicationset

# Checkout the version that corresponds to the one you have installed.
git checkout "(version of applicationset)"
# example: git checkout "0.1.0"

cd applicationset/manifests

# open 'install.yaml' in a text editor, make the same modifications to Deployment 
# as described in the previous section.

# Apply the change to the cluster
kubectl apply -n argocd --server-side --force-conflicts -f install.yaml

Application의 어노테이션·라벨에 가해진 변경 보존 (Preserving changes made to an Applications annotations and labels)

참고 — 같은 동작은 위에서 설명한 ignoreApplicationDifferences 기능으로 앱별로 달성할 수 있어요. 하지만 preserved fields는 전역으로 구성할 수 있는데, 이 기능은 ignoreApplicationDifferences에는 아직 없어요.

Kubernetes에서는 상태를 어노테이션에 저장하는 것이 일반적인 관행이며, operator는 종종 이를 활용해요. 이를 허용하기 위해 ApplicationSet이 재조정할 때 보존해야 할 어노테이션 목록을 구성할 수 있어요.

예를 들어 ApplicationSet으로 만든 Application이 있는데, ApplicationSet 리소스에는 존재하지 않는 커스텀 어노테이션과 라벨이 (Application에) 추가되었다고 상상해 봐요.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  # This annotation and label exists only on this Application, and not in 
  # the parent ApplicationSet template:
  annotations: 
    my-custom-annotation: some-value
  labels:
    my-custom-label: some-value
spec:
  # (...)

이 어노테이션과 라벨을 보존하려면 ApplicationSetpreservedFields 속성을 다음과 같이 사용할 수 있어요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
  # (...)
  preservedFields:
    annotations: ["my-custom-annotation"]
    labels: ["my-custom-label"]

ApplicationSet 컨트롤러는 이 어노테이션과 라벨을 ApplicationSet 자체의 metadata에 정의되지 않았음에도 재조정할 때 그대로 두어요.

기본적으로 Argo CD notifications와 Argo CD refresh 타입 어노테이션도 보존돼요.

참고ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_ANNOTATIONSARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS에 각각 쉼표 구분 목록을 전달해 컨트롤러에 대한 전역 보존 필드도 설정할 수 있어요.

예상치 못한 Application 변경 디버깅 (Debugging unexpected changes to Applications)

ApplicationSet 컨트롤러가 애플리케이션에 변경을 가하면 debug 레벨에서 패치를 로그해요. 이 로그를 보려면 argocd 네임스페이스의 argocd-cmd-params-cm ConfigMap에서 로그 레벨을 debug로 설정하세요.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  applicationsetcontroller.log.level: debug

변경 미리보기 (Previewing changes)

ApplicationSet 컨트롤러가 Application에 가할 변경을 미리 보려면 AppSet을 dry-run 모드로 생성할 수 있어요. 이는 AppSet이 이미 존재하든 아니든 동작해요.

argocd appset create --dry-run ./appset.yaml -o json | jq -r '.status.resources[].name'

dry-run은 반환된 ApplicationSet의 status에 주어진 구성으로 관리될 Application들로 채워요. 기존 Application과 비교해 무엇이 바뀔지 볼 수 있어요.

더 알아보기 (Learn more)