温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2020-08-07 07:10:26 来源:ITPUB博客 阅读:145 作者:PaaS小魔仙 栏目:服务器

在本系列的前两部分中我们介绍了 API Server 的总体流程,以及 API 对象如何存储到 etcd 中。在本文中我们将探讨如何扩展 API 资源。

在一开始的时候,扩展 API 资源的唯一方法是扩展相关 API 源代码,集成为你所需的资源。或者,推动一个全新的类型为新的核心对象 API 合入社区代码。但是,这样就会导致核心 API 资源类型的不断增加,直至 API 过载。为了避免这种 API 资源的无限制扩展,在 Kubernetes 中提供两种扩展核心 API 的方法:

1.     使用自定义资源定义( CRDs ),最开始的时候被称为第三方资源( TPRs )。通过 CRD 你能够简单而灵活的方式定义自己的资源对象类型,并让 API server 处理整个生命周期。

2.     使用与主 API Servers  并行运行的用户 API Servers UAS )。这种方式,可能更多的设计代码开发,可能需要你投入较多的时间及精力。当然,这种方式也能够让你对 API 资源有更细致,全面的了解。

在本文中,我们主要对 CRD 相关定义以及使用进行探讨。

CRDs 的声明及创建

在本系列文章第一部分所提到过的,每个 API 资源根据 Group 群组分类,每个对象都有一个对应的版本号与 HTTP 路径相关联。现在如果想要实现一个 CRD ,首先需要的是就是命名一个新的 API Group 群组,这个 API 群组不能与已经存在的群组重复。在你自己新建的 API 群组中,你可以拥有任意数量的资源,并且它们可以与其他群组中的资源具有相同的名称。下面我们来列举一个实际的例子:

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

在之前我们有介绍过,每个版本的由 API 群组管理的 Kubernetes 资源是跟 HTTP 路径相关的。 CRD 类似于面向对象编程中一个类的定义,而实际使用的 CR 可以看做为它的一组实例。首先我们对例子中的一些字段作说明,第一行中的 CRD apiVersion kube-apiserver 1.7  之后都是这样定义的。从第 5 行之后我们定义了 spec  的相关字段。在第 6 spec.group 是定义了你创建的 CRD API 群组(在本例子中定义为了 example.com )。第 7 行定义了 CRD 对象的版本。每个资源只有一个固定版本,但在 API 群组中还是能有多个不同版本的资源。第 8 行的 spec.names 有两个必填项: kind ,按照惯例第一个字母大写, plural ,按照惯例全为小写,这个字段与最终生成的 HTTP 路径相关,比如在本例子中,最终的 HTTP 路径为 https://<server/apis/example.com/v1/namespaces/default/databases 。还有一个可选的 singular 字段,默认为小写类型值,可以在 kubectl 的上下文中使用。此外,在 spec.names 中还有许多可选字段,这些字段将会由 API Server 自动生成并填充。

上面的 kind 主要是用来描述对象的类型,而 resource  资源是与 HTTP 路径相关的。大多数情况下这两个是匹配的;但是在某些特定情况下在相同的 API HTTP 路径下可能返回不通的 kind (比如 Status  错误对象会返回另一种 kind )。

值得注意的是 resource  资源(在本例中是 databases )和 group 群组(本例中是 example.com )必须与 metadata.name  字段匹配(本例为第四行 databases. example.com )。

现在我们根据上面的 YAML 文件来创建一个 CRD

$ kubectl create -f databases-crd.yaml

customresourcedefinition "databases.example.com" created

由于这个创建过程是异步进行的,所以你必须检查一下你创建的 CRD 的状态,确认你创建的 CRD 没有与其它资源冲突,并且 API Server 已经调用相关处理函数完成创建。你可以在脚本或代码中通过轮询完成这个过程。最后我们能得到以下状态:

$ kubectl get crd databases.example.com -o yaml

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  creationTimestamp: 2017-08-09T09:21:43Z

  name: databases.example.com

  resourceVersion: "792"

  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/databases.example.com

  uid: 28c94a05-7ce4-11e7-888c-42010a9a0fd5

spec:

  group: example.com

  names:

    kind: Database

    listKind: DatabaseList

    plural: databases

    singular: database

  scope: Namespaced

  version: v1

status:

  acceptedNames:

    kind: Database

    listKind: DatabaseList

    plural: databases

    singular: database

  conditions:

  - lastTransitionTime: null

    message: no conflicts found

    reason: NoConflicts

    status: "True"

    type: NamesAccepted

  - lastTransitionTime: 2017-08-09T09:21:43Z

    message: the initial names have been accepted

    reason: InitialNamesAccepted

    status: "True"

    type: Established

以上,我们可以看到通过 kubectl 可以看到我们之前创建的 CRD ,并且显示出了 CRD 的一些状态信息。

CRDs 的使用

通过 kubectl proxy Kubernetes API  开启本地代理后,查看我们刚才创建的 CRD:

$ http 127.0.0.1:8001/apis/example.com

HTTP/1.1 200 OK

Content-Length: 223

Content-Type: application/json

Date: Wed, 09 Aug 2017 09:25:44 GMT

 

{

    "apiVersion": "v1",

    "kind": "APIGroup",

    "name": "example.com",

    "preferredVersion": {

        "groupVersion": "example.com/v1",

        "version": "v1"

    },

    "serverAddressByClientCIDRs": null,

    "versions": [

        {

            "groupVersion": "example.com/v1",

            "version": "v1"

        }

    ]

}

请注意,在默认情况下十分钟内, kubectl 是查看存储在 ~/.kube/cache/discovery 目录的缓存。所以,可能会需要 10 分钟后你才能看到你新创建的 CRD 资源。但是,当没有缓存时, kubectl 发现不了所需的资源时,那么会重新缓存它。

接下来,我们来看一个 CRD 实例:

$ cat wordpress-database.yaml

apiVersion: example.com/v1

kind:       Database

metadata:

  name:     wordpress

spec:

  user:     wp

  password: secret

  encoding: unicode

 

$ kubectl create -f wordpress-databases.yaml

database "wordpress" created

 

$ kubectl get databases.example.com

NAME        KIND

wordpress   Database.v1.example.com

想要通过 API 来监控资源的创建与 更新,你可以通过对某个 resourceVersion (我们通过 curl 来实例对指定版本的 database 做监控 )之后的修改做监控 watch

$ http 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases

HTTP/1.1 200 OK

Content-Length: 593

Content-Type: application/json

Date: Wed, 09 Aug 2017 09:38:49 GMT

 

{

    "apiVersion": "example.com/v1",

    "items": [

        {

            "apiVersion": "example.com/v1",

            "kind": "Database",

            "metadata": {

                "clusterName": "",

                "creationTimestamp": "2017-08-09T09:38:30Z",

                "deletionGracePeriodSeconds": null,

                "deletionTimestamp": null,

                "name": "wordpress",

                "namespace": "default",

                "resourceVersion": "2154",

                "selfLink": "/apis/example.com/v1/namespaces/default/databases/wordpress",

                "uid": "8101a7af-7ce6-11e7-888c-42010a9a0fd5"

            },

            "spec": {

                "encoding": "unicode",

                "password": "secret",

                "user": "wp"

            }

        }

    ],

    "kind": "DatabaseList",

    "metadata": {

        "resourceVersion": "2179",

        "selfLink": "/apis/example.com/v1/namespaces/default/databases"

    }

}

我们可以对 /apis/example.com/v1/namespaces/default/databases/wordpress CRD HTTP 路径 通过 curl 命令对的 "resourceVersion": "2154" 进行监控 watch:

$ curl -f 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases?watch=true&resourceVersion=2154

现在我们新开一个 shell 对话窗口,删除 wordpress  CRD 资源,我们可以查看刚才的监控 watch 窗口是否接收到了这个消息:

$ kubectl delete databases.example.com/wordpress

请注意:我们能够使用 kubectl delete database wordpress 删除 CRD 资源,是因为之前在 Kubernetes 没有定义有 database  资源。此外, database  是我们 CRD 中的 spec.name.singular 字段 ,从英语语法派生而来。

我们可以看到之前监控 watch CRD databases API Server 处返回的更新状态:

{"type":"DELETED","object":{"apiVersion":"example.com/v1","kind":"Database","metadata":{"clusterName":"","creationTimestamp":"2017-0[0/515]

:38:30Z","deletionGracePeriodSeconds":null,"deletionTimestamp":null,"name":"wordpress","namespace":"default","resourceVersion":"2154","selfLink":"/apis/example.com/v1/namespaces/

default/databases/wordpress","uid":"8101a7af-7ce6-11e7-888c-42010a9a0fd5"},"spec":{"encoding":"unicode","password":"secret","user":"wp"}}}

上述 shell 会话的运行及输出结果如下图所示:

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

最后,让我们看一下 CRD database  的各个数据是如何存储在 etcd 中的。下面是我们直接通过 HTTP API 进入 etcd 访问得到的数据:

$ curl -s localhost:2379/v2/keys/registry/example.com/databases/default | jq .

{

  "action": "get",

  "node": {

    "key": "/registry/example.com/databases/default",

    "dir": true,

    "nodes": [

      {

        "key": "/registry/example.com/databases/default/wordpress",

        "value": "{\"apiVersion\":\"example.com/v1\",\"kind\":\"Database\",\"metadata\":{\"clusterName\":\"\",\"creationTimestamp\":\"2017-08-09T14:53:40Z\",\"deletionGracePeriodSeconds\":null,\"deletionTimestamp\":null,\"name\":\"wordpress\",\"namespace\":\"default\",\"selfLink\":\"\",\"uid\":\"8837f788-7d12-11e7-9d28-080027390640\"},\"spec\":{\"encoding\":\"unicode\",\"password\":\"secret\",\"user\":\"wp\"}}\n",

        "modifiedIndex": 670,

        "createdIndex": 670

      }

    ],

    "modifiedIndex": 670,

    "createdIndex": 670

  }

}

从上面可以看到, CRD 数据在 etcd 中最终以一个未解析的的状态存在。现在将 CRD 删除,所有的 CRD 实例也会跟着删除,这是一个级联删除操作。

目前 CRDs 的使用现状,局限及将来的展望

CRDs 的发展现状如下所示:

1.        Kubernetes 1.7 版本中 CRDs 开始取代 ThirdPartyResources  (TPRs)  ,并且 TPRs  将会在 Kubernetes 1.8 被删除。

2.        TPRs 迁移到 CRDs 实例可以参考文档 migration

3.        支持一个 CRD 中只有单个 version  版本,当然,一个群组中可能有多个 version 版本。

4.        CRDs 提供一个 API 方案,在用户角度看它与 Kubernetes 原生的 API 资源基本没有区别

5.        CRDs 是多版本多分支稳定的基础。关于 CRD 资源的 JSON-Schema 的格式有效性校验可以参考文档 CRD validation proposal 。相关资源回收可以参考文档 Garbage collection

接下去我们来看一下一些 CRDs 的局限:

1.        CRD 不提供版本转换功能,也就是说,每个 CRD 只能有一个版本(预计不会在近期或中期内看到支持 CRD 版本转换)。

2.        Kubernetes1.7 当中,目前并没有对于 CRD 的相关校验 validation

3.        没有快速,实时的准入( admission  )机制(但是可以支持 webhooks  形式的初始化及准入)。

4.        Kubernetes1.7 中你不能定义子资源( sub-resources ),比如 scale 或者 status ,不过目前有在这方面 proposal   的讨论。

5.        CRD 目前不支持默认值配置,即不支持为特定的字段配默认值(在 Kubernetes1.7 后续的版本中可能会支持)。

为了解决上述的问题,并且灵活的扩展 Kubernetes ,你可以运行一个与主 API Server 并行的用户 API Servers 。我们将在本博文的以后部分中详细介绍如何编写 UAS ,并编写一个 custom controller  完整使用 CRD  。https://www.huaweicloud.com/product/cce.html


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI