随着Kubernetes版本的迭代发布,很多HelmChart包根本跟不上更新进度,导致很多HelmChart包在使用较新版本的Kubernetes时不兼容,所以我们在开发HelmChart包时有必要考虑与不同版本的Kubernetes的兼容性。实现不同版本兼容的核心是利用HelmChart模板提供的内置对象Capabilities。该对象提供了Kubernetes集群支持功能的信息,包括以下功能:Capabilities.APIVersions获取集群版本集Capabilities.APIVersions.Has$version判断是版本(如batch/v1)还是资源(如apps/v1/Deployment)在集群中可用Capabilities.KubeVersion和Capabilities.KubeVersion.Version可以获得Kubernetes版本号版本细节,与helm版本的输出一致Capabilities.HelmVersion.Version是当前Helm版本的语义格式Capabilities.HelmVersion.GitCommitHelm的gitsha1值Capabilities.HelmVersion.GitTreeState是Helmgit树的状态。Capabilities.HelmVersion.GoVersion使用Go编译器的版本。使用上述对象,我们可以确定资源对象需要使用的API版本或属性。我们以Ingress资源对象为例。阐明。Kubernetes在1.19版本引入了新的Ingress资源API:networking.k8s.io/v1,与上一版networking.k8s.io/v1beta1beta基本相同,但与上一版extensions相同/v1beta1在使用上有很大区别,资源对象的属性也有一定区别。因此,为了兼容不同的版本,我们需要对模板中的Ingress对象进行兼容处理。新版本的资源对象格式如下:apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:minimal-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/spec:rules:-http:paths:-path:/testpathpathType:Prefixbackend:service:name:testport:number:80旧版本的资源对象格式如下:apiVersion:extensions/v1beta1kind:Ingressmetadata:name:minimal-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/spec:rules:-http:paths:-path:/testpathbackend:serviceName:testservicePort:80使用哪种格式的资源对象取决于我们的集群版本。首先,我们在Chart包的_helpers.tpl文件中添加几个判断集群版本或API的命名模板:{{/*AllowKubeVersiontobeoverridden.*/}}{{-define"ydzs.kubeVersion"-}}{{-default.Capabilities.KubeVersion.Version.Values.kubeVersionOverride-}}{{-end-{{/*GetIngressAPIVersion*/}}{{-定义“ydzs.ingress.apiVersion”-}}{{-ifand(.Capabilities.APIVersions.Has"networking.k8s.io/v1")(semverCompare">=1.19-0"(include"ydzs.kubeVersion".))-}}{{-print"networking.k8s.io/v1"-}}{{-elseif.Capabilities.APIVersions.Has"networking.k8s.io/v1beta1"-}}{{-print"networking.k8s.io/v1beta1"-}}{{-else-}}{{-print"扩展/v1beta1"-}}{{-end-}}{{-end-}}{{/*CheckIngressstability*/}}{{-define"ydzs.ingress.isStable"-}}{{-eq(include"ydzs.ingress.apiVersion".)"networking.k8s.io/v1"-}}{{-end-}}{{/*CheckIngresssupportspathType*/}}{{/*pathTypewasaddedtonetnetworking.k8s.io/v1beta1inKubernetes1.18*/}}{{-定义“ydzs.ingress.supportsPathType”-}}{{-或(eq(包括“ydzs.ingress.isStable”。)“true”)(和(eq(包括“ydzs.ingress.apiVersion”".)"networking.k8s.io/v1beta1")(semverCompare">=1.18-0"(include"ydzs.kubeVersion".)))-}}{{-end-}}上面我们传递.Capabilities.APIVersions.必须确定我们应该使用的APIVersion。如果版本是networking.k8s.io/v1,则定义为isStable。另外,还要根据版本判断是否需要支持pathType属性,然后可以在Ingress对象模板中使用上面的定义命名模板,来判断应该使用哪些属性,如下图ingress.yaml文件:{{-$apiIsStable:=eq(include"ydzs.ingress.isStable".)"true"-}}{{-$ingressSupportsPathType:=eq(include"ydzs.ingress.supportsPathType".)"true"-}}{{-$ingressClass:=index.Values"ingress-nginx""controller""ingressClass"}}apiVersion:{{include"ydzs.ingress.apiVersion".}}kind:Ingressmetadata:name:portal-ingressannotations:{{-if$ingressClass}}kubernetes.io/ingress.class:{{$ingressClass}}{{-end}}nginx.ingress.kubernetes.io/proxy-connect-timeout:"120"nginx.ingress.kubernetes.io/代理读取超时:“3600”nginx.ingress.kubernetes.io/代理发送超时:“3600”nginx.ingress.kubernetes.io/ssl-redirect:“false”标签:{{-include"ydzs.labels".|nindent4}}spec:rules:{{-ifeq.Values.endpoint.type"FQDN"}}-host:{{required".Values.endpoint.FQDNisrequiredforFQDN".Values.endpoint.FQDN}}http:{{-else}}-http:{{-end}}paths:-path:/{{-if$ingressSupportsPathType}}pathType:Prefix{{-end}}backend:{{-if$apiIsStable}}service:name:portalport:number:80{{-else}}serviceName:portalservicePort:80{{-end}}在Ingress模板中,通过命名模板中的变量来决定应该使用哪些属性,这样我们定义的Chart模板就可以兼容不同版本的Kubernetes。如果其他版本之间有差异,我们也可以单独判断定义即其他资源对象,如Deployment,也可以用同样的方式兼容
