27K8CRD:如何根据需求自定义你的API?
文章目录
你好,我是正范。
随着使用的深入,你会发现 Kubernetes 中内置的对象定义,比如 Deployment、StatefulSet、Configmap,可能已经不能满足你的需求了。你很希望在 Kubernetes 定义一些自己的对象,一来可以通过 kube-apiserver 提供统一的访问入口,二来可以像其他内置对象一样,通过 kubectl 命令管理这些自定义的对象。
Kubernetes 中提供了两种自定义对象的方式,一种是聚合 API,另一种是 CRD。
我们今天就来看看。
聚合 API
聚合 API(Aggregation API,AA)是自 Kubernetes v1.7 版本就引入的功能,主要目的是方便用户将自己定义的 API 注册到 kube-apiserver 中,并且可以像使用其他内置的 API 一样,通过 APIServer 的 URL 就可以访问和操作。
在使用 API 聚合之前,我们还需要通过一些参数在 kube-apiserver 中启用这个功能:
|
|
Kubernetes 在 kube-apiserver 中引入了一个 API 聚合层(API Aggregation Layer),可以将访问请求转发到后端用户自己的扩展 APIServer 中。你可以参考这个文档学习如何安装一个扩展的 APIServer。当然,扩展的 APIServer 需要你自己修改并实现相关的代码逻辑。
Kubernetes apiserver 会判断 –requestheader-client-ca-file 指定的 CA 证书中的 CN 是否是 –requestheader-allowed-names 提供的列表名称之一。如果不是,则该请求被拒绝。如果名称允许,则请求会被转发。
接着 Kubernetes apiserver 将使用由 –proxy-client-*-file 指定的文件来访问用户的扩展 APIServer。
下图就是用户发起请求后一个完整的身份认证流程,你可以阅读官方文档来详细了解步骤 。
图 1:一个完整的身份认证流程
配置好了上述参数后, 为了让 kube-apiserver 知道我们自定义的 API,我们需要创建一个 APIService 的对象,比如:
|
|
通过上述 YAML 文件,我们就在 kube-apiserver 中创建一个 API 对象组,其对应的组(Group)为 wardle.example.com,版本号为 v1alpha1。创建成功后,我们就可以通过 /apis/wardle.example.com/v1alpha1 这个路径访问了。至于这个对象组里提供了哪些对象,就需要我们在扩展的 APIServer 中声明出来了。
那 kube-apiserver 又是怎么知道将 /apis/wardle.example.com/v1alpha1 这个路径的所有请求转发到后端的扩展 APIServer 中的呢?我们注意到上面的 APIService 定义中,还有一个 spec.service 字段,就是在这里,我们指定了扩展 APIServer 的服务名,也就是说 kube-apiserver 会将 /apis/wardle.example.com/v1alpha1 这个路径的所有访问通过 API 聚合层转发到后端的服务 myapi.wardle.svc 上。
扩展 APIServer 的具体代码设计及逻辑,你可以参考sample-apiserver或者使用apiserver-builder。
这种聚合 API 的方式对代码要求很高,但支持对 API 行为进行完全的掌控,比如你可以自己定义数据如何存储、API 各个版本的切换、各个对象的逻辑控制。
如果你只想简简单单地在 Kubernetes 中定义个对象,可以直接通过下面要介绍的 CRD 定义。
CRD
CRD(CustomResourceDefinitions)在 v1.7 刚引入进来的时候,其实是 ThirdPartyResources(TPR)的升级版本,而 TPR 在 v1.8 的版本被剔除了。CRD 目前使用非常广泛,各个周边项目都在使用它,比如 Ingress、Rancher。
我们来看一下官方的一个例子,通过如下的 YAML 文件,我们可以创建一个 API:
|
|
我们可以像创建其他对象一样,通过 kubectl create 命令创建。创建好了以后,一个类型为 CronTab 的对象就在 kube-apiserver 中注册好了,你可以通过如下的 REST 接口访问,比如 LIST 命名空间 ns1 下的 CronTab 对象,可以通过这个 URL“/apis/stable.example.com/v1/namespaces/ns1/crontabs/”访问。这种接口跟 Kubernetes 内置的其他对象的接口风格是一模一样的。
声明好了 CronTab,下面我们就来看看如何创建一个 CronTab 类型的对象。我们来看看官方给的一个例子:
|
|
通过 kubectl create 创建 my-new-cron-object 后,就可以通过 kubectl get 查看,并使用 kubectl 管理你的 CronTab 对象了。例如:
|
|
这里的资源名是大小写不敏感的,我们在这里可以使用缩写 kubectl get ct,也可以使用 kubectl get crontabs。
同时原生内置的 API 对象一样,这些 CRD 不仅可以通过 kubectl 来创建、查看、修改,删除等操作,还可以给其配置 RBAC 规则。
我们还能开发自定义的控制器,来感知和操作这些自定义的 API。这一部分我会在下一讲中介绍。
我们在创建 CRD 的时候,还可以一起定义 /status 和 /scale 子资源,如下所示:
|
|
这些子资源的定义,可以帮助我们在更新对象的时候,只更改期望的部分,比如只更新 status 部分,避免误更新 spec 部分。
同时 CRD 定义的时候还支持合法性检查、设置默认值等操作,你可以参照文档来实践。
写在最后
当然,你也可以选择在其他地方定义新的 API,你可以参考这份文档确定是否需要在 Kubernetes 中定义 API,还是让你的 API 独立运行。
你可以通过这个网址中的内容来比较 CRD 和 聚合 API 的功能差异。简单来说,CRD 更为易用,而聚合 API 更为灵活。
Kubernetes 提供这两种选项以满足不同用户的需求,这样就既不会牺牲易用性也不会牺牲灵活性。
对于聚合 API 和 CRD,你还有什么问题的话,欢迎在留言区留言。
下一讲,我将介绍如何通过 Operator 扩展 Kubernetes API。
-– ### 精选评论
文章作者 anonymous
上次更新 2024-06-11