我使用以下内容来安装/升级图表:
./舵升级--安装
--set rbac.create=false
--set controller.replicaCount=2
--set controller.service.loadBalancerIP=$ip
--wait main-ingress stable/nginx-ingress
(其中 $ip 是一个 IP,例如 10.0.0.1)
这是在 CI/CD 管道中完成的,所以想法是第一次安装,下次升级。
它安装得很好。 在第二次运行时,它输出以下内容:
_client.go:339:无法修补服务:“main-ingress-nginx-ingress-controller”(服务“main-ingress-nginx-ingress-controller”无效:spec.clusterIP:无效值:“”:字段不可变)
client.go:358: 使用 --force 强制重新创建资源
client.go:339:无法修补服务:“main-ingress-nginx-ingress-default-backend”(服务“main-ingress-nginx-ingress-default-backend”无效:spec.clusterIP:无效值:“” : 字段是不可变的)
client.go:358: 使用 --force 强制重新创建资源
错误:升级失败:服务“main-ingress-nginx-ingress-controller”无效:spec.clusterIP:无效值:“”:字段不可变&服务“main-ingress-nginx-ingress-default-backend”无效:spec.clusterIP:无效值:“”:字段是不可变的_
我也在掌舵列表中得到了这个:
名称命名空间修订更新状态图表
main-ingress default 1 2019-09-06 13:17:33.8463781 -0400 EDT 部署 nginx-ingress-1.18.0
main-ingress default 2 2019-09-06 13:21:11.6428945 -0400 EDT 失败 nginx-ingress-1.18.0
所以,发布失败了。
我在 Helm 2 中没有这个问题。是由于 helm 3 中的行为改变还是错误? 如果是前者,我如何更改命令才不会出现该问题?
helm version
:version.BuildInfo{Version:"v3.0.0-beta.2", GitCommit:"26c7338408f8db593f93cd7c963ad56f67f662d4", GitTreeState:"clean", GoVersion:"go1.12.9"}
kubectl version
:客户端版本:version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.0", GitCommit:"0ed33881dc4355495f623c6f22e7dd0b7632b7c0", GitTreeState:"clean “2018-09-27T17:05:32Z”,GoVersion:“go1.10.4”,编译器:“gc”,平台:“linux/amd64”}
服务器版本:version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.10", GitCommit:"37d169313237cb4ceb2cc4bef300f2ae3053c1a2", GitTreeState:"clean", BuildDate:"20194T0- 49Z", GoVersion:"go1.11.13", 编译器:"gc", 平台:"linux/amd64"}
云提供商/平台(AKS、GKE、Minikube 等):AKS
这可能与 Helm 3 最近的变化有关,它现在使用类似于 kubectl 的三向合并补丁策略。 见#6124
如果您能提供有关如何重现此操作的步骤,那就太好了。 谢谢!
当然!
我创建了一个 AKS 集群。
我在 MC_* 资源组中创建了一个公共 IP。
我将该公共 IP 的 IP 地址存储在 $ip 中。
然后基本上运行该命令两次:
./舵升级--安装
--set rbac.create=false
--set controller.replicaCount=2
--set controller.service.loadBalancerIP=$ip
--wait main-ingress stable/nginx-ingress
这类似于https://docs.microsoft.com/en-us/azure/aks/ingress-static-ip 中所做的
不同之处在于我做了两次 helm upgrade --install 。 这样做的目的是在我的 CI/CD 中有一个命令行(无条件)。
如果您需要更多细节来重现,请告诉我。
这足以重现吗? 如果有帮助,我可以提供一个 bash 脚本。
抱歉,本周在欧盟 Helm 峰会上休假,所以我还没有时间做出回应。
啊……不用担心。 享受峰会!
我也遇到这个问题
$ helm version --short
v3.0.0-beta.3+g5cb923e
nginx-ingress 图表在第一次运行时安装良好,但是在升级时...
$ helm upgrade --install first-chart stable/nginx-ingress --namespace infra
client.go:357: Cannot patch Service: "first-chart-nginx-ingress-controller" (Service "first-chart-nginx-ingress-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable)
client.go:376: Use --force to force recreation of the resource
client.go:357: Cannot patch Service: "first-chart-nginx-ingress-default-backend" (Service "first-chart-nginx-ingress-default-backend" is invalid: spec.clusterIP: Invalid value: "": field is immutable)
client.go:376: Use --force to force recreation of the resource
Error: UPGRADE FAILED: Service "first-chart-nginx-ingress-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable && Service "first-chart-nginx-ingress-default-backend" is invalid: spec.clusterIP: Invalid value: "": field is immutable
$ helm ls -n infra
NAME NAMESPACE REVISION UPDATED STATUS CHART
first-chart infra 1 2019-09-17 16:15:25.513997106 -0500 CDT deployed nginx-ingress-1.20.0
first-chart infra 2 2019-09-17 16:15:30.845249671 -0500 CDT failed nginx-ingress-1.20.0
我相信这是 nginx-ingress 图表的问题,而不是 helm3。 默认情况下,图表将始终尝试传递controller.service.clusterIP = ""
和defaultBackend.service.clusterIP = ""
除非您设置controller.service.omitClusterIP=true
和defaultBackend.service.omitClusterIP=true
。
来源链接:
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
解决方法:
$ helm upgrade --install ingress-test stable/nginx-ingress --set controller.service.omitClusterIP=true --set defaultBackend.service.omitClusterIP=true
我试过这样做,但我仍然遇到同样的错误
helm upgrade --install ingx stable/nginx-ingress -f ingx-values.yaml 1 ↵
client.go:357: Cannot patch Service: "ingx-nginx-ingress-controller" (Service "ingx-nginx-ingress-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable)
client.go:376: Use --force to force recreation of the resource
client.go:357: Cannot patch Service: "ingx-nginx-ingress-default-backend" (Service "ingx-nginx-ingress-default-backend" is invalid: spec.clusterIP: Invalid value: "": field is immutable)
client.go:376: Use --force to force recreation of the resource
Error: UPGRADE FAILED: Service "ingx-nginx-ingress-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable && Service "ingx-nginx-ingress-default-backend" is invalid: spec.clusterIP: Invalid value: "": field is immutable
ingx-values.yaml
rbac:
create: true
controller:
service:
externalTrafficPolicy: Local
omitClusterIP: true
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 100
targetCPUUtilizationPercentage: "70"
targetMemoryUtilizationPercentage: "70"
defaultBackend:
service:
omitClusterIP: true
正如您在下面看到的,模板中没有 clusterIP
掌舵模板 ingx stable/nginx-ingress -f ingx-values.yaml
---
# Source: nginx-ingress/templates/controller-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
heritage: Helm
release: ingx
name: ingx-nginx-ingress
---
# Source: nginx-ingress/templates/default-backend-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
heritage: Helm
release: ingx
name: ingx-nginx-ingress-backend
---
# Source: nginx-ingress/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
heritage: Helm
release: ingx
name: ingx-nginx-ingress
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- update
- watch
- apiGroups:
- extensions
- "networking.k8s.io" # k8s 1.14+
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- extensions
- "networking.k8s.io" # k8s 1.14+
resources:
- ingresses/status
verbs:
- update
---
# Source: nginx-ingress/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
heritage: Helm
release: ingx
name: ingx-nginx-ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingx-nginx-ingress
subjects:
- kind: ServiceAccount
name: ingx-nginx-ingress
namespace: default
---
# Source: nginx-ingress/templates/controller-role.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
heritage: Helm
release: ingx
name: ingx-nginx-ingress
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- update
- watch
- apiGroups:
- extensions
- "networking.k8s.io" # k8s 1.14+
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- "networking.k8s.io" # k8s 1.14+
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
- ingress-controller-leader-nginx
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- create
- get
- update
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
---
# Source: nginx-ingress/templates/controller-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
heritage: Helm
release: ingx
name: ingx-nginx-ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingx-nginx-ingress
subjects:
- kind: ServiceAccount
name: ingx-nginx-ingress
namespace: default
---
# Source: nginx-ingress/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
component: "controller"
heritage: Helm
release: ingx
name: ingx-nginx-ingress-controller
spec:
externalTrafficPolicy: "Local"
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
app: nginx-ingress
component: "controller"
release: ingx
type: "LoadBalancer"
---
# Source: nginx-ingress/templates/default-backend-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
component: "default-backend"
heritage: Helm
release: ingx
name: ingx-nginx-ingress-default-backend
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: nginx-ingress
component: "default-backend"
release: ingx
type: "ClusterIP"
---
# Source: nginx-ingress/templates/controller-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
component: "controller"
heritage: Helm
release: ingx
name: ingx-nginx-ingress-controller
spec:
replicas: 1
revisionHistoryLimit: 10
strategy:
{}
minReadySeconds: 0
template:
metadata:
labels:
app: nginx-ingress
component: "controller"
release: ingx
spec:
dnsPolicy: ClusterFirst
containers:
- name: nginx-ingress-controller
image: "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.1"
imagePullPolicy: "IfNotPresent"
args:
- /nginx-ingress-controller
- --default-backend-service=default/ingx-nginx-ingress-default-backend
- --election-id=ingress-controller-leader
- --ingress-class=nginx
- --configmap=default/ingx-nginx-ingress-controller
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
runAsUser: 33
allowPrivilegeEscalation: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
livenessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
resources:
{}
hostNetwork: false
serviceAccountName: ingx-nginx-ingress
terminationGracePeriodSeconds: 60
---
# Source: nginx-ingress/templates/default-backend-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
component: "default-backend"
heritage: Helm
release: ingx
name: ingx-nginx-ingress-default-backend
spec:
replicas: 1
revisionHistoryLimit: 10
template:
metadata:
labels:
app: nginx-ingress
component: "default-backend"
release: ingx
spec:
containers:
- name: nginx-ingress-default-backend
image: "k8s.gcr.io/defaultbackend-amd64:1.5"
imagePullPolicy: "IfNotPresent"
args:
securityContext:
runAsUser: 65534
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 0
periodSeconds: 5
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
{}
serviceAccountName: ingx-nginx-ingress-backend
terminationGracePeriodSeconds: 60
---
# Source: nginx-ingress/templates/controller-hpa.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.20.0
component: "controller"
heritage: Helm
release: ingx
name: ingx-nginx-ingress-controller
spec:
scaleTargetRef:
apiVersion: apps/v1beta1
kind: Deployment
name: ingx-nginx-ingress-controller
minReplicas: 2
maxReplicas: 100
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 70
- type: Resource
resource:
name: memory
targetAverageUtilization: 70
我怀疑这是因为我最初在没有 omitClusterIP 参数的情况下部署了它,并且 helm v3 正在尝试与原始清单进行 3 向合并,其中确实有clusterIP: ""
helm get manifest ingx --revision 1 | grep "clusterIP"
clusterIP: ""
clusterIP: ""
我能够通过首先删除现有图表来修复它,然后使用omitClusterIP
选项重新创建它。 最重要的是, @bambash建议的解决方法只有在您安装图表时,这些选项从一开始就设置为 true
$ helm upgrade --install ingress-test stable/nginx-ingress --set controller.service.omitClusterIP=true --set defaultBackend.service.omitClusterIP=true
如果 helm v3 中有一种方法可以跳过与现有清单的合并,那就太好了
抱歉,我应该指定在最初安装发行版时需要设置这些值。 更新现有版本可能会更棘手...
我在使用 metric-server-2.8.8 时遇到了这个问题,它的值中没有任何 clusterIP,还有一些其他图表,使用 helm v3.0.0-rc.2。 有什么建议吗? 我不知道如何继续。
我的问题似乎与 helmfile v0.95.0 有关。 我会在那里追求它:)
我有同样的问题,即使我没有使用 helm v3.0.0-rc.2 设置服务类型或 clusterIP,如果我在 helm update --install 命令中使用 --force 选项。 没有 --force 它工作正常
@johannges ,我正要发布相同的内容。 :+1:
设置omitClusterIP: true
似乎适用于defaultBackend和控制器服务,但不适用于指标服务。
我认为这是升级过程中带有--force
选项的 helm 的问题。
Helm 正在尝试重新创建服务,但它也替换了 spec.clusterIP,因此会引发错误。
我可以使用我自己的自定义图表来确认这一点。
Error: UPGRADE FAILED: failed to replace object: Service "litespeed" is invalid: spec.clusterIP: Invalid value: "": field is immutable
实际上这是我的错误,在服务(或图表)的初始化中省略了 clusterIP 定义工作正常👍
对于现有部署的 _kafka_ 和 _redis_ 图表版本,我也遇到了这个错误。 删除--force
确实解决了这个问题。
现在我从 _redis_ 版本中收到一个新错误:
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 forbidden
同意@bacongobbler ,这看起来与 Helm v3 三路合并补丁策略有关,这可能导致将字段(即使具有与以前相同的值)传递给 Kubernetes 在首次创建后认为不可变/不可更改的更新/补丁。
如果有人最终通过 terraform 使用 helm v3,因为您不能直接告诉它不要使用--force
我成功地使用helm delete
手动删除图表,然后重新运行 terraform。 这很糟糕,但确实有效。
编辑:整个错误:(“nginx-ingress-singleton-controller”是我设置的版本名称。它没有具体含义)
Error: cannot patch "nginx-ingress-singleton-controller" with kind Service: Service "nginx-ingress-singleton-controller" is invalid: spec.clusterIP: Invalid value:
"": field is immutable && cannot patch "nginx-ingress-singleton-default-backend" with kind Service: Service "nginx-ingress-singleton-default-backend" is invalid: sp
ec.clusterIP: Invalid value: "": field is immutable
on .terraform/modules/app_dev/nginx-ingress.tf line 1, in resource "helm_release" "nginx_ingress":
1: resource "helm_release" "nginx_ingress" {
@zen4ever在https://github.com/helm/helm/issues/6378#issuecomment -532766512 中解决了这个问题。 我将尝试更详细地解释它......
正如其他人指出的那样,当图表使用空字符串定义 clusterIP 时,就会出现问题。 安装 Service 后,Kubernetes 会使用分配给 Service 的 clusterIP 填充此字段。
当调用helm upgrade
,图表要求删除clusterIP
,因此错误消息为spec.clusterIP: Invalid value: "": field is immutable
。
发生这种情况是由于以下行为:
clusterIP
为空字符串clusterIP
。 我们将在这个例子中使用172.17.0.1
helm upgrade
,图表希望clusterIP
为空字符串(或者在上述@zen4ever的情况下,它被省略)在生成三路补丁时,它看到旧状态为""
,当前状态为"172.17.0.1"
,建议状态为""
。 Helm 检测到用户请求将clusterIP
从“172.17.0.1”更改为“”,因此提供了补丁。
在 Helm 2 中,它忽略了实时状态,因此它没有看到任何变化(旧状态: clusterIP: ""
到新状态: clusterIP: ""
),并且没有生成补丁,绕过了这种行为。
我的建议是更改模板输出。 如果没有提供clusterIP
作为值,则不要将该值设置为空字符串...完全省略该字段。
例如在stable/nginx-ingress
的情况下:
spec:
{{- if not .Values.controller.service.omitClusterIP }}
clusterIP: "{{ .Values.controller.service.clusterIP }}"
{{- end }}
应改为:
spec:
{{- if not .Values.controller.service.omitClusterIP }}
{{ with .Values.controller.service.clusterIP }}clusterIP: {{ quote . }}{{ end }}
{{- end }}
这也是--set controller.service.omitClusterIP=true
在这种情况下起作用的原因。
TL;DR 不要在您的服务模板中执行此操作:
clusterIP: ""
否则,Helm 将尝试将服务的 clusterIP 从自动生成的 IP 地址更改为空字符串,因此会出现错误消息。
希望这可以帮助!
作为临时解决方案,如果您在解决此问题的同时尝试让它立即工作,我发现如果我执行以下操作,我可以执行更新:
kubectl get svc | grep ingress
controller:
service:
clusterIP: <cluster-ip-address-for-controller>
defaultBackend:
service:
clusterIP: <cluster-ip-address-for-default-backend>
我已经为我正在运行的集群测试了这个,它不需要任何娱乐。
这也有效。 好电话@treacher。 通过--set
或在您的值文件中设置相同的值不会生成补丁,因为升级不想更改clusterIP
。
按照上述三路合并补丁行为有意关闭。 操作项是让这些图表遵循 https://github.com/helm/helm/issues/6378#issuecomment-557746499 中提供的建议。 在 Helm 结束时,这里无事可做。 :)
https://github.com/helm/charts/pull/19146/files 已创建! 谢谢@bacongobbler
@zen4ever在#6378(评论)中解决了这个问题。 我将尝试更详细地解释它......
正如其他人指出的那样,当图表使用空字符串定义 clusterIP 时,就会出现问题。 安装 Service 后,Kubernetes 会使用分配给 Service 的 clusterIP 填充此字段。
当调用
helm upgrade
,图表要求删除clusterIP
,因此错误消息为spec.clusterIP: Invalid value: "": field is immutable
。发生这种情况是由于以下行为:
- 在安装时,图表指定它希望
clusterIP
为空字符串- Kubernetes 自动为 Service 分配了
clusterIP
。 我们将在这个例子中使用172.17.0.1
- 在
helm upgrade
,图表希望clusterIP
为空字符串(或者在上述@zen4ever的情况下,它被省略)在生成三路补丁时,它看到旧状态为
""
,当前状态为"172.17.0.1"
,建议状态为""
。 Helm 检测到用户请求将clusterIP
从“172.17.0.1”更改为“”,因此提供了补丁。在 Helm 2 中,它忽略了实时状态,因此它没有看到任何变化(旧状态:
clusterIP: ""
到新状态:clusterIP: ""
),并且没有生成补丁,绕过了这种行为。我的建议是更改模板输出。 如果没有提供
clusterIP
作为值,则不要将该值设置为空字符串...完全省略该字段。例如在
stable/nginx-ingress
的情况下:spec: {{- if not .Values.controller.service.omitClusterIP }} clusterIP: "{{ .Values.controller.service.clusterIP }}" {{- end }}
应改为:
spec: {{- if not .Values.controller.service.omitClusterIP }} {{ with .Values.controller.service.clusterIP }}clusterIP: {{ quote . }}{{ end }} {{- end }}
嗨@bacongobbler ,我认为因为如果没有提供价值,我们仍然会以
clusterIP: ""
......更好的是价值clusterIP: ""
在值文件中完全注释掉。 这会在设置时从呈现的清单中省略它,并且应该可以避免将来的麻烦。 但是,如果使用 helm3 并且当前的 helm 状态设置了clusterIP: ""
,则需要在值文件中对 clusterIP 地址进行硬编码。
这也是
--set controller.service.omitClusterIP=true
在这种情况下起作用的原因。TL;DR 不要在您的服务模板中执行此操作:
clusterIP: ""
否则,Helm 将尝试将服务的 clusterIP 从自动生成的 IP 地址更改为空字符串,因此会出现错误消息。
希望这可以帮助!
嘿@bacongobbler ,我们在将 helm v2 版本迁移到 helm v3 期间遇到了同样的问题。 我们在 Service 中使用type: ClusterIP
但完全省略ClusterIP
,我们得到:
Error: UPGRADE FAILED: failed to replace object: Service "dummy" is invalid: spec.clusterIP: Invalid value: "": field is immutable
我们的 helm 模板中没有spec.clusterIP:
但是在通过 helm 2to3 迁移发布后我们得到了这个错误
服务模板:
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
labels:
app: {{ .Values.image.name }}
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "-" }}
cluster: {{ default "unknown" .Values.cluster }}
region: {{ default "unknown" .Values.region }}
datacenter: {{ default "unknown" .Values.datacenter }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: ClusterIP
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.port }}
protocol: TCP
name: http
selector:
app: {{ .Values.image.name }}
release: {{ .Release.Name }}
同样的问题在这里。 问题是我们还没有触及服务。 升级前更改的是 Ingress。
如果从helm upgrade --install
删除--force
标志并且不接触不可变字段,则它会影响具有不可变字段的资源,一切正常。 但是,如果你想增加资源的 apiversion ??? 您需要重新创建资源,但 helm 3 不会升级资源....
@bacongobbler ^^^
尝试通过 helm 3 使用新的 apiVersion 更新 hpa:
Error: UPGRADE FAILED: rendered manifests contain a new resource that already exists. Unable to continue with update: existing resource conflict: kind: HorizontalPodAutoscaler, namespace: stage, name: dummy-stage
@bacongobbler和@kritcher722拇指clusterIP: ""
是个好主意。
看起来微软是项目的导师。 我看到了风格。 :)
请重新打开。 问题未解决。 nasseemkullah 建议的这种“hack”是不合适的。 不要让人们跳到头上。 修好就行了非常糟糕的迁移路径。 头盔很烂。
@antonakv开始这一年的方式是什么:)
我认为一般来说,我们在提供 clusterIP 作为图表中的可配置值时是在玩火,不能完全责怪一个工具/人/PR。
如果 clusterIP 需要是一个可配置的值,默认情况下它不应该在呈现的模板中,这就是我按照https://github.com/helm/charts/blob/270172836fd8cf56d787cf7d04d938856de0c794/stable在值文件中注释掉的想法
如果我没记错的话,这应该可以防止那些在更改后安装图表的人在未来遇到麻烦。 但是对于我们这些之前安装了它然后迁移到 helm3 的人(包括我自己),恐怕在我们的值文件中硬记录当前 clusterIP 值或卸载并重新安装图表(导致停机!)是我唯一的选择看。
意见是我自己的,我没有报酬来掌舵,只是像你这样的最终用户。 那些全职工作的人可能能够提供更多的见解。
新年快乐,祝你好运! 不要放弃掌舵,我们可以一起让它变得更好。
嘿@bacongobbler ,我们在将 helm v2 版本迁移到 helm v3 期间遇到了同样的问题。 我们在 Service 中使用
type: ClusterIP
但完全省略ClusterIP
,我们得到:
Error: UPGRADE FAILED: failed to replace object: Service "dummy" is invalid: spec.clusterIP: Invalid value: "": field is immutable
我们的 helm 模板中没有
spec.clusterIP:
但是在通过 helm 2to3 迁移发布后我们得到了这个错误服务模板:
apiVersion: v1 kind: Service metadata: name: {{ .Release.Name }} labels: app: {{ .Values.image.name }} chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "-" }} cluster: {{ default "unknown" .Values.cluster }} region: {{ default "unknown" .Values.region }} datacenter: {{ default "unknown" .Values.datacenter }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} spec: type: ClusterIP ports: - port: {{ .Values.service.port }} targetPort: {{ .Values.service.port }} protocol: TCP name: http selector: app: {{ .Values.image.name }} release: {{ .Release.Name }}
我们有同样的问题。 我们根本没有在图表中定义clusterIP
,它也没有出现在最终模板中。 但是,我们仍然遇到相同的错误,并且只有--force
标志。
我们遇到了同样的问题:
apiVersion: v1
kind: Service
{{ include "mde.metadata" $ }}
spec:
ports:
- name: {{ include "mde.portName" $ | quote }}
port: {{ include "mde.port" $ }}
protocol: TCP
targetPort: {{ include "mde.port" $ }}
selector:
app: {{ include "mde.name" $ }}
sessionAffinity: None
type: ClusterIP
spec.clusterIP
不是服务模板的一部分,但在 Helm 3.0.2 和helm upgrade ... --force --install
调用中,我们还看到:
错误:升级失败:无法替换对象:服务“虚拟”无效:spec.clusterIP:无效值:“”:字段不可变
请重新打开。
@tomcruise81请参阅https://github.com/helm/helm/issues/7350以了解--force
上的线程。 这会导致相同的错误,但这是由于kubectl replace
工作方式造成的。 这是一个与此处描述的不同的问题,它与 Service clusterIPs 和三路合并补丁策略( helm upgrade
没有--force
标志)有关。
@bacongobbler - 感谢您的快速回复和澄清。 看着:
https://github.com/helm/helm/blob/a963736f6675e972448bf7a5fd141628fd0ae4df/pkg/kube/client.go#L405 -L411
使用https://github.com/kubernetes/cli-runtime/blob/master/pkg/resource/helper.go#L155 -L181,对helper.Replace
的调用似乎没有与kubectl replace -f ... --force
(注意末尾的--force )。
我猜这是很多混乱的地方。
我知道我对helm upgrade ... --force
期望,它使用的替代策略是它会做与kubectl replace -f ... --force
相同的事情。
嘿@bacongobbler ,我们在将 helm v2 版本迁移到 helm v3 期间遇到了同样的问题。 我们在 Service 中使用
type: ClusterIP
但完全省略ClusterIP
,我们得到:
Error: UPGRADE FAILED: failed to replace object: Service "dummy" is invalid: spec.clusterIP: Invalid value: "": field is immutable
我们的 helm 模板中没有spec.clusterIP:
但是在通过 helm 2to3 迁移发布后我们得到了这个错误
服务模板:apiVersion: v1 kind: Service metadata: name: {{ .Release.Name }} labels: app: {{ .Values.image.name }} chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "-" }} cluster: {{ default "unknown" .Values.cluster }} region: {{ default "unknown" .Values.region }} datacenter: {{ default "unknown" .Values.datacenter }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} spec: type: ClusterIP ports: - port: {{ .Values.service.port }} targetPort: {{ .Values.service.port }} protocol: TCP name: http selector: app: {{ .Values.image.name }} release: {{ .Release.Name }}
我们有同样的问题。 我们根本没有在图表中定义
clusterIP
,它也没有出现在最终模板中。 但是,我们仍然遇到相同的错误,并且只有--force
标志。
我还检查了发布清单中没有clusterIP
:
$ helm get manifest paywall-api-ee | grep clusterIP
$
同样在这里 - 我们没有在任何地方定义ClusterIP
但仍然看到错误
@tomcruise81您可以尝试使用 helm 插件 2to3 并从 helm2 迁移到 helm3 版本并删除--force
如果您以前使用过它)。
这是我们的工作。
至于我,看起来像另一个人--force
有错误的行为,应该像我一样用不可变的字段处理这种情况
@alexandrsemak - 感谢您的推荐。 在我的例子中,我在仅使用 helm 3 安装或升级的图表上看到了这一点。
对我来说同样的问题! 使用
$ helm install my-release xxxxx
$ helm upgrade --install --force my-release xxxxx
就我而言,我没有在图表上使用的任何服务上定义ClusterIP ,但我面临同样的问题(请参阅下面的规范):
spec:
type: {{ .Values.service.type }}
{{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
ports:
- name: htttp-XXX
port: {{ .Values.service.port }}
targetPort: XXX
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort)) }}
nodePort: {{ .Values.service.nodePort }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
selector:
app.kubernetes.io/name: XXX
app.kubernetes.io/instance: {{ .Release.Name }}
正如其他用户之前所说,原因是 Kubernetes 第一次自动为 Service 分配集群IP(例如。 clusterIP: 10.96.26.65
)并且在您尝试升级时与clusterIP: ""
冲突。 请注意,我没有在我的模板上生成这个: clusterIP: ""
请重新打开这个@bacongobbler
我有同样的问题。
@juan131 @Ronsevet : remove --force意思改变了。
在自定义图表上面临同样的问题。
我们没有在任何地方定义 clusterip。
掌舵 v3.0.2
kubectl 1.14.8
问题是,即使 pod 已创建并正在运行,有时图表仍处于失败状态。 如果我们尝试升级同一个版本,它不会在没有力量的情况下工作。
由于 Pod 正在运行,因此无法删除和重新创建发布。
必须有某种方式来使用“强制”
对我来说也是一样 - 我刚刚为服务添加了额外的标签并遇到了这个错误。 我也没有在任何地方定义 ClusterIP - 请重新打开问题
@bacongobbler我们正在部署StorageClasses作为我们图表的一部分,StorageClass 的参数是不可变的。 所以在下一个版本中,当我们更新某些 StorageClass 参数的值时, helm upgrade --force
也会失败。
不确定如何处理 StorageClasses 更新的这种情况。 有什么建议?
Error: UPGRADE FAILED: failed to replace object: StorageClass.storage.k8s.io "ibmc-s3fs-standard-cross-region" is invalid: parameters: Forbidden: updates to parameters are forbidden.
它在 helm v2 中运行良好,因为helm upgrade --force
用于强制删除和重新创建 StorageClass 。
如果有人遇到不是由https://github.com/helm/helm/issues/6378#issuecomment -557746499 中提供的解释导致的症状,请您打开一个新问题,说明您的发现以及我们如何重现它对我们结束了吗?
OP 提出的问题是由于上面提供的场景,其中图表在安装时将 ClusterIP 设置为空字符串。 完全有可能在其他情况下会出现这种特殊情况,例如其他人在使用--force
标志时提到的情况。 这些病例应单独讨论,因为诊断和解决方案可能与之前提供的建议不同。
谢谢!
@mssachan请参阅 #7082 和 #7431 中的草案提案以了解您的用例。 该提案旨在实现kubectl replace —force
,这类似于 Helm 2 的helm install —force
行为。
@mssachan请参阅 #7082 和 #7431 中的草案提案以了解您的用例。 该提案旨在实现
kubectl replace —force
,这类似于 Helm 2 的helm install —force
行为。
发生这种情况很好。 即使省略了--force
标志,我在升级图表时仍然会收到错误消息。 例如,使用cert-manager
:
2020-03-05 12:15:19 CRITICAL: Command returned [ 1 ] exit code and error message [ Error: UPGRADE FAILED: cannot patch "cert-manager-cainjector" with kind Deployment: Deployment.apps "cert-manager-cainjector" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"cainjector", "app.kubernetes.io/instance":"cert-manager", "app.kubernetes.io/managed-by":"Helm", "app.kubernetes.io/name":"cainjector"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable && cannot patch "cert-manager" with kind Deployment: Deployment.apps "cert-manager" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"cert-manager", "app.kubernetes.io/instance":"cert-manager", "app.kubernetes.io/managed-by":"Helm", "app.kubernetes.io/name":"cert-manager"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable && cannot patch "cert-manager-webhook" with kind Deployment: Deployment.apps "cert-manager-webhook" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"webhook", "app.kubernetes.io/instance":"cert-manager", "app.kubernetes.io/managed-by":"Helm", "app.kubernetes.io/name":"webhook"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
@mssachan请参阅 #7082 和 #7431 中的草案提案以了解您的用例。 该提案旨在实现
kubectl replace —force
,这类似于 Helm 2 的helm install —force
行为。发生这种情况很好。 即使省略了
--force
标志,我在升级图表时仍然会收到错误消息。 例如,使用cert-manager
:
2020-03-05 12:15:19 CRITICAL: Command returned [ 1 ] exit code and error message [ Error: UPGRADE FAILED: cannot patch "cert-manager-cainjector" with kind Deployment: Deployment.apps "cert-manager-cainjector" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"cainjector", "app.kubernetes.io/instance":"cert-manager", "app.kubernetes.io/managed-by":"Helm", "app.kubernetes.io/name":"cainjector"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable && cannot patch "cert-manager" with kind Deployment: Deployment.apps "cert-manager" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"cert-manager", "app.kubernetes.io/instance":"cert-manager", "app.kubernetes.io/managed-by":"Helm", "app.kubernetes.io/name":"cert-manager"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable && cannot patch "cert-manager-webhook" with kind Deployment: Deployment.apps "cert-manager-webhook" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"webhook", "app.kubernetes.io/instance":"cert-manager", "app.kubernetes.io/managed-by":"Helm", "app.kubernetes.io/name":"webhook"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
@sc250024将 helm v2 升级到 v3 后,我遇到了完全相同的问题。 升级过程顺利,没有错误,然后我尝试从 helm 升级证书管理器,失败并输出相同。
# helm upgrade cert-manager jetstack/cert-manager --namespace cert-manager --atomic --cleanup-on-fail
# helm version
version.BuildInfo{Version:"v3.1.1", GitCommit:"afe70585407b420d0097d07b21c47dc511525ac8", GitTreeState:"clean", GoVersion:"go1.13.8"}
不使用 --force 时的任何变通方法,或者没有设置clusterIP
周围的任何选项。 这是我的服务清单:
apiVersion: v1
kind: Service
metadata:
name: "{{ .Values.deploymentBaseName }}-{{ .Values.skaffoldUser }}"
labels:
name: "{{ .Values.deploymentBaseName }}-{{ .Values.skaffoldUser }}"
spec:
ports:
- port: {{ .Values.servicePort }}
targetPort: {{ .Values.containerPort }}
protocol: TCP
name: http
- name: debugger-http
port: {{ .Values.debuggerPort }}
targetPort: {{ .Values.debuggerPort }}
protocol: TCP
selector:
app: "{{ .Values.deploymentBaseName }}-{{ .Values.skaffoldUser }}"
type: ClusterIP
@davidfernandezm你有没有找到解决方案? 我看到了同样的情况,我的服务定义与您的完全相同。 没有设置clusterIP
选项,但 Helm 仍然无法升级。
同样在这里
也得到这个,re:以上两条评论。
请提供更多信息。 如果不了解原因或此问题如何在您的案例中出现,我们将无法为您提供帮助。 谢谢。
我有同样的问题,即使我没有使用 helm v3.0.0-rc.2 设置服务类型或 clusterIP,如果我在 helm update --install 命令中使用 --force 选项。 没有 --force 它工作正常
凉爽的! 我从你的回答中得到启发,我必须在 helmfile yaml 中评论force: ..
行:
helmDefaults:
tillerless: true
verify: false
wait: true
timeout: 600
# force: true <---- THI ONE IS COMMENTED
它有效🎉
我尝试了上述所有方法,没有一个对我有用。 我不得不从我的图表中禁用nginx-ingress
,进行升级,再次启用,然后再次升级。 这导致云提供商分配的 IP 地址发生变化,但没有造成任何伤害。
我有同样的问题,即使我没有使用 helm v3.0.0-rc.2 设置服务类型或 clusterIP,如果我在 helm update --install 命令中使用 --force 选项。 没有 --force 它工作正常
最佳解决方案,它对我有用,谢谢!
我们遇到了同样的问题,找不到任何解决方法。
重现非常简单
helm install in stable/inbucket
helm upgrade in stable/inbucket
Error: UPGRADE FAILED: cannot patch "in-inbucket" with kind Service: Service "in-inbucket" is invalid: spec.clusterIP: Invalid value: "": field is immutable
我想知道为什么--force
在这里不起作用,如果这是替换策略,它不应该force resource updates through a replacement strategy
那么应该删除然后替换该服务吗?
@bacongobbler在检查了https://github.com/helm/helm/issues/7956后,我得到了这个线程
与之前的所有评论者一样:我们在模板中根本没有“clusterIP”,但如果使用 --force 标志,最新的 Helm 仍然存在错误。
头盔版本:3.4.1
“helm -n kube-system get manifest CHART_NAME | grep clusterIP”没有显示结果。
错误:
field is immutable && failed to replace object: Service "SERVICE_NAME" is invalid: spec.clusterIP: Invalid value: "": field is immutable
https://github.com/helm/helm/issues/6378#issuecomment -557746499 中提供的相同解释也适用于您的案例@nick4fake。 不同之处在于,使用--force
,您要求 Kubernetes 获取完全渲染的清单并强制覆盖当前活动对象。 由于您的清单不包含clusterIP
字段,Kubernetes 会接受并假设您正在尝试从活动对象中删除clusterIP
字段,因此会出现错误Invalid value: "": field is immutable
。
@bacongobbler如果我在这里遗漏了一些东西,我真的很抱歉,也许我只是对 Helm 内部了解不够。
“我的建议是更改模板输出。如果没有提供 clusterIP 作为值,则不要将该值设置为空字符串......完全省略该字段。”
那么解决方案是什么? 这是否意味着如果 clusterIP 字段未设置为某个静态值,则根本无法使用“--force”标志?
就 Kubernetes 而言:是的。
根据我的理解,这是 Kubernetes 的一个问题,因为“强行覆盖”与“删除并重新创建”的行为方式不同。 是否有任何上游错误?
另一方面,Helm 也具有误导性,因为--force
被描述为“通过替换策略强制资源更新”。 虽然实际上它不做任何替换,它只是试图强行覆盖资源(最好将标志命名为--force-overwrite
)。 强制替换看起来像是再次删除和重新创建(可能有一个标志--force-recreate
)。 当然,将--force-recreate
用于某些资源可能有点危险,但它总会成功。
无论如何,Helm 可以为此类问题实施后备解决方法。 如果当前行为(描述为--force-overwrite
)失败并检测到不可变字段错误,它应该删除并重新创建资源(如--force-recreate
)。
最有用的评论
我有同样的问题,即使我没有使用 helm v3.0.0-rc.2 设置服务类型或 clusterIP,如果我在 helm update --install 命令中使用 --force 选项。 没有 --force 它工作正常