Kubernetes API之资源、种类和对象


【编者的话】本文通过Kubernetes API的方式,详细介绍了Kubernetes三大核心概念,资源、种类和对象,跟随作者,快来一睹为快吧。

这是关于如何从代码中使用Kubernetes API系列文章的第一篇。Kubernetes API比一堆简单的HTTP方法要高级一些。

因此,在试图使用Kubernetes API之前,理解Kubernetes API结构并熟悉术语是至关重要的。要不然,官方的Go客户端带有很多花哨的东西,如果你试图同时理解客户端和API的概念,可能会很快就会让你不知所措。

Kubernetes API是巨大的——它有数百个端点。幸运的是,它是相当一致的,所以我们只需要理解有限数量的思想,然后将这些知识外推到API的其余部分。在这里,我将尝试触及我发现的最基本的概念。

我喜欢简单和易于消化的,而不是学术正确性和材料的完整性。和往常一样,我只是分享我对事物的理解和我对这个主题的思考方式——所以,这不是一个API指南,而是一个个人经验分享。
01.jpg

资源和动词

由于这是一个RESTful的领域,我们将根据资源(松散地说,特定结构的对象)和动词(对这些对象的操作)来操作。

在讨论资源时,重要的是要将资源区分为特定类型的对象和特定类型的实例。因此,Kubernetes API端点被正式命名为资源类型,以避免与资源实例产生歧义。然而,在自然场景下,端点通常被称为资源,这个词的实际含义来自上下文。

出于可扩展性的原因,资源类型被组织到API组中,这些组的版本是相互独立的:
$ kubectl api-resources
NAME                     SHORTNAMES   APIVERSION   NAMESPACED   KIND
bindings                              v1           true         Binding
componentstatuses        cs           v1           false        ComponentStatus
configmaps               cm           v1           true         ConfigMap
endpoints                ep           v1           true         Endpoints
events                   ev           v1           true         Event
limitranges              limits       v1           true         LimitRange
namespaces               ns           v1           false        Namespace
nodes                    no           v1           false        Node
persistentvolumeclaims   pvc          v1           true         PersistentVolumeClaim
persistentvolumes        pv           v1           false        PersistentVolume
pods                     po           v1           true         Pod
...

Kubernetes的API是元数据。通过读取或创建其他资源,可以列出现有资源类型或注册新资源类型。例如,上面的列表是通过调用一个特殊的/apis资源获得的。


实际上,有两种资源——核心资源(pods、secrets、configmaps 等)的遗留资源和其余资源的更通用/api的资源,包括用户定义的自定义资源,/apis/<resource-name>
下面是一个很好的技巧,可以让你看到kubectl工具在运行命令时调用了哪些API:
$ kubectl api-resources -v 6  # -v 6 means "extra verbose logging"
...
I0108 ... GET https://192.168.58.2:8443/api?timeout=32s 200 OK in 10 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis?timeout=32s 200 OK in 1 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/apiregistration.k8s.io/v1?timeout=32s 200 OK in 7 milliseconds
I0108 ... GET https://192.168.58.2:8443/api/v1?timeout=32s 200 OK in 13 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/authentication.k8s.io/v1?timeout=32s 200 OK in 13 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/events.k8s.io/v1?timeout=32s 200 OK in 15 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/apps/v1?timeout=32s 200 OK in 14 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/autoscaling/v2beta1?timeout=32s 200 OK in 16 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/policy/v1beta1?timeout=32s 200 OK in 14 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/scheduling.k8s.io/v1?timeout=32s 200 OK in 14 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/batch/v1?timeout=32s 200 OK in 13 milliseconds
I0108 ... GET https://192.168.58.2:8443/apis/batch/v1beta1?timeout=32s 200 OK in 43 milliseconds
...

你可以使用标准的HTTP客户端(如curl)轻松地调用上述资源(即API端点),并检查返回的资源(即JSON对象,双关语):
# Make Kubernetes API available on localhost:8080
# to bypass the auth step in subsequent queries:
$ kubectl proxy --port=8080 &

# List all known API paths
$ curl http://localhost:8080/
# List known versions of the `core` group
$ curl http://localhost:8080/api
# List known resources of the `core/v1` group
$ curl http://localhost:8080/api/v1
# Get a particular Pod resource
$ curl http://localhost:8080/api/v1/namespaces/default/pods/sleep-7c7db887d8-dkkcg

# List known groups (all but `core`)
$ curl http://localhost:8080/apis
# List known versions of the `apps` group 
$ curl http://localhost:8080/apis
# List known resources of the `apps/v1` group
$ curl http://localhost:8080/apis/apps/v1
# Get a particular Deployment resource
$ curl http://localhost:8080/apis/apps/v1/namespaces/default/deployments/sleep



有一种更简单的方法来检查Kubernetes API:kubectl get --raw /SOME/API/PATH。但是,上面的练习是为了说明Kubernetes API并没有什么神奇之处——拥有一个未经测试的HTTP客户端就足以开始使用它了。
说到动词,也就是资源上的操作,所有标准的CRUD操作都有传统的映射到HTTP方法上。此外,还支持对资源进行修补(可选择的字段修改)和监视(类似流的集合的读取)。来自sig-architecture/api-conventions.md
API resources should use the traditional REST pattern:

GET /<resourceNamePlural> - Retrieve a list of type <resourceName>, e.g. GET /pods returns a list of Pods.
POST /<resourceNamePlural> - Create a new resource from the JSON object provided by the client.
GET /<resourceNamePlural>/<name> - Retrieves a single resource with the given name, e.g. GET /pods/first returns a Pod named 'first'. Should be constant time, and the resource should be bounded in size.
DELETE /<resourceNamePlural>/<name> - Delete the single resource with the given name. DeleteOptions may specify gracePeriodSeconds, the optional duration in seconds before the object should be deleted. Individual kinds may declare fields which provide a default grace period, and different kinds may have differing kind-wide default grace periods. A user provided grace period overrides a default grace period, including the zero grace period ("now").
DELETE /<resourceNamePlural> - Deletes a list of type <resourceName>, e.g. DELETE /pods a list of Pods.
PUT /<resourceNamePlural>/<name> - Update or create the resource with the given name with the JSON object provided by the client.
PATCH /<resourceNamePlural>/<name> - Selectively modify the specified fields of the resource. See more information below.
GET /<resourceNamePlural>?watch=true - Receive a stream of JSON objects corresponding to changes made to any resource of the given kind over time.

种类(Kinds,又称对象模式)

kind这个词会时不时地出现在这里和那里。例如,在kubectl api-resources输出中,你可以看到该persistentvolumes资源具有相应的PersistentVolume种类。

很长一段时间以来,我与Kubernetes的交互仅限于盲目地使用kubectl apply。 这让我认为kind总是包含资源的CamelCase名称,如Pod,Service,Deployment等。
$ cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 1
selector:
...
EOF

但实际上,不是资源的Kubernetes数据结构也可以有kind:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

不是Kubernetes对象(即持久实体)的资源也有kind:
$ kubectl get --raw /api | python -m json.tool
{
"kind": "APIVersions",    
"versions": [
    "v1"
],
...


那么,什么是种类?


所有资源类型都有一个具体的表示,称为一个kind——Kubernetes API参考。好吧,这个解释不是特别有用。
事实证明,在Kubernetes中,一种是对象模式的名称。就像你通常使用JSON模式词汇表描述的那样。换句话说,种类是指特定的数据结构,即属性和属性的某种组合。

根据sig-architecture/api-conventions.md,kind分为三类:
  • 对象(Pod,Service等):系统中的持久实体。
  • 列表(PodList,APIResourceList等):一种或多种资源的集合。
  • status对对象(status、scale等)或非持久性辅助实体(ListOptions、Policy等)的简单特定操作。


Kubernetes中使用的大多数对象,包括API返回的所有JSON对象,都有kind字段。它允许客户端和服务器在通过网络发送它们或将它们存储在磁盘上之前正确地序列化和反序列化这些对象。

Kubernetes对象

就像资源一样,Kubernetes用语中的对象这个词是重载的。从广义上讲,对象可以指任何数据结构——资源类型的实例(如APIGroup)、配置(如审计策略)或持久实体(如Pod)。但是,在本节中,我将在狭义的、明确定义的意义上讨论对象。所以,我将使用大写的词Object来代替。

像ReplicaSet、Namespace或的实体ConfigMap被称为Kubernetes对象。对象是Kubernetes系统中的持久实体,代表集群的意图(期望状态)和状态(实际状态)。


例如,一旦你创建了一个Pod对象,Kubernetes将不断地工作以确保相应的容器集合正在运行。
大多数Kubernetes API资源代表对象。与其他形式的资源只要求kind字段不同,对象必须定义更多字段:
  • kind:标识此对象应具有的架构的字符串
  • apiVersion:一个字符串,用于标识对象应具有的架构版本
  • metadata.namespace:带有命名空间的字符串(默认为“default”)
  • metadata.name:在当前命名空间中唯一标识此对象的字符串
  • metadata.uid:一个唯一的时间和空间值,用于区分已删除和重新创建的同名对象。


此外,元数据字典可能包括labelsannotations字段,以及一些版本控制和时间戳信息。


有趣的事实:该kubectl api-resources命令实际上列出的不是API资源,而是已知类型的Kubernetes对象。要列出真正的API资源,你需要运行一个完整的发现周期,以kubectl get --raw /递归方式查询每个返回的路径。
示例:Pod 对象(截断输出)
$ kubectl get --raw /api/v1/namespaces/default/pods/sleep-7c7db887d8-dkkcg | python -m json.tool
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
    "namespace": "default",
    "name": "sleep-7c7db887d8-dkkcg",        
    "uid": "32bf410a-0009-484e-adac-21179ec28f0f",
    "labels": {
        "app": "sleep",
        "pod-template-hash": "7c7db887d8"
    },        
    "creationTimestamp": "2022-01-08T18:10:04Z",
    "resourceVersion": "465766"        
},
"spec": { ... },
"status": { ... }




有趣的事实:Kubernetes被称为生产级容器编排系统。但是,Container不是Kubernetes对象——它只是一种简单的对象,但是Pod是一个成熟的持久对象。
如上例所示,Kubernetes对象通常具有spec(期望状态)和status(实际状态)字段。但情况并非总是如此。将上面的输出与下面的ConfigMap对象进行比较:
$ kubectl get --raw /api/v1/namespaces/default/configmaps/informer-dynamic-simple-wzgmx | python -m json.tool
{
"apiVersion": "v1",
"kind": "ConfigMap",
"data": {
    "foo": "bar"
},    
"metadata": {
    "namespace": "default",
    "name": "informer-dynamic-simple-wzgmx",
    "uid": "74471398-0244-4686-b490-7007f6246a63",
    "creationTimestamp": "2022-01-06T21:45:04Z",
    "generateName": "informer-dynamic-simple-",
    "resourceVersion": "418185"        
}


从代码中处理Kubernetes API涉及到大量的对象操作,因此必须对常见的对象结构有扎实的理解。该kubectl explain命令可以帮助你。它最酷的部分是它不仅可以在资源上调用,还可以在嵌套字段上调用:
$ kubectl explain deployment.spec.template
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: template <Object>

DESCRIPTION:
 Template describes the pods that will be created.

 PodTemplateSpec describes the data a pod should have when created from a
 template

FIELDS:
metadata <Object>
 Standard object's metadata. More info:
 https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

spec <Object>
 Specification of the desired behavior of the pod. More info:
 https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

总结

Kubernetes用语中的资源可以指资源类型和资源实例。资源类型被组织成API组,并且API组是版本化的。每个资源表都遵循由其kind定义的特定模式。虽然每个资源都遵循其类型定义的具体结构,但并非每个资源都代表一个Kubernetes对象。对象是一种持久性实体,用于表达对意图的记录。不同种类的对象具有不同的结构,但所有对象都带有共同的元数据属性,例如命名空间、名称、uid或创建时间戳。
2.png

敬请关注

下一篇文章将概述k8s.io/apik8s.io/apimachinery包——官方Go客户端的两个主要依赖项。我将展示Kubernetes API对象如何映射到Go结构,Go结构如何被序列化和反序列化,并涉及一些其他常见的(在客户端和服务器之间)API机制,不要错过哦!

原文链接:Working with Kubernetes API - Resources, Kinds, and Objects

译者:Mr.lzc,高级工程师、DevOpsDays、HDZ深圳核心组织者,目前供职于华为,从事云计算工作,专注于K8s、微服务领域。

0 个评论

要回复文章请先登录注册