错误:升级失败:无法替换对象:服务"api"无效:spec.clusterIP:无效值:“":字段是不可变的 [英] Error: UPGRADE FAILED: failed to replace object: Service "api" is invalid: spec.clusterIP: Invalid value: "": field is immutable
问题描述
执行helm upgrade ... --force
时出现以下错误
Error: UPGRADE FAILED: failed to replace object: Service "api" is invalid: spec.clusterIP: Invalid value: "": field is immutable
这就是我的服务文件的样子:(未在任何地方传递clusterIP)
And This is how my service file looks like: (Not passing clusterIP anywhere )
apiVersion: v1
kind: Service
metadata:
name: {{ .Chart.Name }}
namespace: {{ .Release.Namespace }}
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
labels:
app: {{ .Chart.Name }}-service
kubernetes.io/name: {{ .Chart.Name | quote }}
dns: route53
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
spec:
selector:
app: {{ .Chart.Name }}
type: LoadBalancer
ports:
- port: 443
name: https
targetPort: http-port
protocol: TCP
头盔版本: 3.0.1
Kubectl 版本: 1.13.1 [也尝试过 1.17.1 ]
Kubectl Version: 1.13.1 [Tried with the 1.17.1 as well]
服务器: 1.14
注意:以前,我当时使用的是旧版本(服务器,kubectl,helm),当时我没有遇到这种问题. 我可以在GitHub上看到很多与此类似的问题,但是找不到适合我的解决方案.
Note: Previously I was using some old version (of server, kubectl, helm) at that time I did not face this kind of issue. I can see lots of similar issues in GitHub regarding this, but unable to find any working solution for me.
一些类似的问题:
https://github.com/kubernetes/kubernetes/issues/25241
https://github.com/helm/charts/pull/13646 [对于Nginx图表]
https://github.com/helm/charts/pull/13646 [For Nginx chart]
推荐答案
我已经对Helm进行了一些测试,并在尝试将服务类型从NodePort/ClusterIP
更改为LoadBalancer
时遇到了同样的问题.
I've made some tests with Helm and got the same issue when trying to change the Service type from NodePort/ClusterIP
to LoadBalancer
.
这是我转载您的问题的方式:
This is how I've reproduced your issue:
Kubernetes 1.15.3(GKE) 头盔 3.1.1
Kubernetes 1.15.3 (GKE) Helm 3.1.1
用于测试的头盔图表: stable/nginx-ingress
Helm chart used for test: stable/nginx-ingress
- 获取并解压缩文件:
helm fetch stable/nginx-ingress
tar xzvf nginx-ingress-1.33.0.tgz
- 在
values.yaml
文件中将服务类型从type: LoadBalancer
修改为type: NodePort
(第271行):
- Modify service type from
type: LoadBalancer
totype: NodePort
in thevalues.yaml
file (line 271):
sed -i '271s/LoadBalancer/NodePort/' values.yaml
- 安装图表:
helm install nginx-ingress ./
- 检查服务类型,必须为
NodePort
:
kubectl get svc -l app=nginx-ingress,component=controller
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-controller NodePort 10.0.3.137 <none> 80:30117/TCP,443:30003/TCP 1m
- 现在将
values.yaml
中的服务类型再次修改为LoadBalancer
:
- Now modify the Service type again to
LoadBalancer
in thevalues.yaml
:
sed -i '271s/NodePort/LoadBalancer/' values.yaml
- 最后,尝试使用
--force
标志升级图表:
- Finally, try to upgrade the chart using
--force
flag:
helm upgrade nginx-ingress ./ --force
然后:
Error: UPGRADE FAILED: failed to replace object: Service "nginx-ingress-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable
说明
我在HELM中发现了这个问题源代码:
// if --force is applied, attempt to replace the existing resource with the new object.
if force {
obj, err = helper.Replace(target.Namespace, target.Name, true, target.Object)
if err != nil {
return errors.Wrap(err, "failed to replace object")
}
c.Log("Replaced %q with kind %s for kind %s\n", target.Name, currentObj.GetObjectKind().GroupVersionKind().Kind, kind)
} else {
// send patch to server
obj, err = helper.Patch(target.Namespace, target.Name, patchType, patch, nil)
if err != nil {
return errors.Wrapf(err, "cannot patch %q with kind %s", target.Name, kind)
}
}
在设置helm --force
标志时,分析Helm上面的代码将使用类似于kubectl replace
api请求(而不是我们期望的kubectl replace --force
)....
Analyzing the code above Helm will use similar to kubectl replace
api request (instead of kubectl replace --force
as we could expect)... when the helm --force
flag is set.
否则,Helm将使用kubectl patch
api请求进行升级.
If not, then Helm will use kubectl patch
api request to make the upgrade.
让我们检查一下是否有意义:
Let's check if it make sense:
- 使用
NodePort
创建简单的服务:
- Create a simple service as
NodePort
:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
app: test-svc
name: test-svc
spec:
selector:
app: test-app
ports:
- port: 80
protocol: TCP
targetPort: 80
type: NodePort
EOF
创建服务:
kubectl get svc -l app=test-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test-svc NodePort 10.0.7.37 <none> 80:31523/TCP 25
现在,让我们尝试使用kubectl replace
将服务升级到LoadBalancer
,例如helm upgrade --force
:
Now lets try to use kubectl replace
to upgrade the service to LoadBalancer
, like helm upgrade --force
:
kubectl replace -f - <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
app: test-svc
name: test-svc
spec:
selector:
app: test-app
ports:
- port: 80
protocol: TCP
targetPort: 80
type: LoadBalancer
EOF
这显示了错误:
The Service "test-svc" is invalid: spec.clusterIP: Invalid value: "": field is immutable
现在,让我们使用kubectl patch
将NodePort更改为LoadBalancer,模拟舵升级命令不 --force
标志:
Now, lets use kubectl patch
to change the NodePort to LoadBalancer, simulating the helm upgrade command without --force
flag:
此处是kubectl补丁文档,如果想看看如何使用.
Here is the kubectl patch documentation, if want to see how to use.
kubectl patch svc test-svc -p '{"spec":{"type":"LoadBalancer"}}'
然后您会看到:
service/test-svc patched
您应该使用不带--force
的helm upgrade
,它将起作用.
You should to use helm upgrade
without --force
, it will work.
例如,如果您确实需要使用--force
来重新创建一些资源(例如,吊舱以获取最新的configMap
更新),那么我建议您在Helm升级之前首先手动更改服务规格.
If you really need to use --force
to recreate some resources, like pods to get the latest configMap
update, for example, then I suggest you first manually change the service specs before Helm upgrade.
如果您尝试更改服务类型,则可以导出服务yaml
,更改类型并再次应用(因为仅当我第一次尝试应用相同的模板时,我才遇到此现象) :
If you are trying to change the service type you could do it exporting the service yaml
, changing the type and apply it again (because I experienced this behavior only when I tried to apply the same template from the first time):
kubectl get svc test-svc -o yaml | sed 's/NodePort/LoadBalancer/g' | kubectl replace --force -f -
输出:
service "test-svc" deleted
service/test-svc replaced
现在,如果您尝试使用helm upgrade --force
并且对该服务没有任何更改,它将可以正常工作并重新创建您的pod和其他资源.
Now, if you try to use helm upgrade --force
and doesn't have any change to do in the service, it will work and will recreate your pods and others resources.
希望对您有所帮助!
这篇关于错误:升级失败:无法替换对象:服务"api"无效:spec.clusterIP:无效值:“":字段是不可变的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!