helm: Helm 3 - upgrade nginx - spec.clusterIP: Invalid value: "": field is immutable
I use the following to install / upgrade a chart:
./helm upgrade --install
–set rbac.create=false
–set controller.replicaCount=2
–set controller.service.loadBalancerIP=$ip
–wait main-ingress stable/nginx-ingress
(Where $ip is an IP, e.g. 10.0.0.1)
That’s done in a CI/CD pipeline, so the idea is to install the first time, upgrade next times.
It installs fine. At the second run, it outputs the following:
client.go:339: Cannot patch Service: “main-ingress-nginx-ingress-controller” (Service “main-ingress-nginx-ingress-controller” is invalid: spec.clusterIP: Invalid value: “”: field is immutable) client.go:358: Use --force to force recreation of the resource client.go:339: Cannot patch Service: “main-ingress-nginx-ingress-default-backend” (Service “main-ingress-nginx-ingress-default-backend” is invalid: spec.clusterIP: Invalid value: “”: field is immutable) client.go:358: Use --force to force recreation of the resource Error: UPGRADE FAILED: Service “main-ingress-nginx-ingress-controller” is invalid: spec.clusterIP: Invalid value: “”: field is immutable && Service “main-ingress-nginx-ingress-default-backend” is invalid: spec.clusterIP: Invalid value: “”: field is immutable
I also get this on helm list:
NAME NAMESPACE REVISION UPDATED STATUS CHART
main-ingress default 1 2019-09-06 13:17:33.8463781 -0400 EDT deployed nginx-ingress-1.18.0
main-ingress default 2 2019-09-06 13:21:11.6428945 -0400 EDT failed nginx-ingress-1.18.0
So, the release has failed.
I didn’t have that problem with Helm 2. Is it due to a change of behaviour in helm 3 or is it a bug? If it’s the former, how could I change the command not to have that problem?
Output of helm version: version.BuildInfo{Version:“v3.0.0-beta.2”, GitCommit:“26c7338408f8db593f93cd7c963ad56f67f662d4”, GitTreeState:“clean”, GoVersion:“go1.12.9”}
Output of kubectl version: Client Version: version.Info{Major:“1”, Minor:“12”, GitVersion:“v1.12.0”, GitCommit:“0ed33881dc4355495f623c6f22e7dd0b7632b7c0”, GitTreeState:“clean”, BuildDate:“2018-09-27T17:05:32Z”, GoVersion:“go1.10.4”, Compiler:“gc”, Platform:“linux/amd64”}
Server Version: version.Info{Major:“1”, Minor:“13”, GitVersion:“v1.13.10”, GitCommit:“37d169313237cb4ceb2cc4bef300f2ae3053c1a2”, GitTreeState:“clean”, BuildDate:“2019-08-19T10:44:49Z”, GoVersion:“go1.11.13”, Compiler:“gc”, Platform:“linux/amd64”}
Cloud Provider/Platform (AKS, GKE, Minikube etc.): AKS
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 46
- Comments: 71 (19 by maintainers)
Commits related to this issue
- Prevent "field is immutable" error on Helm 3 upgrade When attempting to upgrade openldap resources with Helm client v3, OpenLDAP resources fail to upgrade after initial installation because we DON'T ... — committed to indiebrain/charts by indiebrain 4 years ago
- Prevent "field is immutable" error on Helm 3 upgrade When attempting to upgrade openldap resources with Helm client v3, OpenLDAP resources fail to upgrade after initial installation because we DON'T ... — committed to indiebrain/charts by indiebrain 4 years ago
- Prevent "field is immutable" error on Helm 3 upgrade When attempting to upgrade openldap resources with Helm client v3, OpenLDAP resources fail to upgrade after initial installation because we DON'T ... — committed to indiebrain/charts by indiebrain 4 years ago
- Prevent "field is immutable" error on Helm 3 upgrade When attempting to upgrade openldap resources with Helm client v3, OpenLDAP resources fail to upgrade after initial installation because we DON'T ... — committed to indiebrain/charts by indiebrain 4 years ago
- Prevent "field is immutable" error on Helm 3 upgrade When attempting to upgrade openldap resources with Helm client v3, OpenLDAP resources fail to upgrade after initial installation because we DON'T ... — committed to indiebrain/charts by indiebrain 4 years ago
- Prevent "field is immutable" error on Helm 3 upgrade When attempting to upgrade openldap resources with Helm client v3, OpenLDAP resources fail to upgrade after initial installation because we DON'T ... — committed to indiebrain/charts by indiebrain 4 years ago
- With commit in concourse charts https://github.com/concourse/concourse-chart/pull/163 k8s-topgun failed with `spec.clusterIP: Invalid value: "": field is immutable` We don't have to use `--force` fo... — committed to concourse/concourse by deleted user 3 years ago
- Helm: omit clusterIP from the Service entirely if not provided When clusterIP is provided as an empty string to Helm's three-way patch mechanism during an upgrade, Helm sees the Kubernetes auto-assig... — committed to rmmorrison/mockserver by rmmorrison 3 years ago
- Helm: omit clusterIP from the Service entirely if not provided When clusterIP is provided as an empty string to Helm's three-way patch mechanism during an upgrade, Helm sees the Kubernetes auto-assig... — committed to rmmorrison/mockserver by rmmorrison 3 years ago
- xnat-web/service: only add clusterIP field if the service type is actually ClusterIP Work around https://github.com/helm/helm/issues/6378, specifically see https://github.com/helm/helm/issues/6378#is... — committed to Australian-Imaging-Service/charts by vs49688 3 years ago
- xnat-web/service: only add clusterIP field if the service type is actually ClusterIP Work around https://github.com/helm/helm/issues/6378, specifically see https://github.com/helm/helm/issues/6378#is... — committed to Australian-Imaging-Service/charts by vs49688 3 years ago
- xnat-web/service: only add clusterIP field if the service type is actually ClusterIP Work around https://github.com/helm/helm/issues/6378, specifically see https://github.com/helm/helm/issues/6378#is... — committed to Australian-Imaging-Service/charts by vs49688 3 years ago
I have the same Problem, even without setting the service type or clusterIP with helm v3.0.0-rc.2 if i use the --force option with the helm update --install command. Without the --force it works fine
@zen4ever nailed the issue in https://github.com/helm/helm/issues/6378#issuecomment-532766512. I’ll try to explain it in more detail…
As others have pointed out, the issue arises when a chart defines a clusterIP with an empty string. When the Service is installed, Kubernetes populates this field with the clusterIP it assigned to the Service.
When
helm upgradeis invoked, the chart asked for theclusterIPto be removed, hence why the error message isspec.clusterIP: Invalid value: "": field is immutable.This happens because of the following behaviour:
clusterIPto be an empty stringclusterIP. We’ll use172.17.0.1for this examplehelm upgrade, the chart wants theclusterIPto be an empty string (or in @zen4ever’s case above, it is omitted)When generating the three-way patch, it sees that the old state was
"", live state is currently at"172.17.0.1", and proposed state is"". Helm detected that the user requested to change theclusterIPfrom “172.17.0.1” to “”, so it supplied a patch.In Helm 2, it ignored the live state, so it saw no change (old state:
clusterIP: ""to new state:clusterIP: ""), and no patch was generated, bypassing this behaviour.My recommendation would be to change the template output. If no
clusterIPis being provided as a value, then don’t set the value to an empty string… Omit the field entirely.e.g. in the case of
stable/nginx-ingress:Should be changed to:
This is also why
--set controller.service.omitClusterIP=trueworks in this case.TL;DR don’t do this in your Service templates:
Otherwise, Helm will try to change the service’s clusterIP from an auto-generated IP address to the empty string, hence the error message.
Hope this helps!
We’re running into the same issue:
spec.clusterIPis not part of the Service template, yet with Helm 3.0.2 and ahelm upgrade ... --force --installcall, we’re also seeing:Please re-open.
We have the same problem. We don’t define
clusterIPat all in our chart and it is not present in the final template. However, we still get the same error and only with--forceflag.Please reopen. Issue is not fixed. This “hack” suggested by nasseemkullah is not appropriate. Don’t ask people to jump on heads. Just fix it. Very poor migration path. Helm sucks.
Hey all, please be aware that the related issue in Kubernetes was accepted as a bug
FYI @bacongobbler
https://github.com/kubernetes/kubernetes/issues/91459
I think this is issue with helm with
--forceoption during upgrade. Helm is trying to recreate service but it also replace spec.clusterIP so it throw error. I can confirm this using my own custom chart.Error: UPGRADE FAILED: failed to replace object: Service "litespeed" is invalid: spec.clusterIP: Invalid value: "": field is immutableI believe this is an issue with the nginx-ingress chart, not helm3. By default, the chart will always try to pass
controller.service.clusterIP = ""anddefaultBackend.service.clusterIP = ""unless you setcontroller.service.omitClusterIP=trueanddefaultBackend.service.omitClusterIP=true.link to sources: https://github.com/helm/charts/blob/master/stable/nginx-ingress/values.yaml#L321 https://github.com/helm/charts/blob/master/stable/nginx-ingress/templates/controller-service.yaml#L22
workaround:
According to my understanding this a problem with Kubernetes, because “forcefully overwriting” does not behave the same way as “deleting and recreating again”. Is there any upstream bug?
On the other hand, Helm is also misleading, because
--forceis described as “force resource updates through a replacement strategy”. While in reality it does not do any replacement, it just attempts to forcefully overwrite resources (it would be better to name the flag--force-overwrite). Forceful replacement would look like deleting and recreating again (there could be a flag--force-recreate). Of course,--force-recreatecould be a bit dangerous to use for some resources, but it would always succeed.Anyway, Helm could implement a fallback workaround for such type of issues. If the current behavior (described as
--force-overwrite) fails and detects an immutable field error, it should delete and recreate the resource (as--force-recreate).@johannges, I was just about to post the same. 👍
Messing around with this some more, I’ve observed that:
helm upgrade ... --force --install- results in The Service “dummy” is invalid:spec.clusterIP: Invalid value: “”: field is immutablehelm template ... | kubectl apply -f -- workshelm template ... | kubectl replace -f -- results in The Service “dummy” is invalid:spec.clusterIP: Invalid value: “”: field is immutablehelm template ... | kubectl replace --force -f -- workskubectl version - 1.14.6 helm version - 3.0.2
same here- we dont define
ClusterIPanywhere but still see the errorHey @bacongobbler , we faced with the same issue during migrate helm v2 release to helm v3. We use
type: ClusterIPin Service but omitClusterIPat all and we get:Error: UPGRADE FAILED: failed to replace object: Service "dummy" is invalid: spec.clusterIP: Invalid value: "": field is immutableWe don’t have
spec.clusterIP:in our helm template but we got this Error after migrate release via helm 2to3Service template:
@bacongobbler I’ve got to this thread after checking https://github.com/helm/helm/issues/7956
As with all previous commenters: we don’t have “clusterIP” in templates at all, but error is still present with latest Helm if --force flag is used.
Helm version: 3.4.1
“helm -n kube-system get manifest CHART_NAME | grep clusterIP” shows no results.
Error:
@antonakv what a way to start the year 😃 I think in general we are playing with fire when providing clusterIP as a configurable value in a chart, and cannot totally blame one tool/person/PR in particular. If clusterIP needs to be a configurable value, by default it should not be in the rendered template, that’s the idea of my commenting out in the values files as per https://github.com/helm/charts/blob/270172836fd8cf56d787cf7d04d938856de0c794/stable/nginx-ingress/values.yaml#L236
This, if I’m not mistaken, should prevent anby future headaches for those that install the chart as of that change. But for those of us (myself included) who had installed it prior, and then migrated to helm3, I’m afraid hardcording the current clusterIP values in our values files OR uninstalling and reinstalling the chart (causes downtime!) are the only options I see.
Opinions are my own, I am not paid to work on helm, just an end user like you. Those who are paid to work on this full time may be able to provide more insight.
Happy new year and good luck! Don’t give up on helm, together we can make it better.
As far as Kubernetes is concerned: yes.
Cool! I inspired from your answer, that i have to comment
force: ..line in helmfile yaml :It works 🎉
Looks like Microsoft is mentor of project. I see style. 😃
As a temporary solution if you’re trying to get this to work for now while this issue gets resolved I found if I did the following I was able to perform an update:
kubectl get svc | grep ingressI’ve tested this for a cluster I’m running and it didn’t require any recreation.
@davidfernandezm did you ever find a solution for this? I’m seeing the same on my end and my services are defined exactly as yours are. No option for
clusterIPis being set, and yet Helm still fails on an upgrade.Hi @bacongobbler, I think since if no value is provided we will still wind up with
clusterIP: ""… better would be valueclusterIP: ""completely commented out in the values file. This omits it from rendered manifests when set and should save future headaches. However if using helm3 and current helm state hasclusterIP: ""set, one needs to hardcode the clusterIP addresses in values files.@bacongobbler I am really sorry if I miss something here, maybe I simply don’t know enough about Helm internals.
“My recommendation would be to change the template output. If no clusterIP is being provided as a value, then don’t set the value to an empty string… Omit the field entirely.”
So what is the solution? Does that mean that “–force” flag can’t be used at all if clusterIP field is not set to some static value?
If anyone is experiencing symptoms that are not a result of the explanation provided in https://github.com/helm/helm/issues/6378#issuecomment-557746499, can you please open a new issue with your findings and how we can reproduce it on our end?
The issue raised by the OP was because of the scenario provided above, where a chart set the ClusterIP to an empty string on install. It is entirely possible that there are other scenarios where this particular case can crop up, such as others have mentioned with the use of the
--forceflag. Those cases should be discussed separately, as the diagnosis and solution may differ than the advice provided earlier.Thank you!
Best solution, it works for me, thank you!
@antonakv this issue duplicate of 7956 @bacongobbler more info
@mssachan see #7082 and the draft proposal in #7431 for your use case. That proposal aims to implement
kubectl replace —force, which would be similar to Helm 2’shelm install —force‘s behaviour.@juan131 @Ronsevet: remove --force The meaning changed.
In case anyone ends up here using helm v3 via terraform, since you cant directly tell it not to use
--forcei had success manually deleting the chart usinghelm deletethen re-running terraform. this sucks but it does work.edit: the whole error: ( “nginx-ingress-singleton-controller” is the release name i set. it has no specific meaning )
I was encountering this error as well for existing deployed kafka and redis chart releases. Removing
--forcedid indeed resolve this.Now I’m getting a new error from the redis release:
Error: UPGRADE FAILED: release redis failed, and has been rolled back due to atomic being set: cannot patch "redis-master" with kind StatefulSet: StatefulSet.apps "redis-master" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbiddenAgreed with @bacongobbler that this looks related to the Helm v3 three-way merge patch strategy that’s likely resulting in passing in fields (even with the same values as before) to the update/patch that Kubernetes considers immutable/unchangeable after first creation.