K8S API的使用和管理

API 组和扩展

Kubernetes API 由不同的groups组成。这些组允许:

  • 可预测的 API 模式

  • 用户逐步采用功能

  • 独立定义资源范围和成熟度

  • 特定用例的唯一 API 路径(例如 pod/logs)

最初,Kubernetes API 没有组(group)。此功能后来被命名为核心组。由于资源和版本号之间的紧密耦合,核心组中的资源被证明很难扩展。由于所有资源都在一条/apis/$VERSION/ 路径下,用户很难使用不同版本的资源并保持控制器之间的兼容性。开发 API 需要更多版本来扩展资源,并且在添加第三方资源 (TPR) 之前无法扩展 API。随着客户和供应商开始采用 TPR,各种缺点得到解决,随后TPR 被CustomResourceDefinitions (CRD)取代 。

我们可以使用 apiextensions.k8s.io 组来创建自己的自定义资源 (CR),这将创建全新的组以供使用。这是一个示例,用于创建版本为 v1alpha1, 资源类型为 sock , 组为 mine.k8s.io的对象。

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: socks.mine.k8s.io
spec:
group: mine.k8s.io
versions:
- name: v1alpha1
names:
kind: Sock
plural: socks
scope: Namespaced

通过向 Kubernetes API 提交少量数据,我们将获得以下 API:

1
/apis/mine.k8s.io/v1alpha1/namespaces/$NAMESPACE/socks/$SOCK

我们可以通过kubectl get socks –all-namespaces命令,检查我们拥有哪些 sock 资源。这些构造使 API 足够灵活,可以针对未知用例进行扩展,并且足够简单。

CRD 与聚合

Custom Resources允许Kubernetes API识别自定义资源,而API路径是kubernetes-api主进程的一部分。我们还可以使用聚合 API服务器扩展 Kubernetes API 以声明特定路径(例如,/apis/socks.mine.co/v1)。两者主要区别在于聚合API将请求代理到Kubernetes服务端点。这意味着我们需要在集群内运行负责状态存储和版本生命周期的服务。

版本和生命周期

版本作为 URL 路径的一部分,并定义了关于事物如何从一个版本变化到另一个版本的指南。这些版本将显示在我们的 yaml 文件中 apiVersion 中的组名之后。

Kubernetes 遵循 alpha → beta → stable 的成熟度进程,并带有一些额外的版本控制,因此资源可以迭代而无需进入下一个成熟度级别。

  • Alpha API 是实验性的。它们可能有错误和向后不兼容的更改。默认情况下它们不启用,你应该谨慎使用它们。

  • Beta API 已经过良好测试并默认启用。它们可以依赖于未来的功能,但它们的实现可能会根据用户反馈或可扩展性等约束而改变。

  • 稳定的 API 。它们用一个版本(例如,v1)表示,并且它们的实现不应该在不更改版本号的情况下进行重大更改。

当 Kubernetes API 被弃用时,通常意味着它的一个版本不再可用。绝大多数弃用的发生是因为:

  • 资源方案更改(例如,v1beta1 → v1beta2)。

  • API 变得更加稳定(例如,v1alpha2 → v1beta1)。

  • 组名称已更改(例如,入口从 extensions/v1beta1 移至networking.k8s.io/v1beta1)。

弃用意味着 API 的某个版本已被删除,你需要在清单和资源中验证你使用的API版本是否正确。在某些情况下,你可能需要更改资源字段。如果一个API同时有多个版本可用,Kubernetes API可以为你默默地升级其中的一些。但是,你仍然应该确保拥有正确的资源方案——尤其是随着 alpha API 的成熟,方案可能会在不同版本之间发生变化。

处理升级和弃用

对于创建的自定义资源,以下是处理升级和弃用的方法。首先是测试CR的升级,以确保控制器能够使用自定义资源以及 Kubernetes API 组和版本正常运行。当针对scheme和 API 版本更改更新控制器时,可能需要更新 CR 定义,也可能不需要更新。CustomResourceDefinitions可以在其规范中定义多个版本。这种方法允许 Kubernetes API 同时为多个版本提供服务。

使用我们之前版本v1alpha1 的socks示例,如果我们还想提供 API 的 v1beta1 版本,我们可以定义它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: socks.mine.k8s.io
spec:
group: mine.k8s.io
versions:
- name: v1alpha1
served: true
storage: false
schema: ...
- name: v1beta1
served: true
storage: true
schema: ...
names:
kind: Sock
plural: socks
scope: Namespaced

上述定义了/apsi/mine.k8s.io/v1alpha1//apis/mine.k8s.io/v1beta1/将同时提供API服务。当一个新的“sock”对象被创建时,它会作为 v1beta1 存储在 etcd 中,因为storage: true在v1beta1版本下。与此同时,etcd 中只能存储一个版本。

如果你的版本方案有更改,则需要在将资源提交给 API 时对其进行修改。此步骤通过转换 webhook处理 。webhook 负责读取资源并将方案转换为不同的版本并将其发送回 API 服务器。你可以像这样将转换 webhook 规范添加到你的 CR:

1
conversion: strategy: Webhook webhook: clientConfig: url: "https://socks.converter.example/convert-me"

任何时候在 Kubernetes API 服务器中创建 sock 资源时,其规范都会发送到指定的 URL 进行转换。转换 webhook 应该对资源执行任何必要的操作,并将其作为 ConversionReview 对象发送回 API 服务器。使用 webhooks 进行转换可以非常灵活地管理 CR 生命周期,并让你可以根据需要缓慢地从一个版本迁移到另一个版本。

更新所有资源后,你可以通过在 CR 定义版本中使用 deprecated: true来弃用旧版本。不推荐使用的版本仍将由 API 提供服务,但当使用不推荐使用的版本将资源提交给 API 服务器时,它们将打印警告。