错误:升级失败:无法替换对象:服务"api"无效:spec.clusterIP:无效值:“":字段是不可变的 [英] Error: UPGRADE FAILED: failed to replace object: Service "api" is invalid: spec.clusterIP: Invalid value: "": field is immutable

查看:744
本文介绍了错误:升级失败:无法替换对象:服务"api"无效:spec.clusterIP:无效值:“":字段是不可变的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行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

  1. 获取并解压缩文件:

helm fetch stable/nginx-ingress  
tar xzvf nginx-ingress-1.33.0.tgz  

  1. values.yaml文件中将服务类型从type: LoadBalancer修改为type: NodePort(第271行):
  1. Modify service type from type: LoadBalancer to type: NodePort in the values.yaml file (line 271):

sed -i '271s/LoadBalancer/NodePort/' values.yaml

  1. 安装图表:

helm install nginx-ingress ./

  1. 检查服务类型,必须为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

  1. 现在将values.yaml中的服务类型再次修改为LoadBalancer:
  1. Now modify the Service type again to LoadBalancer in the values.yaml:

sed -i '271s/NodePort/LoadBalancer/' values.yaml

  1. 最后,尝试使用--force标志升级图表:
  1. 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:

  1. 使用NodePort创建简单的服务:
  1. 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

您应该使用不带--forcehelm 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆