LabHub
学习 学习路径 课程

CNPA — 云原生平台工程助理

用 CRD 造平台 API

在 LabHub 中继续学习

目标

扩展 Kubernetes API,亲手创建名为 WebService 的平台 API,并在真实集群中完整实现 schema 验证、服务端默认值、租户边界和自助式 RBAC。

为什么重要

如果把平台 API 做成企业内部 Web 应用,就必须重新实现状态存储、并发控制、身份认证与授权、审计和 watch。注册 CRD 后,这些能力会全部随之而来——这就是 Kubernetes API 成为平台通用语言的原因。OpenAPI schema 尤其能以最低成本实现自助服务三要素中的“快速反馈”。只需一行 maximum: 10,错误请求就不会等到 30 分钟后才出现在流水线日志中,而会立即以人能读懂的语句被拒绝。default 同样能够让服务器强制应用“安全的默认值”。但仅有 CRD 还不能构成完整平台——只有同时具备租户之间互不侵犯的边界(命名空间、配额和 RBAC),才能真正做到无需工单即可授予权限。本实验中的所有资源都是 Kubernetes 内置资源,因此会实际应用,并通过 kubectl 评分。

步骤

  1. /root/cnpa-platform/crd.yaml 中编写并应用 CustomResourceDefinition——设置 metadata.name: webservices.platform.labhub.iospec.group: platform.labhub.iospec.scope: Namespacedspec.names 中 kind 为 WebService、plural 为 webservices、singular 为 webservice、shortNames 第一项为 ws;版本 v1alpha1 设置 served: truestorage: true
  2. 完成同一 CRD 的 v1alpha1 schema——在 spec 对象中定义 image(string,必填)、replicas(integer,default: 2minimum: 1maximum: 10)、public(boolean,default: false)。然后在 additionalPrinterColumns 中添加两列:名称 Image(jsonPath .spec.image,type string)和 Replicas(jsonPath .spec.replicas,type integer)。
  3. 创建命名空间 tenant-blue——添加标签 platform.labhub.io/tenant: bluepod-security.kubernetes.io/enforce: baseline
  4. tenant-blue 中创建 ResourceQuota tenant-blue-quota——设置 requests.cpu: "2"requests.memory: 4Gilimits.cpu: "4"limits.memory: 8Gipods: "10"。在同一命名空间中创建 LimitRange tenant-blue-limits——type 为 Containerdefault 中 cpu 为 200m、memory 为 256MidefaultRequest 中 cpu 为 100m、memory 为 128Mi
  5. tenant-blue 中创建 WebService shop——只写 spec.image: ghcr.io/labhub/shop:1.0.0不要写 replicaspublic。创建后重新读取,确认这两个值已经自动填充。
  6. 验证 schema 违规会被拒绝。尝试创建 spec.replicas: 20 的 WebService bad,并将其放在 tenant-blue 中,并将失败输出(包括标准错误)保存到 /root/cnpa-platform/reject.txtbad 不得残留在集群中。
  7. 创建 ServiceAccount blue-dev,并将其放在 tenant-blue 中,并在同一命名空间中创建 Role webservice-editor(apiGroups 为 platform.labhub.io、resources 为 webservices、verbs 为 get,list,watch,create,update,patch,delete)和 RoleBinding blue-devs(将该 Role 绑定到 blue-dev ServiceAccount)。不要授予修改配额的权限。
  8. 按照相同模式创建第二个租户——命名空间 tenant-green(标签 platform.labhub.io/tenant: green)、ResourceQuota tenant-green-quota(包含 pods: "10"),以及 WebService apispec.image: ghcr.io/labhub/api:1.0.0,不指定 replicas)。tenant-blue 中的 blue-dev 不应有权在 tenant-green 中创建 WebService。

参考

注册 CRD——组、作用域与名称

/root/cnpa-platform/crd.yaml 中编写并应用 CustomResourceDefinition——设置 metadata.name: webservices.platform.labhub.iospec.group: platform.labhub.iospec.scope: Namespacedspec.names 中 kind 为 WebService、plural 为 webservices、singular 为 webservice、shortNames 第一项为 ws;版本 v1alpha1 设置 served: truestorage: true

CRD 名称必须采用 <복수형>.<그룹> 格式。这是由租户创建的资源,请谨慎选择作用域。

Schema 与打印列

完成同一 CRD 的 v1alpha1 schema——在 spec 对象中定义 image(string,必填)、replicas(integer,default: 2minimum: 1maximum: 10)、public(boolean,default: false)。然后在 additionalPrinterColumns 中添加两列:名称 Image(jsonPath .spec.image,type string)和 Replicas(jsonPath .spec.replicas,type integer)。

OpenAPI v3 schema 附加在 versions 数组中的各个版本上。请区分 required、minimum/maximum 和 default 各自应写在哪里。打印列也需要按版本定义。

租户命名空间

创建命名空间 tenant-blue——添加标签 platform.labhub.io/tenant: bluepod-security.kubernetes.io/enforce: baseline

命名空间本身就是租户边界。请同时添加表示归属关系的标签和 Pod 安全标准标签。

ResourceQuota 与 LimitRange

tenant-blue 中创建 ResourceQuota tenant-blue-quota——设置 requests.cpu: "2"requests.memory: 4Gilimits.cpu: "4"limits.memory: 8Gipods: "10"。在同一命名空间中创建 LimitRange tenant-blue-limits——type 为 Containerdefault 中 cpu 为 200m、memory 为 256MidefaultRequest 中 cpu 为 100m、memory 为 128Mi

两者职责不同:一个限制命名空间的资源总量,另一个规定单个容器的默认值和范围。只有两者同时存在,“未填写 requests 的 Pod”才能通过配额检查。

创建 CR 与服务端默认值

tenant-blue 中创建 WebService shop——只写 spec.image: ghcr.io/labhub/shop:1.0.0不要写 replicaspublic。创建后重新读取,确认这两个值已经自动填充。

完全不要填写 replicas,直接创建。重新读取已保存的对象时,其中应当已经有该值。

确认 schema 违规会被拒绝

验证 schema 违规会被拒绝。尝试创建 spec.replicas: 20 的 WebService bad,并将其放在 tenant-blue 中,并将失败输出(包括标准错误)保存到 /root/cnpa-platform/reject.txtbad 不得残留在集群中。

尝试使用超出范围的值创建资源,并把产生的错误消息保存到文件中。标准错误也必须一并保存。

自助权限与防护栏

创建 ServiceAccount blue-dev,并将其放在 tenant-blue 中,并在同一命名空间中创建 Role webservice-editor(apiGroups 为 platform.labhub.io、resources 为 webservices、verbs 为 get,list,watch,create,update,patch,delete)和 RoleBinding blue-devs(将该 Role 绑定到 blue-dev ServiceAccount)。不要授予修改配额的权限。

现有 RBAC 同样适用于新资源。确认规则中的 apiGroups 和 resources 应填写什么,并保持配额不可修改。

第二个租户与隔离证明

按照相同模式创建第二个租户——命名空间 tenant-green(标签 platform.labhub.io/tenant: green)、ResourceQuota tenant-green-quota(包含 pods: "10"),以及 WebService apispec.image: ghcr.io/labhub/api:1.0.0,不指定 replicas)。tenant-blue 中的 blue-dev 不应有权在 tenant-green 中创建 WebService。

把同一种模式再应用一次,才称得上平台。同时,第一个租户的权限不应触及第二个租户。