Intorduction CRD

什么是CRD

在 Kubernetes API 中,resources 是存储 API 对象集合的endpoint。例如,内置 Pod resource 包含 Pod 对象的集合。当我们想扩展API,原生的Kubernetes就不能满足我们的需求了,这时 CRD (CustomResourceDefinition) 就出现了。在 Kubernetes 中创建了 CRD 后,就可以像使用任何其他原生 Kubernetes 对象一样使用它,从而利用 Kubernetes 的所有功能、如安全性、API 服务、RBAC 等。

Kubernetes 1.7 之后增加了对 CRD 自定义资源二次开发能力来扩展 Kubernetes API,通过 CRD 我们可以向 Kubernetes API 中增加新资源类型,而不需要修改 Kubernetes 源码来创建自定义的 API server,该功能大大提高了 Kubernetes 的扩展能力。

创建 CRD

前提条件: Kubernetes 服务器版本必须不低于版本 1.16

再创建新的 CustomResourceDefinition(CRD)时,Kubernetes API 服务器会为指定的每一个版本生成一个 RESTful 的资源路径。(即定义一个Restful API)。CRD 可以是namespace作用域的,也可以是cluster作用域的,取决于 CRD 的 scope 字段设置。和其他现有的内置对象一样,删除一个namespace时,该namespace下的所有定制对象也会被删除。CustomResourceDefinition 本身是不受名字空间限制的,对所有名字空间可用。

例如,编写一个firewall port 规则:

# 1.16版本后固定格式
apiVersion: apiextensions.k8s.io/v1
# 类型crd
kind: CustomResourceDefinition
metadata:
  # 必须为name=spec.names.plural + spec.group
  name: ports.firewalld.fedoraproject.org
spec:
  # api中的group
  # /apis/<group>/<version>/<plural>
  group: firewalld.fedoraproject.org
  # 此crd作用于 可选Namespaced|Cluster
  scope: Namespaced
  names:
    # 名字的复数形式,用于api
    plural: ports
    # 名称的单数形式。用于命令行
    singular: port
    # 种类,资源清单类型
    kind: PortRule
    # 名字简写,类似允许 CLI 上较短的字符串匹配的资源
    shortNames:
    - fp
  versions:
  # 定义版本的类型
  - name: v1
  # 通过 served 标志来启用或禁止
    served: true
  # 其中一个且只有一个版本必需被标记为存储版本
    storage: true
  # 自定义资源的默认认证的模式
    schema:
  # 使用的版本
      openAPIV3Schema:
        # 定义一个参数为对象类型
        type: object
        # 这个参数的类型
        properties:
        # 参数属性spec
          spec:
            # spec属性的类型为对象
            type: object
            # 对象属性
            properties:
              # spec属性name
              name:
              # 类型为string
                type: string
              port:
                type: integer
              host:
                type: string
              isPermanent:
                type: boolean

需要注意的是v1.16版本以后已经 GA了,使用的是v1版本,之前都是vlbeta1,定义规范有部分变化,所以要注意版本变化。

这个地方的定义和我们定义普通的资源对象比较类似,我们说我们可以随意定义一个自定义的资源对象,但是在创建资源的时候,肯定不是任由我们随意去编写YAML文件的,当我们把上面的CRD文件提交给Kubernetes之后,Kubernetes会对我们提交的声明文件进行校验,从定义可以看出CRD是基于 OpenAPIv3 schem 进行规范的。当然这种校验只是对于字段的类型进行校验,比较初级,如果想要更加复杂的校验,这个时候就需要通过Kubernetes的admission webhook来实现了。关于校验的更多用法,可以前往官方文档查看。

创建一个crd类型资源

apiVersion: "firewalld.fedoraproject.org/v1"
kind: PortRule
metadata:
  name: http-port
spec:
  name: "nginx"
  port: 80
  host: "10.0.0.3"
  isPermanent: false

查看创建的crd

# kubectl get t
NAME                                CREATED AT
firewallds.port.fedoraproject.org   2022-06-19T09:27:09Z
06-20 15:15