'How can i remove an element in Deployment volumeMounts with kubectl Patch command?

I have a Deployment like this:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    volumeMounts:
      - mountPath: /home
        name: john-webos-vol
        subPath: home
      - mountPath: /pkg
        name: john-vol
        readOnly: true
        subPath: school

I want to change the Deloyment with the kubectl patch command, so it has the following volumeMounts in the PodTemplate instead:

target.yaml:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    volumeMounts:
      - mountPath: /home
        name: john-webos-vol
        subPath: home

I used the below command, but it didn't work.

kubectl patch deployment sample --patch "$(cat target.yaml)"

Can anyone give me some advice?



Solution 1:[1]

you can't do this with kubectl patch. The patch you did in your problem is called a strategic merge patch. the patch can't replace things, instead with this patch you can only add things.

like if you have intially one container in your podspec but you need to add another container. you can use patch here to add another container. but if you have two container and need to remove one you can't do this with this kind of patch.

if you want to this with patch you need to use retainKeys. Ref

let me explain how you can do this in another simple way. lets assume you have applied below test.yaml with kubectl apply -f test.yaml

test.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /home
          name: john-webos-vol
          subPath: home
        - mountPath: /pkg
          name: john-vol
          readOnly: true
          subPath: school
      volumes:
      - name: john-webos-vol
        emptyDir: {}
      - name: john-vol
        emptyDir: {}

now you need update this one. and the updated one target.yaml will remove one of volume .

target.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /pkg
          name: john-vol
          readOnly: true
          subPath: school
      volumes:
      - name: john-vol
        emptyDir: {}

you can just use:

 kubectl apply -f target.yaml

this one will update your deployment with new configuration

Solution 2:[2]

You can use JSON patch http://jsonpatch.com/

Remove specific volume mount

kubectl patch deployment <NAME> --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/volumeMounts/0"}]'

Replace volume mounts with what you need

kubectl patch deployment <NAME> --type json -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/volumeMounts", "value": [{"mountPath": "/home", "name": "john-webos-vol", "subPath": "home"}]}]'

Kubectl cheet sheet for more info: https://kubernetes.io/docs/reference/kubectl/cheatsheet/#patching-resources

Solution 3:[3]

You can leverage the apply command, by getting the deployment definition in JSON format, modifying (in your case removing) this section

  - mountPath: /pkg
    name: john-vol
    readOnly: true
    subPath: school

with sed or a simmilar utility and then applying it back:

kubectl get deployment <myDeployment> -n <myNamespace> | sed -z -s -E -b -e 's/REGEX_TO_MATCH_PART_OF_DEPLOYMENT_TO_REMOVE//g' | kubectl apply -f -

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Renuka Fernando
Solution 3 George Cimpoies