Kubernetes 弃用策略

    Kubernetes 是一个组件众多、贡献者人数众多的大系统。 就像很多类似的软件,所提供的功能特性集合会随着时间推移而自然发生变化, 而且有时候某个功能特性可能需要被去除。被去除的可能是一个 API、一个参数标志或者 甚至某整个功能特性。为了避免影响到现有用户,Kubernetes 对于其中渐次移除 的各个方面规定了一种弃用策略并遵从此策略。

    由于 Kubernetes 是一个 API 驱动的系统,API 会随着时间推移而演化,以反映 人们对问题共建的认识的变化。Kubernetes API 实际上是一个 API 集合,其中每个 成员称作“API 组(API Group)”,并且每个 API 组都是独立管理版本的。 会有 三类,每类有不同的废弃策略:

    给定的 Kubernetes 发布版本中可以支持任意数量的 API 组,且每组可以包含 任意个数的版本。

    下面的规则负责指导 API 元素的弃用,具体元素包括:

    • REST 资源(也即 API 对象)
    • REST 资源的字段
    • REST 资源的注解,包含“beta”类注解但不包含“alpha”类注解
    • 枚举值或者常数值
    • 组件配置结构

    以下是跨正式发布版本时要实施的规则,不适用于对 master 或发布分支上 不同提交之间的变化。

    规则 #1:只能在增加 API 组版本号时删除 API 元素。

    一旦在某个特定 API 组版本中添加了 API 元素,则该元素不可从该版本中删除, 且其行为也不能大幅度地变化,无论属于哪一类(GA、Alpha 或 Beta)。

    规则 #2:在给定的发布版本中,API 对象必须能够在不同的 API 版本之间来回 转换且不造成信息丢失,除非整个 REST 资源在某些版本中完全不存在。

    例如,一个对象可被用 v1 来写入之后用 v2 来读出并转换为 v1,所得到的 v1 必须 与原来的 v1 对象完全相同。v2 中的表现形式可能与 v1 不同,但系统知道如何 在两个版本之间执行双向转换。 此外,v2 中添加的所有新字段都必须能够转换为 v1 再转换回来。这意味着 v1 必须 添加一个新的等效字段或者将其表现为一个注解。

    规则 #3:给定类别的 API 版本在新的、稳定性未降低的 API 版本发布之前不可被废弃。

    一个正式发布的(GA)API 版本可替换现有的正式 API 版本或 alpha、beta API 版本。 Beta API 版本 不可以 替代正式的 API 版本。

    规则 #4a:除了每类 API 版本中的最新版本,旧的 API 版本在其被宣布被废弃之后 至少以下时长内仍需被支持:

    • Beta: 9 个月或者 3 个发布版本(取其较长者)
    • Alpha: 0 个发布版本

    这里也包含了关于最大支持 2 个发布版本的版本偏差的约定。

    说明: 在被解决之前, 已经被保存到持久性存储中的 API 版本都不可以被去除。 你可以禁止这些版本所对应的 REST 末端(在符合本文中弃用时间线的前提下), 但是 API 服务器必须仍能解析和转换存储中以前写入的数据。

    用户必须能够升级到 Kubernetes 新的发行版本,之后再回滚到前一个发行版本,且 整个过程中无需针对新的 API 版本做任何转换,也不允许出现功能损坏的情况, 除非用户显式地使用了仅在较新版本中才存在的功能特性。 就对象的存储表示而言,这一点尤其是不言自明的。

    以上所有规则最好通过例子来说明。假定现有 Kubernetes 发行版本为 X,其中引入了 新的 API 组。大约每隔 3 个月会有一个新的 Kubernetes 版本被发布(每年 4 个版本)。 下面的表格描述了在一系列后续的发布版本中哪些 API 版本是受支持的。

    发布版本API 版本优选/存储版本注释
    Xv1alpha1v1alpha1
    X+1v1alpha2v1alpha2
    • v1alpha1 被去除,发布说明中会包含 “action required(采取行动)” 说明
    X+2v1beta1v1beta1
    • v1alpha2 被去除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+3v1beta2、v1beta1(已弃用)v1beta1
    • v1beta1 被弃用,发布说明中包含对应的 “action required(采取行动)” 说明
    X+4v1beta2、v1beta1(已弃用)v1beta2
    X+5v1、v1beta1(已弃用)、v1beta2(已弃用)v1beta2
    • v1beta2 被弃用,发布说明中包含对应的 “action required(采取行动)” 说明
    X+6v1、v1beta2(已弃用)v1
    • v1beta1 被去除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+7v1、v1beta2(已弃用)v1
    X+8v2alpha1、v1v1
    • v1beta2 被去除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+9v2alpha2、v1v1
    • v2alpha1 被删除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+10v2beta1、v1v1
    • v2alpha2 被删除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+11v2beta2、v2beta1(已弃用)、v1v1
    • v2beta1 被弃用,发布说明中包含对应的 “action required(采取行动)” 说明
    X+12v2、v2beta2(已弃用)、v2beta1(已弃用)、v1(已弃用)v1
    • v2beta2 已被弃用,发布说明中包含对应的 “action required(采取行动)” 说明
    • v1 已被弃用,发布说明中包含对应的 “action required(采取行动)” 说明
    X+13v2、v2beta1(已弃用)、v2beta2(已弃用)、v1(已弃用)v2
    X+14v2、v2beta2(已弃用)、v1(已弃用)v2
    • v2beta1 被删除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+15v2、v1(已弃用)v2
    • v2beta2 被删除,发布说明中包含对应的 “action required(采取行动)” 说明
    X+16v2、v1(已弃用)v2
    X+17v2v2

      考虑一个假想的名为 Widget 的 REST 资源,在上述时间线中位于 API v1, 而现在打算将其弃用。 我们会在文档和 声明 中与 X+1 版本的发布同步记述此弃用决定。 Wdiget 资源仍会在 API 版本 v1(已弃用)中存在,但不会出现在 v2alpha1 中。 Widget 资源会 X+8 发布版本之前(含 X+8)一直存在并可用。 只有在发布版本 X+9 中,API v1 寿终正寝时,Widget 才彻底消失,相应的资源行为也被移除。

      从 Kubernetes v1.19 开始,当 API 请求被发送到一个已弃用的 REST API 末端时:

      1. API 响应中会包含一个 头部字段(如 所定义);

      2. 该请求会导致对应的 审计事件 中会增加一个注解 "k8s.io/deprecated":"true"

      3. kube-apiserver 进程的 度量值会被 设置为 1。 该度量值还附带 group、、resourcesubresource 标签 (可供添加到度量值 上), 和一个 removed_release 标签,标明该 API 将消失的 Kubernetes 发布版本。 下面的 Prometheus 查询会返回对 v1.22 中将移除的、已弃用的 API 的请求的信息:

      REST 资源的字段

      就像整个 REST 资源一样,在 API v1 中曾经存在的各个字段在 API v1 被移除 之前必须一直存在且起作用。 与整个资源上的规定不同,v2 API 可以选择为字段提供不同的表示方式, 只要对应的资源对象可在不同版本之间来回转换即可。 例如,v1 版本中一个名为 “magnitude” 的已弃用字段可能在 API v2 中被命名 为 “deprecatedMagnitude”。当 v1 最终被移除时,废弃的字段也可以从 v2 中移除。

      就像前文讲述的 REST 资源及其中的单个字段一样,API v1 中所支持的常数值 必须在 API v1 被移除之前一直存在且起作用。

      组件配置结构

      组件的配置也是有版本的,并且按 REST 资源的方式来管理。

      随着时间推移,Kubernetes 会引入粒度更细的 API 版本。 到那时,这里的规则会根据需要进行调整。

      Kubernetes 系统中包含若干不同的、相互协作的程序。 有时,Kubernetes 可能会删除这些程序的某些标志或 CLI 命令(统称“命令行元素”)。 这些程序可以天然地划分到两个大组中:面向用户的和面向管理员的程序。 二者之间的弃用策略略有不同。 除非某个标志显示地通过前缀或文档来标明其为“alpha”或“beta”, 该标志要被视作正式发布的(GA)。

      命令行元素相当于系统的 API 的一部分,不过因为它们并没有采用 REST API 一样的方式来管理版本,其弃用规则规定如下:

      规则 #5a:面向用户的命令行元素(例如,kubectl)必须在其宣布被弃用其 在以下时长内仍能使用:

      • GA:12 个月或者 2 个发布版本(取其较长者)
      • Beta:3 个月或者 1 个发布版本(取其较长者)
      • Alpha:0 发布版本

      规则 #5b:面向管理员的命令行元素(例如,kubelet)必须在其被宣布弃用 之后以下时长内保持可用:

      • GA:6 个月或 1 个发行版本(取其较长者)
      • Beta: 3 个月或 1 个发行版本(取其较长者)
      • Alpha: 0 个发布版本

      在一些较偶然的情形下,某 Kubernetes 发行版本需要弃用系统的某项功能 特性或者行为,而对应的功能特性或行为并不受 API 或 CLI 控制。在这种情况下, 其弃用规则如下:

      规则 #7:被弃用的行为必须在被宣布弃用之后至少 1 年时间内必须保持能用。

      这并不意味着对系统的所有更改都受此策略约束。 此规则仅适用于重大的、用户可见的行为;这些行为会影响到在 Kubernetes 中运行的应用的正确性,或者影响到 Kubernetes 集群的管理。 此规则也适用于那些被整个移除的功能特性或行为。

      上述规则的一个例外是 特性门控(Feature Gates)。特性门控是一些键值偶对, 允许用户启用或禁用一些试验性的功能特性。

      特性门控意在覆盖功能特性的整个开发周期,它们无意成为长期的 API。 因此,它们会在某功能特性正式发布或被抛弃之后被弃用和删除。

      随着一个功能特性经过不同的成熟阶段,相关的特性门控也会演化。 与功能特性生命周期对应的特性门控状态为:

      • Alpha:特性门控默认被禁用,只能由用户显式启用。
      • Beta:特性门控默认被弃用,可被用户显式禁用。
      • GA: 特性门控被弃用(参见),并且不再起作用。
      • GA,弃用窗口期结束:特性门控被删除,不再接受调用。

      弃用

      功能特性在正式发布之前的生命周期内任何时间点都可被移除。 当未正式发布的功能特性被移除时,它们对应的特性门控也被弃用。

      当尝试禁用一个不再起作用的特性门控时,该调用会失败,这样可以避免 毫无迹象地执行一些不受支持的场景。

      在某些场合,移除一个即将正式发布的功能特性需要很长时间。特性门控 可以保持其功能,直到对应的功能特性被彻底去除,直到那时特性门控 自身才可被弃用。

      由于移除一个已经正式发布的功能特性对应的特性门控也需要一定时间,对特性 门控的调用可能一直被允许,前提是特性门控对功能本身无影响且特性门控不会 引发任何错误。

      意在允许用户禁用的功能特性应该包含一个在相关联的特性门控中禁用该功能的机制。

      特性门控的版本管理与之前讨论的组件版本管理不同,因此其对应的弃用策略如下:

      规则 #8:特性门控所对应的功能特性经历下面所列的成熟性阶段转换时,特性门控 必须被弃用。特性门控弃用时必须在以下时长内保持其功能可用:

      • Beta 特性转为 GA:6 个月或者 2 个发布版本(取其较长者)
      • Beta 特性转为丢弃:3 个月或者 1 个发布版本(取其较长者)

      规则 #9:已弃用的特色门控再被使用时必须给出警告回应。当特性门控被 弃用时,必须在发布说明和对应的 CLI 帮助信息中通过文档宣布。 警告信息和文档都要标明是否某特性门控不再起作用。

      没有策略可以覆盖所有情况。此策略文档是一个随时被更新的文档,会随着时间 推移演化。在实践中,会有一些情况无法很好地匹配到这里的弃用策略,或者 这里的策略变成了很严重的羁绊。这类情形要与 SIG 和项目牵头人讨论, 寻求对应场景的最佳解决方案。请一直铭记,Kubernetes 承诺要成为一个 稳定的系统,至少会尽力做到不会影响到其用户。此弃用策略的任何例外情况 都会在所有相关的发布说明中公布。