Argo CD doesn’t actually "exclude" resources from sync in the way you might think; it selectively applies them based on a declarative filter.

Let’s see it in action. Imagine you have a Deployment in your Git repository that you don’t want Argo CD to manage. You’d typically remove it from your manifest. But what if you want to keep it in Git, maybe for documentation or as a reference, but prevent Argo CD from touching it in the cluster? You can achieve this by adding an argocd.argoproj.io/compare-options annotation to the resource’s YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-unmanaged-deployment
  annotations:
    argocd.argoproj.io/compare-options: IgnoreExtraneous
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

When Argo CD runs a sync or detects drift, it will see this Deployment in Git and in the cluster. However, because of IgnoreExtraneous, it will effectively ignore any differences related to this specific resource during the comparison phase for sync purposes. It won’t try to create it if it’s missing in the cluster, nor will it try to update or delete it if it exists.

This mechanism is built around Argo CD’s reconciliation loop. Argo CD continuously compares the desired state (from Git) with the live state (in the cluster). When it finds resources that are not in the desired state, it tries to reconcile them. Annotations like IgnoreExtraneous or IgnoreDifferences modify how Argo CD performs this comparison and reconciliation.

The primary problem this solves is managing drift for resources that are externally managed or that you want to keep in Git but not have Argo CD actively control. For instance, you might have a Namespace resource that you create manually or via a different tool, but you want to keep its definition in your Git repository alongside your application manifests. You can then tell Argo CD to ignore changes to that Namespace resource.

Here’s the full mental model:

  1. Application Definition: Argo CD applications are defined by Git repositories.
  2. Resource Manifests: These repositories contain Kubernetes YAML manifests for your applications.
  3. Sync Process: When you sync an application, Argo CD fetches these manifests and compares them against the live state of resources in your target Kubernetes cluster.
  4. Reconciliation: If differences are found (e.g., a resource in Git is not in the cluster, or a resource in the cluster doesn’t match Git), Argo CD attempts to "reconcile" the cluster to match Git.
  5. Annotations as Directives: Argo CD respects specific annotations on Kubernetes resources. These annotations act as directives, telling Argo CD how to handle that particular resource during sync and drift detection.

The most common annotations for exclusion/ignoring are:

  • argocd.argoproj.io/compare-options: IgnoreExtraneous

    • What it does: Tells Argo CD to ignore this resource entirely for sync purposes. If the resource exists in Git but not the cluster, Argo CD won’t create it. If it exists in the cluster but not Git, Argo CD won’t delete it. If it exists in both and differs, Argo CD won’t attempt to reconcile the differences.
    • Use case: Useful for resources that are managed by other controllers or external processes, but you want their definition to remain in your Git repo.
  • argocd.argoproj.io/compare-options: IgnoreDifferences

    • What it does: Tells Argo CD to ignore specific fields within a resource. You combine this with a argocd.argoproj.io/compare-options list.
    • Use case: You want Argo CD to manage most of a resource but ignore certain dynamic fields (like status or specific annotations) that are expected to change outside of Git.
  • argocd.argoproj.io/sync-options: PruneLast

    • What it does: While not strictly an exclusion, this annotation ensures that if a resource is deleted from Git, Argo CD will delete it from the cluster last among all resources in the same manifest file. This can help prevent cascading deletions of dependent resources.

Let’s say you have a ConfigMap that’s automatically updated by an external process, and you want to keep it in Git but prevent Argo CD from overwriting it. You’d add IgnoreExtraneous to that ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-externally-managed-config
  annotations:
    argocd.argoproj.io/compare-options: IgnoreExtraneous
data:
  key: some-value-that-changes

With IgnoreExtraneous, if Argo CD sees this ConfigMap in Git and it exists in the cluster, it will simply not compare it for sync. If it’s in Git but not the cluster, it won’t be created. If it’s in the cluster but not Git, it won’t be deleted. It effectively takes the resource out of Argo CD’s direct management while keeping its definition version-controlled.

The subtle point most people miss is that IgnoreExtraneous doesn’t remove the resource from Argo CD’s awareness; it removes it from the sync and drift detection process. Argo CD still lists the resource in its UI and may report it as "OutOfSync" if its state differs from Git, but it won’t attempt to reconcile it. The primary benefit is maintaining version control over resources managed elsewhere, providing a single source of truth for definitions even if not for live state.

Once you’ve applied IgnoreExtraneous to a resource, the next thing you’ll likely encounter is needing to manage the lifecycle of resources that are still managed by Argo CD but have complex dependencies.

Want structured learning?

Take the full Argocd course →