Kubectl: Unable to change service from type=NodePort to type=ClusterIP with kubectl

Created on 23 Jan 2018  路  24Comments  路  Source: kubernetes/kubectl

Is this a BUG REPORT or FEATURE REQUEST? (choose one):
/kind bug

Kubernetes version (use kubectl version):

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"8", GitVersion:"v1.8.6", GitCommit:"6260bb08c46c31eea6cb538b34a9ceb3e406689c", GitTreeState:"clean", BuildDate:"2017-12-21T06:34:11Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10+", GitVersion:"v1.10.0-alpha.1.930+0d1986ad8219bf-dirty", GitCommit:"0d1986ad8219bf1a64fc657eac407cc84d3ad647", GitTreeState:"dirty", BuildDate:"2018-01-17T03:10:36Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}

What happened:

  • Create a service with type=ClusterIP. Let's say kube-dns:
apiVersion: v1
kind: Service
metadata:
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: KubeDNS
  name: kube-dns
  namespace: kube-system
spec:
  clusterIP: 10.0.0.10
  ports:
  - name: dns
    port: 53
    protocol: UDP
    targetPort: 53
  - name: dns-tcp
    port: 53
    protocol: TCP
    targetPort: 53
  selector:
    k8s-app: kube-dns
  type: ClusterIP
  • Edit type from ClusterIP to NodePort, and now we have:
apiVersion: v1
kind: Service
metadata:
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: KubeDNS
  name: kube-dns
  namespace: kube-system
spec:
  clusterIP: 10.0.0.10
  ports:
  - name: dns
    nodePort: 31716
    port: 53
    protocol: UDP
    targetPort: 53
  - name: dns-tcp
    nodePort: 30492
    port: 53
    protocol: TCP
    targetPort: 53
  selector:
    k8s-app: kube-dns
  type: NodePort
  • Edit type from NodePort to ClusterIP with all the auto-allocated nodePorts removed, and we hit this error:
# services "kube-dns" was not valid:
# * spec.ports[1].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'
  • Try to use kubectl apply -f with a similar kube-dns yaml (type=ClusterIP with all nodePorts removed) and hit the same error:
$ kubectl apply -f kube-dns.yaml 
The Service "kube-dns" is invalid: spec.ports[1].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'

What you expected to happen:
Users should be able to modify service type from NodePort to CluserIP.

Anything else we need to know:
Is this a regression? There was a similar bug before (https://github.com/kubernetes/kubernetes/issues/42282), which was fixed.

@mengqiy @kubernetes/sig-cli-bugs

kinbug lifecyclrotten sicli

Most helpful comment

Dup of kubernetes/kubernetes#66390, which has been fixed in kubernetes/kubernetes#66602.

Please try using kubectl apply -f test-service.yaml --force.

/close

Please reopen if needed.

All 24 comments

This is caused by a known issue: mergeKey in ports is portNumber (both are 53) cannot uniquely identify an entry in this case.

I've just run into this issue, is there a workaround?

kubectl replace can be the workaround.

Hitting similar issue. Any workaround which doesn't delete service ?

@Vikash082 Does kubectl replace work for you?

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

Just came across this issue so definitely not stale.

kubectl replace worked for me

Note: it requires specifying the clusterIP field to be the same IP as the allocated ClusterIP of this service

Stale issues rot after 30d of inactivity.
Mark the issue as fresh with /remove-lifecycle rotten.
Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle rotten

Not fixed:

$ kubectl replace -f grav-deployment.yml
deployment.apps/grav replaced
The Service "grav-service" is invalid: spec.clusterIP: Invalid value: "": field is immutable
$ kubectl delete -f grav-deployment.yml                                                                                                                                                                                                           
deployment.apps "grav" deleted
service "grav-service" deleted
$ kubectl apply -f grav-deployment.yml                                                                                                                                                                                                            
deployment.apps/grav created
service/grav-service created

Dup of kubernetes/kubernetes#66390, which has been fixed in kubernetes/kubernetes#66602.

Please try using kubectl apply -f test-service.yaml --force.

/close

Please reopen if needed.

@dixudx: Closing this issue.

In response to this:

Dup of kubernetes/kubernetes#66390, which has been fixed in kubernetes/kubernetes#66602.

Please try using kubectl apply -f test-service.yaml --force.

/close

Please reopen if needed.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

it workd for me
kubectl apply -f test-service.yaml --force.

The Service "ingress-nginx" is invalid:
* spec.ports[0].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'
* spec.ports[1].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'

Should we update the error message?

is there a workaround for this that does not require the use of --force?

@mpgarate Have you tried kubectl replace?

Ref https://github.com/kubernetes/kubectl/issues/221#issuecomment-409399714.

I ran into this message with kubectl replace:
The Service ... is invalid: spec.clusterIP: Invalid value: "": field is immutable

I suspect this is because I do not have the ip address hard-coded as mentioned in comment 221. In my case is is not practical to do that for every service, and instead I am using a NodePort type as a workaround.

@mpgarate Agreed that hardcoding the IP for every service on creation is not practical. But it may be doable to simply copy over the randomly allocated clusterIP when you try to update the service (e.g. via kubectl replace)?

use edit service, and
comment out the # nodePort: 30492
change to ClusterIP
save it

I use helm and this helped me fix the issue:

spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.externalPort }}
{{- if (eq .Values.service.type "ClusterIP") }}
      nodePort: null
{{- end }}
      targetPort: {{ .Values.service.internalPort }}
      protocol: TCP
      name: {{ .Values.service.name }}

Edit: this only works _after_ the first install. So there's no "declarative" workaround, you need to change your service manually.

nodePort: null definitely works declaratively. Thanks @aserrallerios.

nodePort: null definitely works declaratively. Thanks @aserrallerios.

The following worked for me kubectl patch svc my-service --type='json' -p '[{"op":"replace","path":"/spec/type","value":"ClusterIP"},{"op":"replace","path":"/spec/ports/0/nodePort","value":null}]'.

I encountered the same bug, is it a bug?has it been fixed?

Check for indentations too. In my case its the issue :p

Was this page helpful?
0 / 5 - 0 ratings