欢迎光临
我们一直在努力

Kubernetes CRD(自定义资源,CustomResourceDefinition)详解

Kubernetes CRD(自定义资源,CustomResourceDefinition)详解

robot1

文章目录

  • Kubernetes CRD(自定义资源,CustomResourceDefinition)详解
    • 1. 引言
    • 2. 基本概念
    • 3. CRD 的工作原理
    • 4. 如何创建 CRD
    • 5. 使用 CRD
    • 6. 控制器模式
    • 7. 高级特性
      • 7.1 版本管理
      • 7.2 子资源
      • 7.3 验证和默认值
      • 7.4 附加打印列
      • 7.5 最终确定器 (Finalizers)
    • 8. 实际应用场景
    • 9. 最佳实践和注意事项
    • 10. 总结

1. 引言

Kubernetes 是一个可扩展的平台,其核心 API 提供了诸如 Pod、Service、Deployment 等丰富的内置资源,用于管理容器化应用。然而,在实际业务中,我们往往需要表达一些 Kubernetes 原生不支持的领域概念,例如数据库实例、消息队列主题、应用配置策略等。CustomResourceDefinition (CRD) 正是 Kubernetes 提供的一种机制,允许用户在不修改核心代码的情况下,向 Kubernetes API 中添加自定义的资源类型,从而将 Kubernetes 打造成一个通用的、可编程的应用平台。

CRD 是 Kubernetes API 扩展的事实标准,与 Operator 模式紧密结合,成为构建云原生基础设施和应用的关键技术。

2. 基本概念

CRD 本身是 Kubernetes API 中的一个内置资源类型(位于 apiextensions.k8s.io/v1 API 组)。通过创建一个 CRD 对象,你向 Kubernetes 声明了一种新的、用户自定义的资源类型。此后,你就可以像操作 Pod 一样,通过 kubectl 或直接调用 API 来创建、查看、更新和删除这种新资源的实例。

  • CustomResourceDefinition (CRD):定义一种新的资源类型的元数据,包括资源名称、API 组、版本、作用域(Namespaced 或 Cluster)以及结构验证规则等。
  • Custom Resource (CR):根据 CRD 定义创建出来的具体资源对象,代表某个领域实体的实例。

例如,你可以定义一个名为 Database 的 CRD,然后创建 database-sample 这样的 CR 来代表一个具体的数据库实例。

3. CRD 的工作原理

CRD 的实现基于 Kubernetes API 服务器的扩展能力。当你创建一个 CRD 对象时,API Server 会自动注册一个新的 RESTful 路径,用于处理该自定义资源的请求。其工作流程大致如下:

  • 用户创建 CRD:用户提交一个 CRD YAML 到 Kubernetes API。
  • API Server 动态注册:API Server 解析 CRD,验证其合法性,然后在内部存储中注册新的资源类型。这相当于在 API Server 的路由表中增加了一条规则,将 /<api-group>/<version>/namespaces/<namespace>/<resource-plural> 路径映射到新的资源处理逻辑。
  • 存储支持:自定义资源的数据同样存储在 etcd 中,与内置资源一样享受高可用和一致性保证。API Server 负责对 CR 进行请求认证、鉴权、验证(根据 CRD 中定义的 OpenAPI schema)以及持久化。
  • 用户操作 CR:此后,用户可以通过标准的 Kubernetes API 或 kubectl 来操作自定义资源。例如 kubectl get databases 或 kubectl describe database database-sample。
  • 控制器协调:通常,CRD 会配合一个控制器(Controller)一起工作。控制器监听自定义资源的变化,并根据 CR 的期望状态(Spec)执行相应的业务逻辑,最终更新资源的状态(Status)。这一模式正是 Kubernetes 声明式 API 的精髓。
  • 4. 如何创建 CRD

    创建一个 CRD 需要编写 YAML 清单,并通过 kubectl apply 提交。以下是一个简化的 CRD 示例,定义了一个名为 Database 的自定义资源:

    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
    name: databases.example.com 必须格式:<plural>.<group>
    spec:
    group: example.com API 组
    versions:
    name: v1alpha1 版本
    served: true 是否在该版本上提供服务
    storage: true 是否将数据存储为该版本
    schema: OpenAPI v3 验证 schema
    openAPIV3Schema:
    type: object
    properties:
    spec:
    type: object
    properties:
    engine:
    type: string
    enum: ["mysql", "postgres"]
    version:
    type: string
    storageGB:
    type: integer
    minimum: 1
    status:
    type: object
    properties:
    phase:
    type: string
    connectionString:
    type: string
    subresources:
    status: {} 启用 status 子资源
    scale: 启用 scale 子资源(可选)
    specReplicasPath: .spec.replicas
    statusReplicasPath: .status.replicas
    additionalPrinterColumns: 定义 `kubectl get` 显示的额外列
    name: Engine
    type: string
    jsonPath: .spec.engine
    name: Version
    type: string
    jsonPath: .spec.version
    name: Age
    type: date
    jsonPath: .metadata.creationTimestamp
    scope: Namespaced 作用域:Namespaced 或 Cluster
    names:
    plural: databases 复数名称,用于 URL
    singular: database 单数名称,用于 CLI 别名
    kind: Database 资源类型名称,用于 YAML/CLI
    shortNames: 短名称
    db

    关键字段说明:

    • group:自定义资源所属的 API 组,通常采用域名形式以避免冲突。
    • versions:支持一个或多个版本,每个版本可以独立定义验证 schema、子资源等。必须指定一个存储版本。
    • schema:OpenAPI v3 schema,用于验证自定义资源的字段类型和值,确保数据的合法性。强烈建议提供,避免无效数据进入 etcd。
    • subresources:启用 /status 和 /scale 子路径,方便控制器更新状态或水平伸缩。
    • additionalPrinterColumns:定义 kubectl get 输出时显示的额外列,提升可读性。
    • scope:资源是命名空间级别(Namespaced)还是集群级别(Cluster)。
    • names:资源的各种名称形式。

    5. 使用 CRD

    一旦 CRD 创建成功,你就可以像操作内置资源一样操作自定义资源。

    • 创建自定义资源实例(CR):

      apiVersion: example.com/v1alpha1
      kind: Database
      metadata:
      name: mydb
      namespace: default
      spec:
      engine: postgres
      version: "13"
      storageGB: 100

      使用 kubectl apply -f database.yaml 创建。

    • 查看自定义资源:

      kubectl get databases
      kubectl get db 使用短名称
      kubectl describe database mydb

    • 直接访问 API: 也可以通过 API Server 的代理访问,例如:

      kubectl proxy –port=8080 &
      curl http://localhost:8080/apis/example.com/v1alpha1/namespaces/default/databases/mydb

    6. 控制器模式

    CRD 本身只负责存储和提供 API,而实际的业务逻辑需要通过控制器来实现。控制器监听自定义资源的事件(创建、更新、删除),然后采取相应的动作使实际状态趋近于期望状态。这种模式被称为 Operator 模式。

    例如,一个 Database 控制器可能会:

    • 当发现一个新的 Database CR 时,根据 spec 中的引擎和版本信息,在底层云平台或数据库服务中创建一个真实的数据库实例。
    • 更新 CR 的 status 字段,将数据库的连接地址、状态等信息写回。
    • 当 CR 被删除时,清理对应的真实数据库资源。

    开发控制器常用的工具包括:

    • kubebuilder:官方脚手架,基于 controller-runtime 库。
    • Operator SDK:由 Red Hat 主导,封装了 kubebuilder 并提供额外功能。
    • controller-runtime:直接使用 Go 库编写控制器。

    7. 高级特性

    7.1 版本管理

    CRD 支持多个 API 版本共存,方便资源演进。你可以定义多个版本,并通过 storage 字段指定哪个版本负责存储。对于不同版本之间的转换,可以通过 Conversion Webhook 实现自定义的转换逻辑,确保旧版本对象可以无损地转换为新版本。

    7.2 子资源

    • status 子资源:启用后,对 CR 的 /status 子路径的更新不会触发 metadata.generation 的增加,便于控制器与用户更改分离。
    • scale 子资源:使自定义资源可以接入 kubectl scale 命令,并与 HorizontalPodAutoscaler 集成。

    7.3 验证和默认值

    除了 OpenAPI schema 验证,CRD 还支持通过 ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook 实现更复杂的验证和默认值设置。Webhook 可以在资源持久化之前拦截请求,进行自定义逻辑。

    7.4 附加打印列

    通过 additionalPrinterColumns,你可以让 kubectl get 的输出包含用户关心的字段,如状态、版本等,提升 CLI 的友好度。

    7.5 最终确定器 (Finalizers)

    与内置资源一样,CR 可以包含 finalizers,用于在删除资源前执行异步清理任务。控制器在完成清理后移除 finalizer,资源才会被真正删除。

    8. 实际应用场景

    CRD 广泛应用于云原生生态中的各种 Operator 和扩展:

    • Istio:通过 VirtualService、DestinationRule 等 CRD 管理服务网格流量规则。
    • Cert-Manager:提供 Certificate、Issuer 等 CRD 自动化 TLS 证书的申请和续期。
    • Prometheus Operator:使用 ServiceMonitor、PrometheusRule 等 CRD 动态配置监控和告警。
    • Knative:定义 Service、Revision 等 CRD 实现 Serverless 平台。
    • 数据库 Operator:如 MySQL Operator、Postgres Operator 通过 CRD 管理数据库实例的生命周期。

    9. 最佳实践和注意事项

    • 设计良好的 API:遵循 Kubernetes API 设计规范,使用 spec 和 status 分离期望状态和实际状态。
    • 版本规划:从一开始考虑 API 的演进,合理设计多版本策略,尽早定义转换 webhook。
    • 提供完整的验证 schema:避免无效数据进入存储,减少控制器处理异常情况的复杂度。
    • 使用 status 子资源:让控制器通过 status 更新状态,避免与用户对 spec 的更新冲突。
    • 合理设置 finalizers:确保资源删除时能正确清理外部依赖,防止残留。
    • 注意性能:CRD 本身不会带来明显的性能开销,但大量 CR 或频繁的更新可能会增加 API Server 和 etcd 的压力。使用 label 选择器和 informer 机制减少不必要的监听。
    • 避免名称冲突:选择特定的 API 组(如 company.com)以避免与其他 CRD 冲突。
    • 权限管理:使用 RBAC 为不同的用户或控制器授予对自定义资源的适当权限。

    10. 总结

    CRD 是 Kubernetes 可扩展性的基石,它允许你将 Kubernetes 的声明式 API 模型应用到任何领域。通过 CRD,用户可以定义自己的资源类型,并配合控制器实现复杂的自动化运维逻辑,即 Operator 模式。掌握 CRD 的设计与开发,能够帮助你充分利用 Kubernetes 平台的能力,构建高度自动化和可扩展的云原生应用。

    无论是平台工程师还是应用开发者,理解 CRD 的工作原理和使用方法,都是在 Kubernetes 生态中进行深度实践的关键一步。

    赞(0)
    未经允许不得转载:171主机测评 » Kubernetes CRD(自定义资源,CustomResourceDefinition)详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址