LabHub
学习 学习路径 课程

CKA — Kubernetes 管理员

用 CRD 把 API 拓宽

在 LabHub 中继续学习

目标

亲手编写 CustomResourceDefinition 来扩展 Kubernetes API,确认 schema 验证会真正拒绝请求,并通过 Aggregated ClusterRole 为新资源添加权限。

为什么这很重要

CKA 考试范围包含 CRD,并不是要求你编写 operator,而是考查你能否运维已经安装了 operator 的集群。实际集群中通常已经安装了数十个 CRD。

这里需要理解一个结构:创建 CRD 后,apiserver 会出现新的 endpoint,并提供存储、验证和 watch 功能。但仅此而已。 真正执行操作的是 watch 该 CR 的控制器,而控制器是独立软件。如果创建 CR 后没有任何事情发生,通常是因为控制器不存在或已经停止运行。

schema 也是同一道理。在 apiextensions.k8s.io/v1 中,schema 不是可选项,而是必需项。schema 就是该 API 的契约,错误值会先被 apiserver 阻止,而不是留给控制器处理。

步骤

  1. 创建 CRD widgets.labhub.io。group 为 labhub.io,scope 为 Namespaced,kind 为 Widget,plural 为 widgets,singular 为 widget,shortNames 中包含 wg;只有一个版本 v1alpha1,served 与 storage 均为 true。
  2. 创建 namespace cka-crd,并在其中创建 Widget demospec.replicas 为 3,spec.tiersmall
  3. 修改 CRD 的 v1alpha1 schema,加入验证规则。spec.replicas 的 type 为 integer,minimum 为 1,maximum 为 10。spec.tier 的 type 为 string,enum 为 [small, large]。spec 对象的 required 为 [replicas, tier]
  4. 尝试创建 spec.replicas 为 99 的 Widget too-big,并将拒绝错误输出保存到 /root/cka-crd/reject.txttoo-big 不应被创建。
  5. 为 v1alpha1 添加两个 additionalPrinterColumns。名称 REPLICAS(type 为 integer,jsonPath 为 .spec.replicas);名称 TIER(type 为 string,jsonPath 为 .spec.tier)。
  6. 创建 CRD clusterwidgets.labhub.io。scope 为 Cluster,kind 为 ClusterWidget,plural 为 clusterwidgets,group 为 labhub.io,版本为 v1alpha1。然后创建 ClusterWidget global
  7. 创建 ClusterRole cka-widget-viewer。添加标签 rbac.labhub.io/aggregate-to-widget=true,规则允许对 apiGroups labhub.io 中的 widgets 执行 getlistwatch。然后创建 ClusterRole cka-widget-aggregate,使其 aggregationRule 通过选择器选择该标签。

参考

创建 CustomResourceDefinition

创建 CRD widgets.labhub.io。group 为 labhub.io,scope 为 Namespaced,kind 为 Widget,plural 为 widgets,singular 为 widget,shortNames 中包含 wg;只有一个版本 v1alpha1,served 与 storage 均为 true。

CRD 的 metadata.name 必须采用“复数形式.组”的格式。在 apiextensions.k8s.io/v1 中,versions 数组的每一项都必须包含 schema。

创建自定义资源

创建 namespace cka-crd,并在其中创建 Widget demospec.replicas 为 3,spec.tiersmall

CR 的 apiVersion 格式为“组/版本”。schema 较宽松时可以加入任意字段,因此一开始允许 spec 下的未知字段会更方便。

在 schema 中加入验证规则

修改 CRD 的 v1alpha1 schema,加入验证规则。spec.replicas 的 type 为 integer,minimum 为 1,maximum 为 10。spec.tier 的 type 为 string,enum 为 [small, large]。spec 对象的 required 为 [replicas, tier]

在 openAPIV3Schema 的 properties.spec.properties 下,为每个字段设置 type 和 minimum/maximum/enum。required 不是字段值,而是该对象层级中的数组。

确认验证拒绝请求的瞬间

尝试创建 spec.replicas 为 99 的 Widget too-big,并将拒绝错误输出保存到 /root/cka-crd/reject.txttoo-big 不应被创建。

错误输出写入标准错误,而不是标准输出。重定向时不要忘记 2>&1。被拒绝的资源不应创建,这才是正常结果。

为 kubectl get 输出添加列

为 v1alpha1 添加两个 additionalPrinterColumns。名称 REPLICAS(type 为 integer,jsonPath 为 .spec.replicas);名称 TIER(type 为 string,jsonPath 为 .spec.tier)。

additionalPrinterColumns 位于 versions 数组的各个版本内部。需要 name、type、jsonPath 三个字段,且 jsonPath 以点号开头。

创建集群作用域 CRD

创建 CRD clusterwidgets.labhub.io。scope 为 Cluster,kind 为 ClusterWidget,plural 为 clusterwidgets,group 为 labhub.io,版本为 v1alpha1。然后创建 ClusterWidget global

创建 CRD 后无法修改 scope。集群作用域资源不接受 -n 选项。

通过 Aggregated ClusterRole 扩展权限

创建 ClusterRole cka-widget-viewer。添加标签 rbac.labhub.io/aggregate-to-widget=true,规则允许对 apiGroups labhub.io 中的 widgets 执行 getlistwatch。然后创建 ClusterRole cka-widget-aggregate,使其 aggregationRule 通过选择器选择该标签。

不要直接编写带有 aggregationRule 的 ClusterRole 的 rules。控制器会查找带标签的其他 ClusterRole 并将其规则合并。