github.com/argoproj/argo-cd/v2@v2.10.5/docs/user-guide/diffing.md (about)

     1  # Diffing Customization
     2  
     3  It is possible for an application to be `OutOfSync` even immediately after a successful Sync operation. Some reasons for this might be:
     4  
     5  * There is a bug in the manifest, where it contains extra/unknown fields from the actual K8s spec. These extra fields would get dropped when querying Kubernetes for the live state,
     6  resulting in an `OutOfSync` status indicating a missing field was detected.
     7  * The sync was performed (with pruning disabled), and there are resources which need to be deleted.
     8  * A controller or [mutating webhook](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook) is altering the object after it was
     9  submitted to Kubernetes in a manner which contradicts Git.
    10  * A Helm chart is using a template function such as [`randAlphaNum`](https://github.com/helm/charts/blob/master/stable/redis/templates/secret.yaml#L16),
    11  which generates different data every time `helm template` is invoked.
    12  * For Horizontal Pod Autoscaling (HPA) objects, the HPA controller is known to reorder `spec.metrics`
    13    in a specific order. See [kubernetes issue #74099](https://github.com/kubernetes/kubernetes/issues/74099).
    14    To work around this, you can order `spec.metrics` in Git in the same order that the controller
    15    prefers.
    16  
    17  In case it is impossible to fix the upstream issue, Argo CD allows you to optionally ignore differences of problematic resources.
    18  The diffing customization can be configured for single or multiple application resources or at a system level.
    19  
    20  ## Application Level Configuration
    21  
    22  Argo CD allows ignoring differences at a specific JSON path, using [RFC6902 JSON patches](https://tools.ietf.org/html/rfc6902) and [JQ path expressions](https://stedolan.github.io/jq/manual/#path(path_expression)). It is also possible to ignore differences from fields owned by specific managers defined in `metadata.managedFields` in live resources.
    23  
    24  The following sample application is configured to ignore differences in `spec.replicas` for all deployments:
    25  
    26  ```yaml
    27  spec:
    28    ignoreDifferences:
    29    - group: apps
    30      kind: Deployment
    31      jsonPointers:
    32      - /spec/replicas
    33  ```
    34  
    35  Note that the `group` field relates to the [Kubernetes API group](https://kubernetes.io/docs/reference/using-api/#api-groups) without the version.
    36  The above customization could be narrowed to a resource with the specified name and optional namespace:
    37  
    38  ```yaml
    39  spec:
    40    ignoreDifferences:
    41    - group: apps
    42      kind: Deployment
    43      name: guestbook
    44      namespace: default
    45      jsonPointers:
    46      - /spec/replicas
    47  ```
    48  
    49  To ignore elements of a list, you can use JQ path expressions to identify list items based on item content:
    50  ```yaml
    51  spec:
    52    ignoreDifferences:
    53    - group: apps
    54      kind: Deployment
    55      jqPathExpressions:
    56      - .spec.template.spec.initContainers[] | select(.name == "injected-init-container")
    57  ```
    58  
    59  To ignore fields owned by specific managers defined in your live resources:
    60  ```yaml
    61  spec:
    62    ignoreDifferences:
    63    - group: "*"
    64      kind: "*"
    65      managedFieldsManagers:
    66      - kube-controller-manager
    67  ```
    68  
    69  The above configuration will ignore differences from all fields owned by `kube-controller-manager` for all resources belonging to this application.
    70  
    71  If you have a slash `/` in your pointer path, you can use the `~1` character. For example:
    72  
    73  ```yaml
    74  spec:
    75    ignoreDifferences:
    76    - kind: Node
    77      jsonPointers: /metadata/labels/node-role.kubernetes.io~1worker
    78  ```
    79  
    80  ## System-Level Configuration
    81  
    82  The comparison of resources with well-known issues can be customized at a system level. Ignored differences can be configured for a specified group and kind
    83  in `resource.customizations` key of `argocd-cm` ConfigMap. Following is an example of a customization which ignores the `caBundle` field
    84  of a `MutatingWebhookConfiguration` webhooks:
    85  
    86  ```yaml
    87  data:
    88    resource.customizations.ignoreDifferences.admissionregistration.k8s.io_MutatingWebhookConfiguration: |
    89      jqPathExpressions:
    90      - '.webhooks[]?.clientConfig.caBundle'
    91  ```
    92  
    93  Resource customization can also be configured to ignore all differences made by a managedField.manager at the system level. The example below shows how to configure Argo CD to ignore changes made by `kube-controller-manager` in `Deployment` resources.
    94  
    95  ```yaml
    96  data:
    97    resource.customizations.ignoreDifferences.apps_Deployment: |
    98      managedFieldsManagers:
    99      - kube-controller-manager
   100  ```
   101  
   102  It is possible to configure ignoreDifferences to be applied to all resources in every Application managed by an Argo CD instance. In order to do so, resource customizations can be configured like in the example below:
   103  
   104  ```yaml
   105  data:
   106    resource.customizations.ignoreDifferences.all: |
   107      managedFieldsManagers:
   108      - kube-controller-manager
   109      jsonPointers:
   110      - /spec/replicas
   111  ```
   112  
   113  The `status` field of `CustomResourceDefinitions` is often stored in Git/Helm manifest and should be ignored during diffing. The `ignoreResourceStatusField` setting simplifies
   114  handling that edge case:
   115  
   116  ```yaml
   117  data:
   118    resource.compareoptions: |
   119      # disables status field diffing in specified resource types
   120      # 'crd' - CustomResourceDefinitions (default)
   121      # 'all' - all resources
   122      # 'none' - disabled
   123      ignoreResourceStatusField: crd
   124  ```
   125  
   126  By default `status` field is ignored during diffing for `CustomResourceDefinition` resource. The behavior can be extended to all resources using `all` value or disabled using `none`.
   127  
   128  ### Ignoring RBAC changes made by AggregateRoles
   129  
   130  If you are using [Aggregated ClusterRoles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles) and don't want Argo CD to detect the `rules` changes as drift, you can set `resource.compareoptions.ignoreAggregatedRoles: true`. Then Argo CD will no longer detect these changes as an event that requires syncing.
   131  
   132  ```yaml
   133  apiVersion: v1
   134  kind: ConfigMap
   135  metadata:
   136    name: argocd-cm
   137  data:
   138    resource.compareoptions: |
   139      # disables status field diffing in specified resource types
   140      ignoreAggregatedRoles: true
   141  ```
   142  
   143  ## Known Kubernetes types in CRDs (Resource limits, Volume mounts etc)
   144  
   145  Some CRDs are re-using data structures defined in the Kubernetes source base and therefore inheriting custom
   146  JSON/YAML marshaling. Custom marshalers might serialize CRDs in a slightly different format that causes false
   147  positives during drift detection.
   148  
   149  A typical example is the `argoproj.io/Rollout` CRD that re-using `core/v1/PodSpec` data structure. Pod resource requests
   150  might be reformatted by the custom marshaller of `IntOrString` data type:
   151  
   152  from:
   153  ```yaml
   154  resources:
   155    requests:
   156      cpu: 100m
   157  ```
   158  
   159  to:
   160  ```yaml
   161  resources:
   162    requests:
   163      cpu: 0.1
   164  ```
   165  
   166  The solution is to specify which CRDs fields are using built-in Kubernetes types in the `resource.customizations`
   167  section of `argocd-cm` ConfigMap:
   168  
   169  ```yaml
   170  apiVersion: v1
   171  kind: ConfigMap
   172  metadata:
   173    name: argocd-cm
   174    namespace: argocd
   175    labels:
   176      app.kubernetes.io/name: argocd-cm
   177      app.kubernetes.io/part-of: argocd
   178  data:
   179    resource.customizations.knownTypeFields.argoproj.io_Rollout: |
   180      - field: spec.template.spec
   181        type: core/v1/PodSpec
   182  ```
   183  
   184  The list of supported Kubernetes types is available in [diffing_known_types.txt](https://raw.githubusercontent.com/argoproj/argo-cd/master/util/argo/normalizers/diffing_known_types.txt) and additionally:
   185  
   186  * `core/Quantity`
   187  * `meta/v1/duration`