Argo CD can be configured to ignore specific differences between the desired state in Git and the live state in the cluster, allowing you to manage certain resource attributes dynamically without triggering sync failures.

Let’s see this in action. Imagine you have a Kubernetes Deployment managed by Argo CD, and you want to ignore changes to the spec.template.metadata.annotations field because an external controller (like cert-manager) is adding annotations to your Pods.

Here’s a simplified deployment.yaml in your Git repository:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
      # This is where cert-manager might add annotations
      annotations:
        some-managed-annotation: "value"
    spec:
      containers:
      - name: main
        image: nginx:latest

When Argo CD syncs this, and cert-manager (or another controller) adds an annotation like cert-manager.io/cluster-issuer: "letsencrypt-prod" to the Pod template’s metadata, Argo CD will see this as a difference and report a sync error if automatic sync is enabled, or simply show a diff if manual sync is used.

To prevent this, you can tell Argo CD to ignore this specific field. You do this by modifying the Application manifest itself, adding an ignoreDifferences section.

Here’s how your Application manifest would look:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-username/your-repo.git
    targetRevision: HEAD
    path: path/to/your/app
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
  ignoreDifferences:
    - group: apps
      kind: Deployment
      name: my-app
      jsonPointers:
        - "/spec/template/metadata/annotations"

Let’s break down the ignoreDifferences section:

  • group: The API group of the resource. For Deployments, this is apps.
  • kind: The resource type, Deployment.
  • name: The specific name of the resource to apply this rule to, my-app. If you omit name, the rule applies to all resources of that kind and group.
  • jsonPointers: A list of JSON Pointers indicating the fields to ignore. /spec/template/metadata/annotations points directly to the annotations map within the Pod template.

How it works mechanically:

When Argo CD compares the live state of my-app in the default namespace with the desired state from Git, it will parse the ignoreDifferences rules. For any resource matching group: apps, kind: Deployment, and name: my-app, it will specifically exclude the fields specified by the jsonPointers from its diff calculation. If the only difference between Git and live is within an ignored field, Argo CD will consider the resource "synced" and healthy, even if the values don’t match.

You can ignore more than just annotations. For example, if you have a Service with a dynamically assigned clusterIP that you don’t want to track, you could add:

  ignoreDifferences:
    - group: "" # Core API group
      kind: Service
      name: my-service
      jsonPointers:
        - "/spec/clusterIP"

Or, to ignore all status fields across all resources:

  ignoreDifferences:
    - jsonPointers:
        - "/status"
      # group, kind, name omitted to apply globally

The jsonPointers are crucial. They follow the RFC 6901 standard for JSON Pointers. A leading / signifies the root of the document, and subsequent / characters denote nested fields. You can also use * as a wildcard for array elements or map keys if you want to ignore a pattern rather than a specific path, though this is less common for specific resource attributes.

The most surprising thing about ignoreDifferences is how granularly you can apply it. It’s not just about ignoring entire fields; you can ignore specific keys within a map or specific elements within an array if you know the exact JSON Pointer path. This allows for very precise control over what Argo CD considers drift. For instance, if you only wanted to ignore a specific annotation key, say cert-manager.io/cluster-issuer, you’d need to target the parent annotations map with the JSON Pointer /spec/template/metadata/annotations and then rely on the fact that cert-manager is the only external agent modifying it. If other agents also modified annotations, you might need a more sophisticated approach or accept that any annotation change will be ignored.

Understanding the exact JSON Pointer to the field you want to ignore is key. You can get this by examining the output of kubectl get <resource> <resource-name> -o json and tracing the path to the differing field.

Once you’ve applied ignoreDifferences, Argo CD will no longer flag these specific discrepancies, and your application will show as synchronized if all other tracked fields match.

The next challenge you’ll likely encounter is managing secrets that are injected into your cluster by external systems, and deciding whether or not to ignore their differences.

Want structured learning?

Take the full Argocd course →