What to Leave Out of the Diff
In one sentence
An ignore rule is a device that removes specific fields from the synchronization verdict, and used broadly, it makes real drift disappear along with the noise, so you must confirm with your own eyes the lines that get erased with argocd admin settings resource-overrides ignore-differences before committing.
Why this device was needed
The ideal of GitOps is "what is written in the repository is the cluster". Reality is not like that. Values that cannot be written in the repository keep appearing in the cluster. The HPA changes spec.replicas, a sidecar-injection webhook inserts one more container, and a controller attaches annotations such as deployment.kubernetes.io/revision. You cannot write these values in the repository — the moment you write them, the value becomes fixed, and then the HPA or the webhook has no reason to exist.
That is why ignore rules exist. They are the place that declares "a difference in this field does not count as OutOfSync". The problem is that this device has a force that tilts only one way. If you ignore broadly, the screen goes quiet, and if you ignore narrowly, it stays noisy. The price of the quiet side comes months later.
How it works
You can write rules in two places. The global one is, in argocd-cm, resource.customizations.ignoreDifferences.<그룹>_<종류> (group, then kind), and the per-app one is the spec.ignoreDifferences list of the Application. The two are merged and applied — so you cannot hang a rule broadly on the global side and narrow it in the app. A rule in the narrowing direction must be put on the app side from the start.
Three kinds of lists can be written inside a rule block.
resource.customizations.ignoreDifferences.apps_Deployment: |
jsonPointers:
- /spec/replicas
jqPathExpressions:
- .spec.template.spec.containers[] | select(.name == "sidecar").image
managedFieldsManagers:
- kubectl
jsonPointers is a path that descends with slashes. It is simple, but an array can be pointed to only by position number, so if the container order changes, you end up ignoring the wrong element. jqPathExpressions can pick by a condition — as in the example above, you can point to "the image of the container named sidecar", which cannot be done stably with a pointer.
managedFieldsManagers is a different kind. It chooses what to ignore not by a field path but by the name of the manager that last wrote that field. It is a method that relies on the ownership record left by server-side apply, so you cannot calculate what will be removed from the resource YAML alone. That is why the preview command cannot render anything from this list alone.
There is one more handle with a similar name. ignoreResourceUpdates decides whether to wake up the reconcile loop. It is a performance handle that prevents the controller from recalculating the whole app every time a single annotation changes, and it does not change the synchronization verdict. They are often confused because the names are alike, but the purposes are entirely different.
What you see in the field
The scene you see most often is this. Ten apps are all yellow, and the cause is the HPA. Someone in a hurry puts into the global argocd-cm a single line that ignores apps_Deployment's whole /spec. The screen goes quiet and nobody looks at this line again. Months later someone changes an image tag by hand in production. Argo CD is still green. The system that calls the repository the source of truth started lying from that day, and there is no screen that tells you so.
The second is an ordering problem. To ignore a sidecar, you wrote /spec/template/spec/containers/1, and one day the webhook inserts the sidecar at the front. Now what is ignored is the application container. A rule like this gives no signal that it is wrong — it quietly behaves the opposite way.
So ignore rules need two habits. First, render before writing and look at the lines that get erased. Second, next to the line where you put the rule, write why that rule is needed. The only person who can delete a rule when its reason is gone is someone who knows that reason.
The limits of this lab environment
The lab Pod has no Argo CD controller. So you cannot see "I put in the rule and OutOfSync changed to Synced", and you cannot confirm with a preview which fields managedFieldsManagers actually filters out. Instead, the code that interprets the rule and erases fields is in the CLI, so you can see exactly the same result for which lines are removed from the comparison.
What you will do in the next lab
Using one Deployment as the material, you change the rules one at a time and render. You see for yourself the difference between a pointer and a jq expression, and confirm that if you ignore the whole /spec, even the image line disappears. You also honestly record how the manager-name rule and ignoreResourceUpdates look in the preview. Finally, you put a per-app rule on an Application, put it up on the kwok cluster, and make a table of "does this rule erase this string" and check it all at once.