Zero-Downtime Migration: Moving Resources Between Argo CD ApplicationSets

Migrating resources from one ApplicationSet to another can be nerve-wracking. If you simply delete the old Set, Argo CD’s cascading deletion will wipe out your Applications and their underlying Kubernetes resources.

Here is a concise, step-by-step guide to performing this migration safely using the Orphan strategy.

The Concept: “Orphaning” your Apps

The goal is to delete the “parent” (ApplicationSet) while leaving the “children” (Applications) and “grandchildren” (K8s Resources) intact, allowing a new parent to take ownership.

Step 1: Apply the Safety Net

Before touching anything, you must tell the ApplicationSet controller not to clean up its resources upon deletion.

Add the preserveResourcesOnDeletion flag to your current (old) ApplicationSet:

spec:
  syncPolicy:
    preserveResourcesOnDeletion: true

Why? This ensures that when the ApplicationSet is deleted, the Application objects it generated remain in the cluster as standalone apps.

Step 2: Detach the Old Set

Now, delete the old ApplicationSet. You can do this via kubectl or by removing it from your GitOps repository.

kubectl delete applicationset <old-appset-name> -n argocd

Verification: Check your Argo CD UI. The applications should still be there, but they will no longer show the “Managed by ApplicationSet” icon. They are now “Orphans”.

Step 3: Prepare the New ApplicationSet

When creating the new ApplicationSet, ensure that the template generates Applications with the exact same name as the previous ones.

Pro-Tip: Use ServerSideApply to handle metadata conflicts (like labels or annotations) between the old and new managers:

spec:
  template:
    spec:
      syncPolicy:
        syncOptions:
          - ServerSideApply=true
  # Optional: Keep the safety net on the new set too
  syncPolicy:
    preserveResourcesOnDeletion: true 

Step 4: Adoption and Sync

Deploy your new ApplicationSet.

The Argo CD controller will:

  1. Identify that an Application with that name already exists.
  2. “Adopt” it under the new ApplicationSet.
  3. Perform a diff against the new Git source.

Action: Perform a Dry Run sync to ensure no unexpected changes occur during the handover:

argocd app sync <app-name> --dry-run

Summary Checklist

  1. [ ] Patch: Add preserveResourcesOnDeletion: true to the old Set.
  2. [ ] Delete: Remove the old ApplicationSet (Applications remain as orphans).
  3. [ ] Deploy: Create the new ApplicationSet with matching names.
  4. [ ] Validate: Verify the new Set has taken ownership and resources are Synced.

When to use this?

  • Renaming your ApplicationSets.
  • Moving from one Generator (e.g., List) to another (e.g., Git).
  • Refactoring your GitOps repository structure.