kubectl get -o yaml: is it possible to hide metadata.managedFields?

Viewed 9381

Using kubectl version 1.18, on microk8s 1.18.3

When getting a resource definition in yaml format. Example kubectl get pod/mypod-6f855c5fff-j8mrw -o yaml. The output contains a section related to metadata.managedFields

Is there a way to hide that metadata.managedFields to shorten the console output?

Below is an example of output to better illustrate the question.

apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"productpage","service":"productpage"},"name":"productpage","namespace":"bookinfo"},"spec":{"ports":[{"name":"http","port":9080}],"selector":{"app":"productpage"}}}
  creationTimestamp: "2020-05-28T05:22:41Z"
  labels:
    app: productpage
    service: productpage
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:kubectl.kubernetes.io/last-applied-configuration: {}
        f:labels:
          .: {}
          f:app: {}
          f:service: {}
      f:spec:
        f:ports:
          .: {}
          k:{"port":9080,"protocol":"TCP"}:
            .: {}
            f:name: {}
            f:port: {}
            f:protocol: {}
            f:targetPort: {}
        f:selector:
          .: {}
          f:app: {}
        f:sessionAffinity: {}
        f:type: {}
    manager: kubectl
    operation: Update
    time: "2020-05-28T05:22:41Z"
  name: productpage
  namespace: bookinfo
  resourceVersion: "121804"
  selfLink: /api/v1/namespaces/bookinfo/services/productpage
  uid: feb5a62b-8784-41d2-b104-bf6ebc4a2763
spec:
  clusterIP: 10.152.183.9
  ports:
  - name: http
    port: 9080
    protocol: TCP
    targetPort: 9080
  selector:
    app: productpage
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
6 Answers

Kubectl 1.21 doesn't include managed fields by default anymore

kubectl get will omit managed fields by default now. Users could set --show-managed-fields to true to show managedFields when the output format is either json or yaml.

https://github.com/kubernetes/kubernetes/pull/96878

check out this kubectl plugin: https://github.com/itaysk/kubectl-neat. it not only removes managedField but many other fields users are not interested in.

for example: kubectl get pod mymod -oyaml | kubectl neat or kubectl neat pod mypod -oyaml

For those who like to download yaml and delete unwanted keys try this:

Install yq then try(please make sure you get yq version 4.x):

cat k8s-config.yaml | yq eval 'del(.status)' - 
   --OR--
kubectl --namespace {namespace} --context {cluster} get pod {podname} | yq ...

You may add/join more yq to delete more keys. Here is what I did:

cat k8s-config.yaml | yq eval 'del(.status)' -  | yq eval 'del (.metadata.managedFields)' - | yq eval 'del (.metadata.annotations)' - | yq eval 'del (.spec.tolerations)' -  | yq eval 'del(.metadata.ownerReferences)' - | yq eval 'del(.metadata.resourceVersion)' - | yq eval 'del(.metadata.uid)' - | yq eval 'del(.metadata.selfLink)' - | yq eval 'del(.metadata.creationTimestamp)' - | yq eval 'del(.metadata.generateName)' - 

--OR--

cat k8s-config.yaml | yq eval 'del(.status)' - \
 | yq eval 'del (.metadata.managedFields)' - \
 | yq eval 'del (.metadata.annotations)' - \
 | yq eval 'del (.spec.tolerations)' - \
 | yq eval 'del(.metadata.ownerReferences)' - \
 | yq eval 'del(.metadata.resourceVersion)' - \
 | yq eval 'del(.metadata.uid)' - \
 | yq eval 'del(.metadata.selfLink)' - \
 | yq eval 'del(.metadata.creationTimestamp)' - \
 | yq eval 'del(.metadata.generateName)' - 

Another way is to have a neat() function on your ~/.bashrc or ~/.zshrc and call it as below:

neat() function:

neat () {
  yq eval 'del(.items[].metadata.managedFields,
    .metadata,
    .apiVersion,
    .items[].apiVersion,
    .items[].metadata.namespace,
    .items[].kind,
    .items[].status,
    .items[].metadata.annotations,
    .items[].metadata.resourceVersion,
    .items[].metadata.selfLink,.items[].metadata.uid,
    .items[].metadata.creationTimestamp,
    .items[].metadata.ownerReferences)' -
}

then:

kubectl get pods -o yaml | neat 
cat k8s-config.yaml | neat

You may read more on yq delete here

I'd like to add some basic information about that feature:

ManagedFields is a section created by ServerSideApply feature. It helps tracking changes in cluster objects by different managers.

If you disable it in the kube-apiserver manifests all object created after this change won't have metadata.managedFields sections, but it doesn't affect the existing objects.

  1. Open the kube-apiserver manifest with your favorite text editor:

    $ sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
    
  2. Add command line argument to spec.containers.command:

       - --feature-gates=ServerSideApply=false
    

kube-apiserver will restart immediately.
It usually takes couple of minutes for the kube-apiserver to start serving requests again.

You can also disable ServerSideApply feature gate on the cluster creation stage.


Alternatively, managedFields can be patched to an empty list for the existing object:

$ kubectl patch pod podname -p '{"metadata":{"managedFields":[{}]}}'

This will overwrite the managedFields with a list containing a single empty entry that then results in the managedFields being stripped entirely from the object. Note that just setting the managedFields to an empty list will not reset the field. This is on purpose, so managedFields never get stripped by clients not aware of the field.

Now that --export is deprecated, to get the output from your resources in the 'original' format (just cleaned up, without any information you don't want in this situation) you can do the following using yq v4.x:

kubectl get <resource> -n <namespace> <resource-name> -o yaml \
  | yq eval 'del(.metadata.resourceVersion, .metadata.uid, .metadata.annotations, .metadata.creationTimestamp, .metadata.selfLink, .metadata.managedFields)' -

First thing what came to my mind was to just use stream editor like sed to just skip this part beggining form managedFields: to another specific pattern.

It's bit hardcoded as you would need to specify 2 patterns like managedFields: and ending pattern like name: productpage but will work for this scenario. If this won't fit you, pleas add more details, how you would like to achieve this.

sed command would look like:

sed -n '/(Pattern1)/{p; :a; N; /(Pattern2)/!ba; s/.*\n//}; p'

For example Ive used Nginx pod:

$ kubectl get po nginx -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu request for container
      nginx'
  creationTimestamp: "2020-05-29T10:54:18Z"
...
spec:
  containers:
  - image: nginx
    imagePullPolicy: Always
    name: nginx
   ...
status:
  conditions:
...
        startedAt: "2020-05-29T10:54:19Z"
  hostIP: 10.154.0.29
  phase: Running
  podIP: 10.52.1.6
  podIPs:
  - ip: 10.52.1.6
  qosClass: Burstable
  startTime: "2020-05-29T10:54:18Z"

After using sed

$ kubectl get po nginx -o yaml | sed -n '/annotations:/{p; :a; N; /hostIP: 10.154.0.29/!ba; s/.*\n//}; p'
apiVersion: v1
kind: Pod
metadata:
  annotations:
  hostIP: 10.154.0.29
  phase: Running
  podIP: 10.52.1.6
  podIPs:
  - ip: 10.52.1.6
  qosClass: Burstable
  startTime: "2020-05-29T10:54:18Z"

In your case command like:

$ kubectl get pod/mypod-6f855c5fff-j8mrw -o yaml | sed -n '/managedFields:/{p; :a; N; /name: productpage/!ba; s/.*\n//}; p'

Should give output like:

apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"productpage","service":"productpage"},"name":"productpage","namespace":"bookinfo"},"spec":{"ports":[{"name":"http","port":9080}],"selector":{"app":"productpage"}}}
  creationTimestamp: "2020-05-28T05:22:41Z"
  labels:
    app: productpage
    service: productpage
  managedFields:
  name: productpage
  namespace: bookinfo
  resourceVersion: "121804"
  selfLink: /api/v1/namespaces/bookinfo/services/productpage
  uid: feb5a62b-8784-41d2-b104-bf6ebc4a2763
spec:
  clusterIP: 10.152.183.9
  ports:
  - name: http
    port: 9080
    protocol: TCP
    targetPort: 9080
  selector:
    app: productpage
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
Related