Skip to content

Server-Side Apply prevents field deletion owned by other managers #23214

Description

@pjiang-dev

Checklist:

  • I've searched in the docs and FAQ for my answer: https://bit.ly/argocd-faq.
  • I've included steps to reproduce the bug.
  • I've pasted the output of argocd version.

Describe the bug

ArgoCD's server-side apply implementation cannot remove fields that were previously applied by client-side apply (kubectl apply) or other field managers. When migrating from client-side apply to server-side apply, removed fields remain in the resource indefinitely, even when they are no longer present in the desired manifest. This leads to resources that are inconsistent with their expected state.

The root cause is that server-side apply only manages fields that are explicitly specified in the applied manifest. Fields owned by other field managers (like kubectl with Update operation) persist even when they should be removed, because ArgoCD's field manager cannot take ownership of fields it doesn't explicitly apply.

This is the same issue described in kubernetes/kubernetes#99003

As the upstream issue has still been open for awhile and doesn't look like it will be resolved soon, we should implement a workaround solution for this case as this will be a common case if users applied resources using kubectl apply before managing with argocd. Or if users have other legacy controllers managing fields that they want to later remove.

To Reproduce

  1. Apply a manifest using client-side apply (kubectl apply):
cat <<EOF | kubectl -n default apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
data:
  key1: value1
  key2: value2
  legacy_field: should_be_removed
EOF
  1. Configure ArgoCD to manage this resource with server-side apply enabled. i.e add this file to Git and create an app that manages this file.
  2. Sync without ServerSideApply
  3. Observe in managed fields in argoCD. Since we applied using kubectl apply -f, the fields are owned by `manager: kubectl-client-side-apply
  managedFields:
    - apiVersion: v1
      fieldsType: FieldsV1
      fieldsV1:
        f:data:
          .: {}
          f:key1: {}
          f:key2: {}
          f:legacy_field: {}
        f:metadata:
          f:annotations: {}
      manager: kubectl-client-side-apply
      operation: Update
      time: '2025-05-30T20:29:26Z'
    - apiVersion: v1
      fieldsType: FieldsV1
      fieldsV1:
        f:metadata:
          f:annotations:
            f:argocd.argoproj.io/tracking-id: {}
            f:kubectl.kubernetes.io/last-applied-configuration: {}
      manager: argocd-controller
      operation: Update
      time: '2025-05-30T20:30:09Z'
  1. Remove the field in Git
kind: ConfigMap
metadata:
  name: test-config
data:
  key1: value1
  key2: value2
  # legacy_field removed
  1. Sync with ServerSideApply
  2. Observe that the legacy_field still exists in the cluster:
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
data:
  key1: value1
  key2: value2
  legacy_field: should_be_removed

Expected behavior

Field should be removed from live manifest after sync with ServerSideApply

Screenshots

Version

argocd version
argocd: v2.14.9+38985bd.dirty
  BuildDate: 2025-04-02T23:02:54Z
  GitCommit: 38985bdcd6c3b031fb83757a1fb0c39a55bf6a24
  GitTreeState: dirty
  GoVersion: go1.24.2
  Compiler: gc
  Platform: darwin/amd64
argocd-server: v3.0.3+c27a9d3.dirty
  BuildDate: 2025-05-27T23:39:57Z
  GitCommit: c27a9d33603b399b228d896e98d4a5fc86afd53c
  GitTreeState: dirty
  GoVersion: go1.24.3
  Compiler: gc
  Platform: darwin/amd64
  Kustomize Version: v5.4.3 2024-07-19T16:40:33Z
  Helm Version: v3.17.1+g980d8ac
  Kubectl Version: v0.32.2
  Jsonnet Version: v0.20.0

Logs

Paste any relevant application logs here.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingfeature:server-side-applyIssue related to the server side apply feature

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions