Skip to content

Commit 182828c

Browse files
Add an API concepts document and describe terminology and API chunking
Create a new API reference page that covers some high level topics - terminology, paths, verbs, watching resources, chunking, and content type negotation.
1 parent 0ca9deb commit 182828c

File tree

2 files changed

+233
-0
lines changed

2 files changed

+233
-0
lines changed

_data/reference.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ toc:
2323
- docs/admin/authorization/rbac.md
2424
- docs/admin/authorization/node.md
2525
- docs/admin/authorization/webhook.md
26+
- docs/reference/api-concepts.md
2627
- docs/reference/deprecation-policy.md
2728
- docs/reference/workloads-18-19.md
2829

docs/reference/api-concepts.md

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
---
2+
title: Kubernetes API Concepts
3+
approvers:
4+
- bgrant0607
5+
- smarterclayton
6+
- lavalamp
7+
- liggitt
8+
---
9+
10+
{% capture overview %}
11+
This page describes common concepts in the Kubernetes API.
12+
{% endcapture %}
13+
14+
{% capture body %}
15+
The Kubernetes API is a resource-based (RESTful) programatic interface provided via HTTP. It supports retrieving, creating,
16+
updating, and deleting primary resources via the standard HTTP verbs (POST, PUT, PATCH, DELETE, GET), includes additional subresources for many objects that allow fine grained authorization (such as binding a pod to a node), and can accept and serve those resources in different representations for convenience or efficiency. It also supports efficient change notifications on resources via "watches" and consistent lists to allow other components to effectively cache and synchronize the state of resources.
17+
18+
## Standard API terminology
19+
20+
Most Kubernetes API resource types are "objects" - they represent a concrete instance of a concept on the cluster, like a pod or namespace. A smaller number of API resource types are "virtual" - they often represent operations rather than objects, such as a permission check (use a POST with a JSON-encoded body of `SubjectAccessReview` to the `subjectaccessreviews` resource). All objects will have a unique name to allow idempotent creation and retrieval, but virtual resource types may not have unique names if they are not retrievable or do not rely on idempotency.
21+
22+
Kubernetes generally leverages standard RESTful terminology to describe the API concepts:
23+
24+
* A **resource type** is the name used in the URL (`pods`, `namespaces`, `services`)
25+
* All resource types have a concrete representation in JSON (their object schema) which is called a **kind**
26+
* A list of instances of a resource type is known as a **collection**
27+
* A single instance of the resource type is called a **resource**
28+
29+
All resource types are either scoped by the cluster (`/apis/GROUP/VERSION/*`) or to a namespace (`/apis/GROUP/VERSION/namespaces/NAMESPACE/*`). A namespace-scoped resource type will be deleted when its namespace is deleted and access to that resource type is controlled by authorization checks on the namespace scope. The following paths are used to retrieve collections and resources:
30+
31+
* Cluster-scoped resources:
32+
* `GET /apis/GROUP/VERSION/RESOURCETYPE` - return the collection of resources of the resource type
33+
* `GET /apis/GROUP/VERSION/RESOURCETYPE/NAME` - return the resource with NAME under the resource type
34+
* Namespace-scoped resources:
35+
* `GET /apis/GROUP/VERSION/RESOURCETYPE` - return the collection of all instances of the resource type across all namespaces
36+
* `GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE` - return collection of all instances of the resource type in NAMESPACE
37+
* `GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME` - return the instance of the resource type with NAME in NAMESPACE
38+
39+
Since a namespace is a cluster-scoped resource type, you can retrieve the list of all namespaces with `GET /api/v1/namespaces` and details about a particular namespace with `GET /api/v1/namespaces/NAME`.
40+
41+
Almost all object resource types support the standard HTTP verbs - GET, POST, PUT, PATCH, and DELETE. Kubernetes uses the term **list** to describe returning a collection of resources to distinguish from retrieving a single resource which is usually called a **get**.
42+
43+
Some resource types will have one or more sub-resources, represented as sub paths below the resource:
44+
45+
* Cluster-scoped subresource: `GET /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE`
46+
* Namespace-scoped subresource: `GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE`
47+
48+
The verbs supported for each subresource will differ depending on the object - see the API documentation more information. It is not possible to access sub-resources across multiple resources - generally a new virtual resource type would be used if that becomes necessary.
49+
50+
51+
## Efficient detection of changes
52+
53+
To enable clients to build a model of the current state of a cluster, all Kubernetes object resource types are required to support consistent lists and an incremental change notification feed called a **watch**. Every Kubernetes object has a `resourceVersion` field representing the version of that resource as stored in the underlying database. When retrieving a collection of resources (either namespace or cluster scoped), the response from the server will contain a `resourceVersion` value that can be used to initiate a watch against the server. The server will return all changes (creates, deletes, and updates) that occur after the supplied `resourceVersion`. This allows a client to fetch the current state and then watch for changes without missing any updates. If the client watch is disconnected they can restart a new watch from the last returned `resourceVersion`, or perform a new collection request and begin again.
54+
55+
For example:
56+
57+
1. List all of the pods in a given namespace
58+
59+
GET /api/v1/namespaces/test/pods
60+
---
61+
200 OK
62+
Content-Type: application/json
63+
{
64+
"kind": "PodList",
65+
"apiVersion": "v1",
66+
"metadata": {"resourceVersion":"10245"},
67+
"items": [...]
68+
}
69+
70+
2. Starting from resource version 10245, receive notifications of any creates, deletes, or updates as individual JSON objects
71+
72+
GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245
73+
---
74+
200 OK
75+
Transfer-Encoding: chunked
76+
Content-Type: application/json
77+
{
78+
"type": "ADDED",
79+
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...}
80+
}
81+
{
82+
"type": "MODIFIED",
83+
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "11020", ...}, ...}
84+
}
85+
...
86+
87+
A given Kubernetes server will only preserve a historical list of changes for a limited time. On older clusters using etcd2 a maximum of 1000 changes will be preserved and on newer clusters using etcd3 changes in the last 5 minutes are preserved by default. Clients must handle the case where the requested watch operations fails because the historical version of that resource is not available by recognizing the status code `410 Gone`, clearing their local cache, performing a list operation, and starting the watch from the `resourceVersion` returned by that new list operation. Most client libraries offer some form of standard tool for this logic (in Go this is called a `Reflector` and is located in the `k8s.io/client-go/cache` package).
88+
89+
90+
## Retrieving large results sets in chunks
91+
92+
On large clusters, retrieving the collection of some resource types may result in very large responses that can impact the server and client. For instance, a cluster may have tens of thousands of pods, each of which is 1-2kb of encoded JSON. Retrieving all pods across all namespaces may result in a very large response (10-20MB) and consume a large amount of server resources. Starting in Kubernetes 1.9 the server supports the ability to break a single large collection request into many smaller chunks while preserving the consistency of the total request. Each chunk can be returned sequentially which reduces both the total size of the request and allows user-oriented clients to display results incrementally to improve responsiveness.
93+
94+
To retrieve a single list in chunks, two new parameters `limit` and `continue` are supported on collection requests and a new field `continue` is returned from all list operations in the list `metadata` field. A client should specify the maximum results they wish to receive in each chunk with `limit` and the server will return up to `limit` resources in the result and include a `continue` value if there are more resources in the collection. The client can then pass this `continue` value to the server on the next request to instruct the server to return the next chunk of results. By continuing until the server returns an empty `continue` value the client can consume the full set of results.
95+
96+
Like a watch operation, a `continue` token will expire after a short amount of time (by default 5 minutes) and return a `410 Gone` if more results cannot be returned. In this case, the client will need to start from the beginning or omit the `limit` parameter.
97+
98+
For example, if there are 1253 pods on the cluster, and the client wants to receive chunks of 500 pods at a time, they would request those chunks as follows:
99+
100+
1. List all of the pods on a cluster, retrieving up to 500 pods each time
101+
102+
GET /api/v1/pods?limit=500
103+
---
104+
200 OK
105+
Content-Type: application/json
106+
{
107+
"kind": "PodList",
108+
"apiVersion": "v1",
109+
"metadata": {
110+
"resourceVersion":"10245",
111+
"continue": "ENCODED_CONTINUE_TOKEN",
112+
...
113+
},
114+
"items": [...] // returns pods 1-500
115+
}
116+
117+
2. Continue the previous call, retrieving the next set of 500 pods
118+
119+
GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN
120+
---
121+
200 OK
122+
Content-Type: application/json
123+
{
124+
"kind": "PodList",
125+
"apiVersion": "v1",
126+
"metadata": {
127+
"resourceVersion":"10245",
128+
"continue": "ENCODED_CONTINUE_TOKEN_2",
129+
...
130+
},
131+
"items": [...] // returns pods 501-1000
132+
}
133+
134+
3. Continue the previous call, retrieving the last 253 pods
135+
136+
GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN_2
137+
---
138+
200 OK
139+
Content-Type: application/json
140+
{
141+
"kind": "PodList",
142+
"apiVersion": "v1",
143+
"metadata": {
144+
"resourceVersion":"10245",
145+
"continue": "", // continue token is empty because we have reached the end of the list
146+
...
147+
},
148+
"items": [...] // returns pods 1001-1253
149+
}
150+
151+
Note that the `resourceVersion` of the list remains constant across each request, indicating the server is showing us a consistent snapshot of the pods. Pods that are created, updated, or deleted after version `10245` would not be shown unless the user makes a list request without the `continue` token. This allows clients to break large requests into smaller chunks and then perform a watch operation on the full set without missing any updates.
152+
153+
154+
## Alternate representations of resources
155+
156+
By default Kubernetes returns objects serialized to JSON with content type `application/json`. This is the default serialization format for the API. However, clients may request the more efficient Protobuf representation of these objects for better performance at scale. The Kubernetes API implements standard HTTP content type negotation - passing an `Accept` header with a `GET` call will request that the server return objects in the provided content type, while sending an object in Protobuf to the server for a `PUT` or `POST` call takes the `Content-Type` header. The server will return a `Content-Type` header if the requested format is supported, or the `406 Not acceptable` error if an invalid content type is provided.
157+
158+
See the API documentation for a list of supported content types for each API.
159+
160+
For example:
161+
162+
1. List all of the pods on a cluster in Protobuf format
163+
164+
GET /api/v1/pods
165+
Accept: application/vnd.kubernetes.protobuf
166+
---
167+
200 OK
168+
Content-Type: application/vnd.kubernetes.protobuf
169+
... binary encoded PodList object
170+
171+
2. Create a pod by sending Protobuf encoded data to the server, but request a response in JSON
172+
173+
POST /api/v1/namespaces/test/pods
174+
Content-Type: application/vnd.kubernetes.protobuf
175+
Accept: application/json
176+
... binary encoded Pod object
177+
---
178+
200 OK
179+
Content-Type: application/json
180+
{
181+
"kind": "Pod",
182+
"apiVersion": "v1",
183+
...
184+
}
185+
186+
Not all API resource types will support Protobuf, specifically those defined via Custom Resource Definitions or those that are API extensions. Clients that must work against all resource types should specify multiple content types in their `Accept` header to support fallback to JSON:
187+
188+
```
189+
Accept: application/vnd.kubernetes.protobuf, application/json
190+
```
191+
192+
193+
### Protobuf encoding
194+
195+
Kubernetes uses an envelope wrapper to encode Protobuf responses. That wrapper starts with a 4 byte magic number to help identify content in disk or in etcd as Protobuf (as opposed to JSON), and then is followed by a Protobuf encoded wrapper message, which describes the encoding and type of the underlying object and then contains the object.
196+
197+
The wrapper format is:
198+
199+
```
200+
A four byte magic number prefix:
201+
Bytes 0-3: "k8s\x00" [0x6b, 0x38, 0x73, 0x00]
202+
203+
An encoded Protobuf message with the following IDL:
204+
message Unknown {
205+
// typeMeta should have the string values for "kind" and "apiVersion" as set on the JSON object
206+
optional TypeMeta typeMeta = 1;
207+
208+
// raw will hold the complete serialized object in protobuf. See the protobuf definitions in the client libraries for a given kind.
209+
optional bytes raw = 2;
210+
211+
// contentEncoding is encoding used for the raw data. Unspecified means no encoding.
212+
optional string contentEncoding = 3;
213+
214+
// contentType is the serialization method used to serialize 'raw'. Unspecified means application/vnd.kubernetes.protobuf and is usually
215+
// omitted.
216+
optional string contentType = 4;
217+
}
218+
219+
message TypeMeta {
220+
// apiVersion is the group/version for this type
221+
optional string apiVersion = 1;
222+
// kind is the name of the object schema. A protobuf definition should exist for this object.
223+
optional string kind = 2;
224+
}
225+
```
226+
227+
Clients that receive a response in `application/vnd.kubernetes.protobuf` that does not match the expected prefix should reject the response since
228+
future versions may need to alter the serialization format in an incompatible way, and will do so by changing the prefix.
229+
230+
{% endcapture %}
231+
232+
{% include templates/concept.md %}

0 commit comments

Comments
 (0)