已弃用的 Kubernetes API

Kubernetes 是一个 API 驱动的系统,API 随着时间的推移而发展,以反映对问题空间的不断理解。 这是跨系统及其 API 的常见做法。 API 发展的重要组成部分是良好的弃用策略和流程,以告知用户 API 如何实施更改。 换句话说,API 的使用者需要提前知道 API 将在哪个版本中被移除或更改。 这消除了使用者对意外更改和破坏性更改的担忧。

Kubernetes 弃用策略 文档说明了 Kubernetes 如何处理其 API 版本的更改。 弃用策略规定了 API 版本在弃用公告后将支持的时间范围。 因此,务必了解弃用公告,并了解 API 版本将何时被移除,以最大程度地减少影响。

这是一个示例公告 有关 Kubernetes 1.16 中已弃用 API 版本的移除,并在发布前几个月发布。 这些 API 版本在此之前再次宣布弃用。 这表明有一个良好的策略到位,可以告知使用者 API 版本支持情况。

Helm 模板在定义 Kubernetes 对象时指定 Kubernetes API 组,类似于 Kubernetes 清单文件。 它在模板的 apiVersion 字段中指定,用于标识 Kubernetes 对象的 API 版本。 这意味着 Helm 用户和图表维护者需要了解 Kubernetes API 版本何时被弃用,以及它们将在哪个 Kubernetes 版本中被移除。

图表维护者

您应该审核图表,检查 Kubernetes API 版本是否已弃用或已在 Kubernetes 版本中移除。 应将找到的由于即将移除或不再支持的 API 版本更新到支持的版本,并发布图表的新版本。 API 版本由 kindapiVersion 字段定义。 例如,以下是 Kubernetes 1.16 中移除的 Deployment 对象 API 版本

apiVersion: apps/v1beta1
kind: Deployment

Helm 用户

您应该审核您使用的图表(类似于 图表维护者),并识别任何在 Kubernetes 版本中已弃用或移除的 API 版本的图表。 对于已识别的图表,您需要检查图表的最新版本(具有支持的 API 版本),或者自己更新图表。

此外,您还需要审核已部署的任何图表(即 Helm 发布),再次检查是否有任何已弃用或移除的 API 版本。 这可以通过使用 helm get manifest 命令获取发布的详细信息来完成。

将 Helm 发布更新到支持的 API 的方法取决于您的发现,如下所示

  1. 如果您只找到已弃用的 API 版本,则
  • 执行 helm upgrade,使用具有支持的 Kubernetes API 版本的图表版本
  • 在升级中添加说明,例如不要回滚到此当前版本之前的 Helm 版本
  1. 如果您找到任何在 Kubernetes 版本中移除的 API 版本,则
  • 如果您运行的是 Kubernetes 版本,其中 API 版本仍然可用(例如,您运行的是 Kubernetes 1.15,并且发现您使用的是将在 Kubernetes 1.16 中移除的 API),则
    • 按照步骤 1 的过程进行
  • 否则(例如,您已经运行的是 Kubernetes 版本,其中 helm get manifest 报告的某些 API 版本不再可用),则
    • 您需要编辑存储在集群中的发布清单,以将 API 版本更新到支持的 API。 有关更多详细信息,请参见 更新发布清单的 API 版本

注意:在所有使用支持的 API 更新 Helm 发布的情况下,您永远不要将发布回滚到具有支持的 API 的发布版本之前的版本。

建议:最佳实践是在升级到移除这些 API 版本的 Kubernetes 集群之前,将使用已弃用 API 版本的发布升级到支持的 API 版本。

如果您没有按照前面的建议更新发布,则在尝试在 Kubernetes 版本中升级发布时,您将遇到类似于以下的错误,其中其 API 版本已移除

Error: UPGRADE FAILED: current release manifest contains removed kubernetes api(s)
for this kubernetes version and it is therefore unable to build the kubernetes
objects for performing the diff. error from kubernetes: unable to recognize "":
no matches for kind "Deployment" in version "apps/v1beta1"

Helm 在这种情况下失败,因为它试图在当前部署的发布(包含在该 Kubernetes 版本中移除的 Kubernetes API)与您传递的具有更新/支持的 API 版本的图表之间创建差异补丁。 失败的根本原因是,当 Kubernetes 移除 API 版本时,Kubernetes Go 客户端库将无法再解析已弃用的对象,因此 Helm 在调用库时失败。 不幸的是,Helm 无法从这种情况中恢复,并且不再能够管理此类发布。 有关如何从这种情况中恢复的更多详细信息,请参见 更新发布清单的 API 版本

更新发布清单的 API 版本

清单是 Helm 发布对象的属性,它存储在集群中 Secret(默认)或 ConfigMap 的 data 字段中。 data 字段包含一个 gzip 压缩的对象,该对象经过 Base64 编码(对于 Secret,还有一个额外的 Base64 编码)。 在发布的命名空间中,每个发布版本/修订都有一个 Secret/ConfigMap。

您可以使用 Helm mapkubeapis 插件执行发布到支持的 API 的更新。 查看自述文件以了解更多详细信息。

或者,您可以按照以下手动步骤执行发布清单的 API 版本更新。 根据您的配置,您将按照 Secret 或 ConfigMap 后端的步骤进行操作。

  • 获取与最新部署的发布关联的 Secret 或 Configmap 的名称
    • Secrets 后端:kubectl get secret -l owner=helm,status=deployed,name=<release_name> --namespace <release_namespace> | awk '{print $1}' | grep -v NAME
    • ConfigMap 后端:kubectl get configmap -l owner=helm,status=deployed,name=<release_name> --namespace <release_namespace> | awk '{print $1}' | grep -v NAME
  • 获取最新部署的发布详细信息
    • Secrets 后端:kubectl get secret <release_secret_name> -n <release_namespace> -o yaml > release.yaml
    • ConfigMap 后端:kubectl get configmap <release_configmap_name> -n <release_namespace> -o yaml > release.yaml
  • 备份发布,以防万一出现问题需要恢复
    • cp release.yaml release.bak
    • 在紧急情况下,恢复:kubectl apply -f release.bak -n <release_namespace>
  • 解码发布对象
    • Secrets 后端:cat release.yaml | grep -oP '(?<=release: ).*' | base64 -d | base64 -d | gzip -d > release.data.decoded
    • ConfigMap 后端:cat release.yaml | grep -oP '(?<=release: ).*' | base64 -d | gzip -d > release.data.decoded
  • 更改清单的 API 版本。 可以使用任何工具(例如编辑器)进行更改。 这在解码的发布对象(release.data.decoded)的 manifest 字段中
  • 编码发布对象
    • Secrets 后端:cat release.data.decoded | gzip | base64 | base64
    • ConfigMap 后端:cat release.data.decoded | gzip | base64
  • 将部署的发布文件(release.yaml)中的 data.release 属性值替换为新的编码发布对象
  • 将文件应用于命名空间:kubectl apply -f release.yaml -n <release_namespace>
  • 执行 helm upgrade,使用具有支持的 Kubernetes API 版本的图表版本
  • 在升级中添加说明,例如不要回滚到此当前版本之前的 Helm 版本