如何在 Helm Chart 中兼容不同的 Kubernetes 版本?

运维 系统运维
很多 Helm Chart 包压根跟不上更新的进度,导致在使用较新版本的 Kubernetes 的时候很多 Helm Chart 包不兼容,所以我们在开发 Helm Chart 包的时候有必要考虑到对不同版本的 Kubernetes 进行兼容。

 [[434481]]

随着 Kubernetes 的版本不断迭代发布,很多 Helm Chart 包压根跟不上更新的进度,导致在使用较新版本的 Kubernetes 的时候很多 Helm Chart 包不兼容,所以我们在开发 Helm Chart 包的时候有必要考虑到对不同版本的 Kubernetes 进行兼容。

要实现对不同版本的兼容核心就是利用 Helm Chart 模板提供的内置对象 Capabilities,该对象提供了关于 Kubernetes 集群支持功能的信息,包括如下特性:

  • Capabilities.APIVersions 获取集群版本集合
  • Capabilities.APIVersions.Has $version 判断集群中的某个版本 (e.g., batch/v1) 或是资源 (e.g., apps/v1/Deployment) 是否可用
  • Capabilities.KubeVersion 和 Capabilities.KubeVersion.Version 可以获取 Kubernetes 版本号
  • Capabilities.KubeVersion.Major 获取 Kubernetes 的主版本
  • Capabilities.KubeVersion.Minor 获取 Kubernetes 的次版本
  • Capabilities.HelmVersion 包含 Helm 版本详细信息的对象,和 helm version 的输出一致
  • Capabilities.HelmVersion.Version 是当前 Helm 版本的语义格式
  • Capabilities.HelmVersion.GitCommit Helm 的 git sha1 值
  • Capabilities.HelmVersion.GitTreeState 是 Helm git 树的状态
  • Capabilities.HelmVersion.GoVersion 使用的 Go 编译器版本

利用上面的几个对象我们可以判断资源对象需要使用的 API 版本或者属性,下面我们以 Ingress 资源对象为例进行说明。

Kubernetes 在 1.19 版本为 Ingress 资源引入了一个新的 API:networking.k8s.io/v1,这与之前的 networking.k8s.io/v1beta1 beta 版本使用方式基本一致,但是和前面的 extensions/v1beta1 这个版本在使用上有很大的不同,资源对象的属性上有一定的区别,所以要兼容不同的版本,我们就需要对模板中的 Ingress 对象做兼容处理。

新版本的资源对象格式如下所示:

  1. apiVersion: networking.k8s.io/v1 
  2. kind: Ingress 
  3. metadata: 
  4.   name: minimal-ingress 
  5.   annotations: 
  6.     nginx.ingress.kubernetes.io/rewrite-target: / 
  7. spec: 
  8.   rules: 
  9.   - http: 
  10.       paths: 
  11.       - path: /testpath 
  12.         pathType: Prefix 
  13.         backend: 
  14.           service: 
  15.             name: test 
  16.             port: 
  17.               number: 80 

而旧版本的资源对象格式如下:

  1. apiVersion: extensions/v1beta1 
  2. kind: Ingress 
  3. metadata: 
  4.   name: minimal-ingress 
  5.   annotations: 
  6.     nginx.ingress.kubernetes.io/rewrite-target: / 
  7. spec: 
  8.   rules: 
  9.   - http: 
  10.       paths: 
  11.       - path: /testpath 
  12.         backend: 
  13.           serviceName: test 
  14.           servicePort: 80 

具体使用哪种格式的资源对象需要依赖我们的集群版本,首先我们在 Chart 包的 _helpers.tpl 文件中添加几个用于判断集群版本或 API 的命名模板:

  1. {{/* Allow KubeVersion to be overridden. */}} 
  2. {{- define "ydzs.kubeVersion" -}} 
  3.   {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} 
  4. {{- end - 
  5.  
  6. {{/* Get Ingress API Version */}} 
  7. {{- define "ydzs.ingress.apiVersion" -}} 
  8.   {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "ydzs.kubeVersion" .)) -}} 
  9.       {{- print "networking.k8s.io/v1" -}} 
  10.   {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} 
  11.     {{- print "networking.k8s.io/v1beta1" -}} 
  12.   {{- else -}} 
  13.     {{- print "extensions/v1beta1" -}} 
  14.   {{- end -}} 
  15. {{- end -}} 
  16.  
  17. {{/* Check Ingress stability */}} 
  18. {{- define "ydzs.ingress.isStable" -}} 
  19.   {{- eq (include "ydzs.ingress.apiVersion" .) "networking.k8s.io/v1" -}} 
  20. {{- end -}} 
  21.  
  22. {{/* Check Ingress supports pathType */}} 
  23. {{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}} 
  24. {{- define "ydzs.ingress.supportsPathType" -}} 
  25.   {{- or (eq (include "ydzs.ingress.isStable" .) "true") (and (eq (include "ydzs.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "ydzs.kubeVersion" .))) -}} 
  26. {{- end -}} 

上面我们通过 .Capabilities.APIVersions.Has 来判断我们应该使用的 APIVersion,如果版本为 networking.k8s.io/v1,则定义为 isStable,此外还根据版本来判断是否需要支持 pathType 属性,然后在 Ingress 对象模板中就可以使用上面定义的命名模板来决定应该使用哪些属性,如下 ingress.yaml 文件所示:

  1. {{- $apiIsStable := eq (include "ydzs.ingress.isStable" .) "true" -}} 
  2. {{- $ingressSupportsPathType := eq (include "ydzs.ingress.supportsPathType" .) "true" -}} 
  3. {{- $ingressClass := index .Values "ingress-nginx" "controller" "ingressClass" }} 
  4. apiVersion: {{ include "ydzs.ingress.apiVersion" . }} 
  5. kind: Ingress 
  6. metadata: 
  7.   name: portal-ingress 
  8.   annotations: 
  9.     {{- if $ingressClass }} 
  10.     kubernetes.io/ingress.class: {{ $ingressClass }} 
  11.     {{- end }} 
  12.     nginx.ingress.kubernetes.io/proxy-connect-timeout: "120" 
  13.     nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" 
  14.     nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" 
  15.     nginx.ingress.kubernetes.io/ssl-redirect: "false" 
  16.   labels: 
  17.     {{- include "ydzs.labels" . | nindent 4 }} 
  18. spec: 
  19.   rules: 
  20.   {{- if eq .Values.endpoint.type "FQDN" }} 
  21.   - host: {{ required ".Values.endpoint.FQDN is required for FQDN" .Values.endpoint.FQDN }} 
  22.     http: 
  23.   {{- else }} 
  24.   - http: 
  25.   {{- end }} 
  26.       paths: 
  27.       - path: / 
  28.         {{- if $ingressSupportsPathType }} 
  29.         pathType: Prefix 
  30.         {{- end }} 
  31.         backend: 
  32.           {{- if $apiIsStable }} 
  33.           service: 
  34.             name: portal 
  35.             port: 
  36.               number: 80 
  37.           {{- else }} 
  38.           serviceName: portal 
  39.           servicePort: 80 
  40.           {{- end }} 

在 Ingress 模板中使用命名模板中的变量来判断应该使用哪些属性,这样我们定义的这个 Chart 模板就可以兼容 Kubernetes 的不同版本了,如果还有其他版本之间的差异,我们也可以分别判断进行定义即可,对于其他的资源对象,比如 Deployment 也可以用同样的方式进行兼容。

 

责任编辑:姜华 来源: k8s技术圈
相关推荐

2023-04-06 10:08:58

2018-08-23 09:56:03

Linux程序版本

2020-07-13 07:00:21

Kubernetes

2022-06-27 05:48:24

Kubernetes容器

2020-07-20 07:00:00

KubernetesHostPath

2022-02-24 16:48:53

SnapLinux

2019-07-30 10:33:01

2018-12-03 16:00:22

Linux屏幕设置壁纸

2023-07-29 11:54:44

KuberneteNFS

2010-03-18 14:36:46

Java线程同步

2019-07-12 16:28:32

MacKubernetes

2019-03-29 09:00:31

Kubernetes开发者工具

2019-09-02 13:57:07

Helm Chart工具Kubernetes

2017-03-21 11:42:29

Linux安装Python 3.6

2023-10-31 08:32:59

2020-12-15 08:00:00

KubernetesDocker容器

2015-04-01 13:51:49

2023-04-28 17:53:09

Kubernetes沙盒Signadot

2023-11-02 11:15:01

容器Kubernetes

2021-05-28 17:59:37

K8sDNS解析CoreDNS
点赞
收藏

51CTO技术栈公众号