Kuberneters CRD从入门到熟悉(第一部分)
文章目录
前言简介:
CRD 是什么概念?
k8s允许用户自定义自己的资源对象,就如同deploument 或者 statefulset 一样,这个应用非常广泛,例如prmetheus opterator就自定义prometheus对象,在江上一个自动一个的controller 监听到 kubectl create prometheus 时就去创建Pod 组成一个prometheus集群,所以,扩展k8s两个最常用的最需要掌握的东西:自定义资源CRD 和 adminsion webhook。
CRD 有哪些特点?
CRD全称是 Custom Resource Definition,其有如下特点:
- CRD 本身是 Kubernetes 的一种资源,允许用户自定义新的资源类型
- 除了 CRD 还需要用户提供一个Controller 以实现自己的逻辑
- CRD 允许用户给予已有的 kubernetes 资源,例如 Deployment、Configmap 等,拓展集群能力
- CRD 可以自定义一套成体系的规范,自造概念
参考 Future of CRDs: Structural Schemas ,Schema 可以确保 Yaml 描述的资源是规范的、合法的。CRD 本质是一个 Open Api 的 Schema,向 Kubernetes 集群注册一种新资源,并告诉 ApiServer,这种资源怎么被合法的定义。
CRD能做什么?
拓展:什么是控制器模式?
以 Deployment 为实例,Deployment 没有直接创建 Pod,而是管理 RS,而 RS 管理 Pod,这就是控制器模式。控制器模式允许基于已有的资源定义更高阶的控制器,用来实现更复杂的能力,详情可参考Kubernetes 控制器的工作原理解读
yaml解读
当你创建一个新的CRD时,k8s api 服务器将会为你制定的每个版本创建一个新的 restful 资源路径,我们可以根据api 路径来创建一些我们自己定义的类型资源,crd 可以是明明空间的,也可以是集群范围的,由 crd 的作用域(scpoe) 字段中所制定的,与现有内置对象一样,删除命名空间将删除该命名空间中所有自动一对象, crd 本身是集群级别资源,所有命名空间都可以使用。
创建一个 CRD
接下来,我们通过 yaml 来创建一个 crd :
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name:用于定义CRD的名字,后缀需要跟group一致,前缀需要跟names中的plural一致。
name: nginxs.zhaobei.nginxs.com
spec:
# 用于REST API的组名称: /apis/<group>/<version>
group: zhaobei.nginxs.com
# 此CustomResourceDefinition支持的版本列表
versions:
- name: v1
# 每个版本都可以通过服务标志启用/禁用。
served: true
# 必须将一个且只有一个版本标记为存储版本。
storage: true
# 指定crd资源作用范围在命名空间或集群
scope: Namespaced
names:
# URL中使用的复数名称: /apis/<group>/<version>/<plural>
plural: nginxs
# 在CLI(shell界面输入的参数)上用作别名并用于显示的单数名称
singular: my-ngx
# kind字段使用驼峰命名规则. 资源清单使用如此
kind: Nginxs
# 短名称允许短字符串匹配CLI上的资源,意识就是能通过kubectl 在查看资源的时候使用该资源的简名称来获取。
shortNames:
- ngs
根据CRD 创建一个自定义资源的对象
在创建 crd 后,我们可以创建定制资源的对象,自定义对象可以包含自定义字段,这些字段可以包含任意json ,下面的例子中,我们将一个pod资源对象的kind 和 apiversion 改为我们自定义的资源。
# apiVersion 对应 crd 中的spec.group
apiVersion: zhaobei.nginxs.com/v1
# Kind 对应 crd 中的 names.Kind
kind: Nginxs
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
然后我们验证一下:
zhaobei@zhaobeideMacBook-Pro crd % k get nginxs
NAME AGE
my-new-cron-object 111s
nginx 15s
为自定义资源添加验证
validation 这个验证是为了在创建好资源后,通过该资源创建对象的时候,对象的字段中村咋i五小只,则创建该对象的请求将被拒绝,否则会被创建,我们可以在 crd 文件中添加 validation 来添加相应的机制。我们可以通过使用OpenAPI v3 模式来验证我们自定义的资源对象,使用该模式也应用了一些限制:
-
default, nullable, discriminator, readOnly, writeOnly, xml, deprecated和$ref不能设置这些字段。
-
字段uniqueItem不能设置为true
-
字段additionalProperties不能设置为false
在crd资源中对自定义资源应用openapi v3模式验证,该自定义资源中对cronSpec和replicas两个字段做了验证,不符合规则的不给予创建该资源对象。
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
version: v1
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
validation:
# openAPIV3Schema is the schema for validating custom objects.
openAPIV3Schema:
properties:
spec:
properties:
cronSpec: #--必须是字符串,并且必须是正则表达式所描述的形式
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
replicas: #----必须是整数,最小值必须为1,最大值必须为10
type: integer
minimum: 1
maximum: 10
为自定义资源添加额外的打印列
从 kubernetes 1.11 开始k8s 使用服务器端进行打印,服务器决定由 kubectl get 命令现实哪些列即在我们获取一个内置资源的时候会显示一些列表信息,例如 kubectl get pods ,这里我们可以使用 crd 自定义这些列,当我们在查看需要的列表信息,通过 crd 文件中的 additionalPrinterColumns 字段,在该字段下生米给你需要打印列的信息。这里我们在crd对象中为自定义资源添加要显示的列表信息:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: nginxs.zhaobei.nginxs.com
spec:
group: zhaobei.nginxs.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: nginxs
singular: my-ngx
kind: Nginxs
shortNames:
- ngs
additionalPrinterColumns:
- name: Spec
type: string
description: The cron spec defining the interval a CronJob is run
JSONPath: .spec.cronSpec
- name: Replicas
type: integer
description: The number of jobs launched by the CronJob
JSONPath: .spec.replicas
- name: Age
type: date
JSONPath: .metadata.creationTimestamp
为自定义的资源添加状态和伸缩配置
一般的话我们要是没有在自定义资源中配置相关资源对象的伸缩和状态信息的话,那么在当我们通过该自定义资源创建对象后,又想通过 kubectl scale 来弹性的扩展对该对象容器的时候就会无能为力,而 crd 可以允许我们添加该方面的相关配置生命,从大达到我们对与资源对象的伸缩处理,添加 subresources 字段来声明状态和伸缩信息,在 k8s 中,这个称之为子资源,我们可以通过 kube-apiserve.yaml 文件来关闭或启用该功能,
--feature-gates=CustomResourceSubresources=false”
注意:在CRD OpenAPI验证模式的根目录中,只允许以下结构在crd文件中出现:
Description、Example、ExclusiveMaximum、ExclusiveMinimum、ExternalDocs、Format、Items、Maximum、MaxItems、MaxLength、Minimum、MinItems、MinLength、MultipleOf、Pattern、
如下crd文件中同时申明status和scale子资源:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: nginxs.zhaobei.nginxs.com
spec:
group: zhaobei.nginxs.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: nginxs
singular: my-ngx
kind: Nginxs
shortNames:
- ngs
additionalPrinterColumns:
- name: Spec
type: string
description: The cron spec defining the interval a CronJob is run
JSONPath: .spec.cronSpec
- name: Replicas
type: integer
description: The number of jobs launched by the CronJob
JSONPath: .spec.replicas
- name: Age
type: date
JSONPath: .metadata.creationTimestamp
# 自定义资源的子资源的描述
subresources:
# 启用状态子资源。
status: {}
# 启用scale子资源
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
labelSelectorPath: .status.labelSelector
扩充自定义资源对象副本数目
kubectl scale --replicas=5 ngs/nginx
为自定义资源分配所属组
一般的我们在创建碗自定义资源的时候就是一个分组,为了减少分组信息,我们可以将自定义资源分配到对应已存在的组里面。通过 categories 字段来定义我们自定义资源所属的组,在crd 文件中添加 categories 字段来声明所属组。
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: nginxs.zhaobei.nginxs.com
spec:
group: zhaobei.nginxs.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: nginxs
singular: my-ngx
kind: Nginxs
shortNames:
- ngs
categories:
- all
additionalPrinterColumns:
- name: Spec
type: string
description: The cron spec defining the interval a CronJob is run
JSONPath: .spec.cronSpec
- name: Replicas
type: integer
description: The number of jobs launched by the CronJob
JSONPath: .spec.replicas
- name: Age
type: date
JSONPath: .metadata.creationTimestamp
# 自定义资源的子资源的描述
subresources:
# 启用状态子资源。
status: {}
# 启用scale子资源
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
labelSelectorPath: .status.labelSelector