[执行helm upgrade ... --force
时出现以下错误
Error: UPGRADE FAILED: failed to replace object: Service "api" is invalid: spec.clusterIP: Invalid value: "": field is immutable
而且这就是我的服务文件的样子:(未在任何地方传递clusterIP)
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]
服务器:1.14
Note:以前我当时使用的是旧版本(服务器,kubectl,helm),当时我没有遇到这种问题。我可以在GitHub上看到很多与此类似的问题,但是找不到适合我的解决方案。
很少有类似问题:
https://github.com/kubernetes/kubernetes/issues/25241
https://github.com/helm/charts/pull/13646 [对于Nginx图表]
我已经使用Helm进行了一些测试,并在尝试将服务类型从NodePort/ClusterIP
更改为LoadBalancer
时遇到了相同的问题。
这是我转载您的问题的方式:
Kubernetes 1.15.3(GKE)头盔 3.1.1
用于测试的头盔图:stable/nginx-ingress
helm fetch stable/nginx-ingress
tar xzvf nginx-ingress-1.33.0.tgz
type: LoadBalancer
文件中将服务类型从type: NodePort
修改为values.yaml
(第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
LoadBalancer
中的服务类型再次修改为values.yaml
:sed -i '271s/NodePort/LoadBalancer/' values.yaml
--force
标志升级图表: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 source code:中发现了此问题>
// 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上面的代码将使用类似于
kubectl replace
api请求(而不是我们期望的kubectl replace --force
)...设置了Helm--force
标志时。
如果不是,那么Helm将使用kubectl patch
api请求进行升级。
让我们检查一下是否有意义:
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
:
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,模拟头盔升级命令without
--force
标志:[Here是kubectl修补程序文档,如果想了解如何使用。
kubectl patch svc test-svc -p '{"spec":{"type":"LoadBalancer"}}'
然后您会看到:
service/test-svc patched
您应在不使用helm upgrade
的情况下使用--force
,它将起作用。
例如,如果您确实确实需要使用--force
来重新创建某些资源,例如吊舱以获取最新的configMap
更新,那么我建议您在Helm升级之前首先手动更改服务规格。
如果您尝试更改服务类型,则可以导出服务yaml
,更改类型并再次应用(因为只有在我第一次尝试应用相同的模板时,我才遇到此现象):
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
并且对该服务没有任何更改,它将可以使用并重新创建您的广告连播和其他资源。
希望对您有所帮助!