做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
注意:以前我当时使用的是旧版本(服务器,kubectl,helm),当时我没有遇到这种问题。 我可以在GitHub上看到很多与此类似的问题,但是找不到适合我的解决方案。
一些类似的问题:
https://github.com/kubernetes/kubernetes/issues/25241
https://github.com/helm/charts/pull/13646 [对于Nginx图表]
答案 0 :(得分:10)
我已经对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,模拟舵升级命令无 --force
标志:
Here是kubectl补丁文档,如果想了解使用方法。
kubectl patch svc test-svc -p '{"spec":{"type":"LoadBalancer"}}'
然后您会看到:
service/test-svc patched
您应该在不使用helm upgrade
的情况下使用--force
,它将起作用。
例如,如果您确实需要使用--force
来重新创建一些资源,例如pod来获取最新的configMap
更新,那么我建议您在Helm升级之前首先手动更改服务规格。 / p>
如果您尝试更改服务类型,则可以导出服务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
并且对该服务没有任何更改,它将可以正常工作并重新创建您的pod和其他资源。
希望对您有所帮助!