本文是如何创建 CRD 来扩展 Kubernetes API 的教程。CRD 是用来扩展 Kubernetes 最常用的方式,在 Service Mesh 和 Operator 中也被大量使用。因此读者如果想在 Kubernetes 上做扩展和开发的话,是十分有必要了解 CRD 的。

在阅读本文前您需要先了解使用自定义资源扩展 API, 以下内容译自 Kubernetes 官方文档,有删改,推荐阅读如何从零开始编写一个 Kubernetes CRD

创建 CRD(CustomResourceDefinition)

创建新的 CustomResourceDefinition(CRD)时,Kubernetes API Server 会为您指定的每个版本创建新的 RESTful 资源路径。CRD 可以是命名空间的,也可以是集群范围的,可以在 CRD scope 字段中所指定。与现有的内置对象一样,删除命名空间会删除该命名空间中的所有自定义对象。CustomResourceDefinition 本身是非命名空间的,可供所有命名空间使用。

参考下面的 CRD,将其配置保存在 resourcedefinition.yaml 文件中:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# 名称必须符合下面的格式:<plural>.<group>
name: crontabs.stable.example.com
spec:
# REST API使用的组名称:/apis/<group>/<version>
group: stable.example.com
# REST API使用的版本号:/apis/<group>/<version>
versions:
- name: v1
# 可以通过 served 来开关每个 version
served: true
# 有且仅有一个 version 开启存储
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
# Namespaced或Cluster
scope: Namespaced
names:
# URL中使用的复数名称: /apis/<group>/<version>/<plural>
plural: crontabs
# CLI中使用的单数名称
singular: crontab
# CamelCased格式的单数类型。在清单文件中使用
kind: CronTab
# CLI中使用的资源简称
shortNames:
- ct

此处使用的 apiVersion 版本是 apiextensions.k8s.io/v1,跟上一版 apiextensions.k8s.io/v1beta1 的最主要区别是改用了 OpenAPI v3.0 validation schema

创建该 CRD

kubectl create -f resourcedefinition.yaml

访问 RESTful API 端点如 http://172.20.0.113:8080 将看到如下 API 端点已创建:

/apis/stable.example.com/v1/namespaces/*/crontabs/...

然后,此端点 URL 可用于创建和管理自定义对象。上面的 CRD 中定义的类型就是 CronTab

可能需要几秒钟才能创建端点。您可以监控 CustomResourceDefinition 中 Established 的状态何时为 true,或者查看 API 资源的发现信息中是否显示了您的资源。

创建自定义对象

创建 CustomResourceDefinition 对象后,您可以创建自定义对象。自定义对象可包含自定义字段。这些字段可以包含任意 JSON。在以下示例中, cronSpec 和 image 自定义字段在自定义对象中设置 CronTabCronTab 类型来自您在上面创建的 CustomResourceDefinition 对象的规范。

如果您将以下 YAML 保存到 my-crontab.yaml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image

并创建它:

kubectl create -f my-crontab.yaml

然后,您可以使用 kubectl 管理 CronTab 对象。例如:

kubectl get crontab

应该打印这样的列表:

NAME                 AGE
my-new-cron-object 6s

使用 kubectl 时,资源名称不区分大小写,您可以使用 CRD 中定义的单数或复数形式,以及任何短名称。

您还可以查看原始 YAML 数据:

kubectl get ct -o yaml

您应该看到它的 yaml 中的自定义 cronSpec 和 image 字段:

apiVersion: v1
items:
- apiVersion: stable.example.com/v1
kind: CronTab
metadata:
clusterName: ""
creationTimestamp: 2017-05-31T12:56:35Z
deletionGracePeriodSeconds: null
deletionTimestamp: null
name: my-new-cron-object
namespace: default
resourceVersion: "285"
selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
uid: 9423255b-4600-11e7-af6a-28d2447dc82b
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ""
selfLink: ""

删除 CustomResourceDefinition

删除 CustomResourceDefinition 时,服务器将删除 RESTful API 端点并删除存储在其中的所有自定义对象。

kubectl delete -f resourcedefinition.yaml
kubectl get crontabs
Error from server (NotFound): Unable to list "crontabs": the server could not find the requested resource (get crontabs.stable.example.com)

如果稍后重新创建相同的 CustomResourceDefinition,它将从空开始。

高级主题

Finalizer(终结器)

Finalizer(终结器)允许控制器实现异步预删除 hook。自定义对象支持终结器,就像内置对象一样。

您可以将终结器添加到自定义对象,如下所示:

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
finalizers:
- finalizer.stable.example.com

终结器是任意字符串值,当存在时确保在资源存在时不可能进行硬删除。

对具有终结器的对象的第一个删除请求设置该metadata.deletionTimestamp字段的值, 但不删除它。设置此值后,finalizer 只能删除列表中的条目。

如果设置了 metadata.deletionTimestamp 字段,控制器监控对象将执行它们所有的终结器,对该对象轮询更新请求。执行完所有终结器后,将删除该资源。

metadata.deletionGracePeriodSeconds控制轮询更新之间的间隔。

每个控制器都有责任从列表中删除其终结器。

如果终结器列表为空,Kubernetes 最终只会删除该对象,这意味着所有终结器都已执行。

Validation(验证)

功能状态: Kubernetes v1.12 beta

可以通过 OpenAPI v3 schema验证自定义对象是否符合标准 。此外,以下限制适用于 schema:

  • 字段defaultnullablediscriminatorreadOnlywriteOnlyxml、 deprecated 和 $ref 不能设置。
  • 该字段 uniqueItems 不能设置为 true。
  • 该字段 additionalProperties 不能设置为 false。

您可以使用 kube-apiserverCustomResourceValidation 上的功能门(feature gate)禁用此功能:

--feature-gates=CustomResourceValidation=false

该 schema 在 CustomResourceDefinition 中定义。在以下示例中,CustomResourceDefinition 对自定义对象应用以下验证:

  • spec.cronSpec 必须是字符串,并且必须是正则表达式描述的形式。
  • spec.replicas 必须是整数,且最小值必须为 1,最大值为 10。

将 CustomResourceDefinition 保存到 resourcedefinition.yaml

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 适用于验证自定义对象的 schema。
openAPIV3Schema:
properties:
spec:
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
replicas:
type: integer
minimum: 1
maximum: 10

并创建它:

kubectl create -f resourcedefinition.yaml

CronTab 如果其字段中存在无效值,则将拒绝创建类型的自定义对象的请求。在以下示例中,自定义对象包含具有无效值的字段:

  • spec.cronSpec 与正则表达式不匹配。
  • spec.replicas 大于10。

如果您将以下YAML保存到my-crontab.yaml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * *"
image: my-awesome-cron-image
replicas: 15

并创建它:

kubectl create -f my-crontab.yaml

你会收到一个错误:

The CronTab "my-new-cron-object" is invalid: []: Invalid value: map[string]interface {}{"apiVersion":"stable.example.com/v1", "kind":"CronTab", "metadata":map[string]interface {}{"name":"my-new-cron-object", "namespace":"default", "deletionTimestamp":interface {}(nil), "deletionGracePeriodSeconds":(*int64)(nil), "creationTimestamp":"2017-09-05T05:20:07Z", "uid":"e14d79e7-91f9-11e7-a598-f0761cb232d1", "selfLink":"", "clusterName":""}, "spec":map[string]interface {}{"cronSpec":"* * * *", "image":"my-awesome-cron-image", "replicas":15}}:
validation failure list:
spec.cronSpec in body should match '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
spec.replicas in body should be less than or equal to 10

如果字段包含有效值,则接受对象创建请求。

将以下 YAML 保存到 my-crontab.yaml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 5

并创建它:

kubectl create -f my-crontab.yaml
crontab "my-new-cron-object" created

其他打印列

从 Kubernetes 1.11 开始,kubectl 使用服务器端打印。服务器决定 kubectl get 命令显示哪些列。您可以使用 CustomResourceDefinition 自定义这些列。下面的示例将输出 SpecReplicas 和 Age 列。

  1. 将 CustomResourceDefinition 保存到 resourcedefinition.yaml

      apiVersion: apiextensions.k8s.io/v1beta1
    kind: CustomResourceDefinition
    metadata:
    name: crontabs.stable.example.com
    spec:
    group: stable.example.com
    version: v1
    scope: Namespaced
    names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
    - ct
    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
  2. 创建 CustomResourceDefinition:

    kubectl create -f resourcedefinition.yaml
  3. 使用上一节中的创建的 my-crontab.yaml 实例。

  4. 调用服务器端打印:

    kubectl get crontab my-new-cron-object

    请注意 NAMESPECREPLICAS 和 AGE 在输出列:

      NAME                 SPEC        REPLICAS   AGE
    my-new-cron-object * * * * * 1 7s

    NAME 列是隐含的,不需要在 CustomResourceDefinition 中定义。

Priority(优先级)

每列中都包含一个 priority 字段。目前,优先级区分标准视图或 wide 视图中显示的列(使用 -o wide 标志)。

  • 具有优先级的列 0 显示在标准视图中。
  • 优先级大于 0 的列仅在 wide 视图中显示。

Type(类型)

列中的 type 字段可以是以下任何一种(参考 OpenAPI v3 数据类型):

  • integer - 非浮点数
  • number - 浮点数
  • string - 字符串
  • boolean - ture 或 false
  • date - 自此时间戳以来的时间差异呈现

如果 CustomResource 中的值与为列指定的类型不匹配,则省略该值。使用 CustomResource 验证以确保值类型正确。

Format(格式)

列中的 format 字段可以是以下任何一个:

  • int32
  • int64
  • float
  • double
  • byte
  • date
  • date-time
  • password

该列 format 控制 kubectl 打印值时使用的样式。

子资源

功能状态: Kubernetes v1.12 beta

自定义资源支持 /status 和 /scale 子资源。

您可以使用 kube-apiserver CustomResourceSubresources 上的功能门(feature gate)禁用此功能:

--feature-gates=CustomResourceSubresources=false

可以通过在 CustomResourceDefinition 中定义它们来选择性地启用 status 和 scale 子资源。

状态子资源

启用状态子资源后,将公开自定义资源的子资源 /status

  • 状态和规范节分别由自定义资源内的 JSONPath .status 和 .specJSONPath 表示。
  • PUT``/status 对子资源的请求采用自定义资源对象,并忽略除状态节之外的任何更改。
  • PUT``/status 对子资源的请求仅验证自定义资源的状态节。
  • PUTPOSTPATCH 请求自定义资源忽略更改状态节。
  • 对 spec 节的任何更改都会增加 .metadata.generation 的值。
  • 在 CRD OpenAPI 验证模式的根目录中只允许以下构造:
    • Description
    • Example
    • ExclusiveMaximum
    • ExclusiveMinimum
    • ExternalDocs
    • Format
    • Items
    • Maximum
    • MaxItems
    • MaxLength
    • Minimum
    • MinItems
    • MinLength
    • MultipleOf
    • Pattern
    • Properties
    • Required
    • Title
    • Type
    • UniqueItems

扩展子资源

启用 scale 子资源后,将公开自定义资源的子资源 /scale。该 autoscaling/v1.Scale 对象作为有效负载发送 /scale

要启用 scale 子资源,CustomResourceDefinition 中需要定义以下值。

  • SpecReplicasPath 在与之对应的自定义资源中定义 JSONPath Scale.Spec.Replicas

    • 这是一个必需的值。
    • .spec 只允许使用带点符号的 JSONPaths 。
    • 如果 SpecReplicasPath 自定义资源中没有值,则 /scale 子资源将在GET上返回错误。
  • StatusReplicasPath 在与之对应的自定义资源中定义 JSONPath Scale.Status.Replicas
    • 这是一个必需的值。
    • .stutus 只允许使用带点符号的 JSONPaths 。
    • 如果 StatusReplicasPath 自定义资源中没有值,则子资源 /scale 中的状态副本值将默认为 0。
  • LabelSelectorPath在与之对应的自定义资源中定义 JSONPath Scale.Status.Selector
    • 这是一个可选值。
    • 必须将其设置为与 HPA 一起使用。
    • .status 只允许使用带点符号的 JSONPaths 。
    • 如果 LabelSelectorPath 自定义资源中没有值,则子资源 /scale 中的状态选择器值将默认为空字符串。

在以下示例中,启用了status 和 scale 子资源。

将 CustomResourceDefinition 保存到resourcedefinition.yaml

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
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
# subresources describes the subresources for custom resources.
subresources:
# status enables the status subresource.
status: {}
# scale enables the scale subresource.
scale:
# specReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Spec.Replicas.
specReplicasPath: .spec.replicas
# statusReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Replicas.
statusReplicasPath: .status.replicas
# labelSelectorPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Selector.
labelSelectorPath: .status.labelSelector

并创建它:

kubectl create -f resourcedefinition.yaml

创建 CustomResourceDefinition 对象后,您可以创建自定义对象。

如果您将以下 YAML 保存到 my-crontab.yaml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 3

并创建它:

kubectl create -f my-crontab.yaml

然后在以下位置创建新的命名空间 RESTful API 端点:

/apis/stable.example.com/v1/namespaces/*/crontabs/status

/apis/stable.example.com/v1/namespaces/*/crontabs/scale

可以使用该 kubectl scale 命令缩放自定义资源。例如,以上创建的自定义资源的的 .spec.replicas 设置为 5:

kubectl scale --replicas=5 crontabs/my-new-cron-object
crontabs "my-new-cron-object" scaled kubectl get crontabs my-new-cron-object -o jsonpath='{.spec.replicas}'
5

Category(分类)

类别是自定义资源所属的分组资源的列表(例如 all)。您可以使用 kubectl get <category-name> 列出属于该类别的资源。此功能是 beta,可用于 v1.10 中的自定义资源。

以下示例添加 all CustomResourceDefinition 中的类别列表,并说明如何使用 kubectl get all 输出自定义资源 。

将以下 CustomResourceDefinition 保存到 resourcedefinition.yaml

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
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
# categories is a list of grouped resources the custom resource belongs to.
categories:
- all

并创建它:

kubectl create -f resourcedefinition.yaml

创建 CustomResourceDefinition 对象后,您可以创建自定义对象。

将以下 YAML 保存到 my-crontab.yaml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image

并创建它:

kubectl create -f my-crontab.yaml

您可以使用kubectl get以下方式指定类别:

kubectl get all

它将包括种类的自定义资源CronTab

NAME                          AGE
crontabs/my-new-cron-object 3s

使用CRD扩展Kubernetes API的更多相关文章

  1. 使用aggregation API扩展你的kubernetes API

    Overview What is Kubernetes aggregation Kubernetes apiserver aggregation AA 是Kubernetes提供的一种扩展API的方法 ...

  2. 资深专家深度剖析Kubernetes API Server第3章(共3章)

    在本系列的前两部分中我们介绍了API Server的总体流程,以及API对象如何存储到etcd中.在本文中我们将探讨如何扩展API资源. 在一开始的时候,扩展API资源的唯一方法是扩展相关API源代码 ...

  3. 深度剖析Kubernetes API Server三部曲 - part 3

    在本系列的前两部分中我们介绍了API Server的总体流程,以及API对象如何存储到etcd中.在本文中我们将探讨如何扩展API资源. 在一开始的时候,扩展API资源的唯一方法是扩展相关API源代码 ...

  4. 亲历者说:Kubernetes API 与 Operator,不为人知的开发者战争

    如果我问你,如何把一个 etcd 集群部署在 Google Cloud 或者阿里云上,你一定会不假思索的给出答案:当然是用 etcd Operator! 实际上,几乎在一夜之间,Kubernetes ...

  5. 第24 章 : Kubernetes API 编程利器:Operator 和 Operator Framework

    Kubernetes API 编程利器:Operator 和 Operator Framework 本节课程主要分享以下三方面的内容: operator 概述 operator framework 实 ...

  6. 第23 章 : Kubernetes API 编程范式

    Kubernetes API 编程范式 需求来源 首先我们先来看一下 API 编程范式的需求来源. 在 Kubernetes 里面, API 编程范式也就是 Custom Resources Defi ...

  7. 资深专家深度剖析Kubernetes API Server第2章(共3章)

    欢迎来到深入学习Kubernetes API Server的系列文章的第二部分.在上一部分中我们对APIserver总体,相关术语及request请求流进行探讨说明.在本部分文章中,我们主要聚焦于探究 ...

  8. 资深专家深度剖析Kubernetes API Server第1章(共3章)

    欢迎来到深入学习Kubernetes API Server的系列文章,在本系列文章中我们将深入的探究Kubernetes API Server的相关实现.如果你对Kubernetes的内部实现机制比较 ...

  9. 零基础攻略!如何使用kubectl和HPA扩展Kubernetes应用程序

    现如今,Kubernetes已经完全改变了软件开发方式.Kubernetes作为一个管理容器化工作负载及服务的开源平台,其拥有可移植.可扩展的特性,并促进了声明式配置和自动化,同时它还证明了自己是管理 ...

  10. 深度剖析Kubernetes API Server三部曲 - part 2

    欢迎来到深入学习Kubernetes API Server的系列文章的第二部分.在上一部分中我们对APIserver总体,相关术语及request请求流进行探讨说明.在本部分文章中,我们主要聚焦于探究 ...

随机推荐

  1. rh358 003 ansible部署双网卡绑定 DNS原理 bind正向解析

    双网卡绑定 绑定多张网卡成为逻辑口,从而实现链路冗余,以及数据流量的负载均衡 1.创建team口 [root@servera ~]# nmcli connection add type team co ...

  2. 什么?MySQL 8.0 会同时修改两个ib_logfilesN 文件?

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 作者介绍:孙黎,GreatDB 认证DBA 问题现象 ...

  3. KingbaseES V8R6 ksql 关闭自动提交

    背景 用过oracle或mysql的人都知道,做一个dml语句,如果发现做错了,还可以rollback,但在Kingbase ksql 中,如果执行一个dml,没有先运行begin; 的话,一执行完就 ...

  4. KingbaseES DBLink 扩展介绍

    DBLink 扩展插件功能与 Kingbase_FDW 类似,用于远程访问KingbaseES 数据库.相比于Kingbase_FDW,DBLink 功能更强大,可以执行DML,还可以通过 begin ...

  5. Springboot shiro JWT集成总结

    SpringBoot Shiro JWT 1.建表 DDL.sql CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, ` ...

  6. 【读书笔记】C#高级编程 第七章 运算符和类型强制转换

    (一)运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ -- 移位运算符 < ...

  7. Elasticsearch:shard 分配感知

  8. 使用nginx代理nexus,不是/根路径

    location /nexus/ { proxy_pass http://192.168.0.218:8081/; proxy_set_header Host $host:$server_port; ...

  9. k8s中安装redis6集群

    注意:第二步不用操作了,yaml文件仅供参考 1.创建Namespace kubectl apply -f Namespace.yaml apiVersion: v1 kind: Namespace ...

  10. .NET6 使用 AutoMapper (解析)

    一.Net 6环境下的.net core项目里如何使用AutoMapper实现依赖注入. 注: AutoMapper 是一个对象-对象映射器,可以将一个对象映射到另一个对象. 第一步,在Nuget引入 ...