Skip to content

Commit 21c3005

Browse files
authored
Merge pull request #31261 from sftim/20220108_improve_api_documentation_objects
Improve documentation about Kubernetes objects & managing them
2 parents 681e415 + 0a89bf8 commit 21c3005

File tree

3 files changed

+449
-186
lines changed

3 files changed

+449
-186
lines changed

content/en/docs/reference/labels-annotations-taints/_index.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,22 @@ This annotation is deprecated. You should use the
11211121
annotation instead. Kubernetes versions 1.25 and newer ignore this annotation.
11221122
{{< /note >}}
11231123

1124+
### kubectl.kubernetes.io/last-applied-configuration
1125+
1126+
Type: Annotation
1127+
1128+
Example: _see following snippet_
1129+
```yaml
1130+
kubectl.kubernetes.io/last-applied-configuration: >
1131+
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"example","namespace":"default"},"spec":{"selector":{"matchLabels":{"app.kubernetes.io/name":foo}},"template":{"metadata":{"labels":{"app.kubernetes.io/name":"foo"}},"spec":{"containers":[{"image":"container-registry.example/foo-bar:1.42","name":"foo-bar","ports":[{"containerPort":42}]}]}}}}
1132+
```
1133+
1134+
Used on: all objects
1135+
1136+
The kubectl command line tool uses this annotation as a legacy mechanism
1137+
to track changes. That mechanism has been superseded by
1138+
[Server-side apply](/docs/reference/using-api/server-side-apply/).
1139+
11241140
### endpoints.kubernetes.io/over-capacity
11251141
11261142
Type: Annotation

content/en/docs/reference/using-api/api-concepts.md

Lines changed: 134 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ For PUT requests, Kubernetes internally classifies these as either **create** or
7676
based on the state of the existing object. An **update** is different from a **patch**; the
7777
HTTP verb for a **patch** is PATCH.
7878

79+
7980
## Resource URIs
8081

8182
All resource types are either scoped by the cluster (`/apis/GROUP/VERSION/*`) or to a
@@ -162,7 +163,7 @@ For example:
162163
```
163164

164165
2. Starting from resource version 10245, receive notifications of any API operations
165-
(such as **create**, **delete**, **apply** or **update**) that affect Pods in the
166+
(such as **create**, **delete**, **patch** or **update**) that affect Pods in the
166167
_test_ namespace. Each change notification is a JSON document. The HTTP response body
167168
(served as `application/json`) consists a series of JSON documents.
168169

@@ -750,7 +751,7 @@ Once the last finalizer is removed, the resource is actually removed from etcd.
750751

751752
## Single resource API
752753

753-
The Kubernetes API verbs **get**, **create**, **apply**, **update**, **patch**,
754+
The Kubernetes API verbs **get**, **create**, **update**, **patch**,
754755
**delete** and **proxy** support single resources only.
755756
These verbs with single resource support have no support for submitting multiple
756757
resources together in an ordered or unordered list or transaction.
@@ -786,9 +787,9 @@ These situations are:
786787
fields via `x-kubernetes-preserve-unknown-fields`).
787788
2. The field is duplicated in the object.
788789

789-
### Validation for unrecognized or duplicate fields (#setting-the-field-validation-level)
790+
### Validation for unrecognized or duplicate fields {#setting-the-field-validation-level}
790791

791-
{{< feature-state for_k8s_version="v1.27" state="stable" >}}
792+
{{< feature-state for_k8s_version="v1.27" state="stable" >}}
792793

793794
From 1.25 onward, unrecognized or duplicate fields in an object are detected via
794795
validation on the server when you use HTTP verbs that can submit data (`POST`, `PUT`, and `PATCH`). Possible levels of
@@ -937,17 +938,143 @@ rules:
937938

938939
See [Authorization Overview](/docs/reference/access-authn-authz/authorization/).
939940

940-
## Server Side Apply
941+
## Updates to existing resources {#patch-and-apply}
942+
943+
Kubernetes provides several ways to update existing objects.
944+
You can read [choosing an update mechanism](#update-mechanism-choose) to
945+
learn about which approach might be best for your use case.
946+
947+
You can overwrite (**update**) an existing resource - for example, a ConfigMap -
948+
using an HTTP PUT. For a PUT request, it is the client's responsibility to specify
949+
the `resourceVersion` (taking this from the object being updated). Kubernetes uses
950+
that `resourceVersion` information so that the API server can detect lost updates
951+
and reject requests made by a client that is out of date with the cluster.
952+
In the event that the resource has changed (the `resourceVersion` the client
953+
provided is stale), the API server returns a `409 Conflict` error response.
954+
955+
Instead of sending a PUT request, the client can send an instruction to the API
956+
server to **patch** an existing resource. A **patch** is typically appropriate
957+
if the change that the client wants to make isn't conditional on the existing data. Clients that need effective detection of lost updates should consider
958+
making their request conditional on the existing `resourceVersion` (either HTTP PUT or HTTP PATCH),
959+
and then handle any retries that are needed in case there is a conflict.
960+
961+
The Kubernetes API supports four different PATCH operations, determined by their
962+
corresponding HTTP `Content-Type` header:
963+
964+
`application/apply-patch+yaml`
965+
: Server Side Apply YAML (a Kubernetes-specific extension, based on YAML).
966+
All JSON documents are valid YAML, so you can also submit JSON using this
967+
media type. See [Server Side Apply serialization](/docs/reference/using-api/server-side-apply/#serialization)
968+
for more details.
969+
To Kubernetes, this is a **create** operation if the object does not exist,
970+
or a **patch** operation if the object already exists.
971+
972+
`application/json-patch+json`
973+
: JSON Patch, as defined in [RFC6902](https://tools.ietf.org/html/rfc6902).
974+
A JSON patch is a sequence of operations that are executed on the resource;
975+
for example `{"op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ]}`.
976+
To Kubernetes, this is a **patch** operation.
977+
978+
A **patch** using `application/json-patch+json` can include conditions to
979+
validate consistency, allowing the operation to fail if those conditions
980+
are not met (for example, to avoid a lost update).
981+
982+
`application/merge-patch+json`
983+
: JSON Merge Patch, as defined in [RFC7386](https://tools.ietf.org/html/rfc7386).
984+
A JSON Merge Patch is essentially a partial representation of the resource.
985+
The submitted JSON is combined with the current resource to create a new one,
986+
then the new one is saved.
987+
To Kubernetes, this is a **patch** operation.
988+
989+
`application/strategic-merge-patch+json`
990+
: Strategic Merge Patch (a Kubernetes-specific extension based on JSON).
991+
Strategic Merge Patch is a custom implementation of JSON Merge Patch.
992+
You can only use Strategic Merge Patch with built-in APIs, or with aggregated
993+
API servers that have special support for it. You cannot use
994+
`application/strategic-merge-patch+json` with any API
995+
defined using a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}}.
996+
997+
{{< note >}}
998+
The Kubernetes _server side apply_ mechanism has superseded Strategic Merge
999+
Patch.
1000+
{{< /note >}}
1001+
9411002

9421003
Kubernetes' [Server Side Apply](/docs/reference/using-api/server-side-apply/)
9431004
feature allows the control plane to track managed fields for newly created objects.
9441005
Server Side Apply provides a clear pattern for managing field conflicts,
945-
offers server-side `Apply` and `Update` operations, and replaces the
1006+
offers server-side **apply** and **update** operations, and replaces the
9461007
client-side functionality of `kubectl apply`.
9471008

948-
The API verb for Server-Side Apply is **apply**.
1009+
For Server-Side Apply, Kubernetes treats the request as a **create** if the object
1010+
does not yet exist, and a **patch** otherwise. For other requests that use PATCH
1011+
at the HTTP level, the logical Kubernetes operation is always **patch**.
1012+
9491013
See [Server Side Apply](/docs/reference/using-api/server-side-apply/) for more details.
9501014

1015+
### Choosing an update mechanism {#update-mechanism-choose}
1016+
1017+
#### HTTP PUT to replace existing resource {#update-mechanism-update}
1018+
1019+
The **update** (HTTP `PUT`) operation is simple to implement and flexible,
1020+
but has drawbacks:
1021+
1022+
* You need to handle conflicts where the `resourceVersion` of the object changes
1023+
between your client reading it and trying to write it back. Kubernetes always
1024+
detects the conflict, but you as the client author need to implement retries.
1025+
* You might accidentally drop fields if you decode an object locally (for example,
1026+
using client-go, you could receive fields that your client does not know how to
1027+
handle - and then drop them as part of your update.
1028+
* If there's a lot of contention on the object (even on a field, or set of fields,
1029+
that you're not trying to edit), you might have trouble sending the update.
1030+
The problem is worse for larger objects and for objects with many fields.
1031+
1032+
#### HTTP PATCH using JSON Patch {#update-mechanism-json-patch}
1033+
1034+
A **patch** update is helpful, because:
1035+
1036+
* As you're only sending differences, you have less data to send in the `PATCH`
1037+
request.
1038+
* You can make changes that rely on existing values, such as copying the
1039+
value of a particular field into an annotation.
1040+
* Unlike with an **update** (HTTP `PUT`), making your change can happen right away
1041+
even if there are frequent changes to unrelated fields): you usually would
1042+
not need to retry.
1043+
* You might still need to specify the `resourceVersion` (to match an existing object)
1044+
if you want to be extra careful to avoid lost updates
1045+
* It's still good practice to write in some retry logic in case of errors.
1046+
* You can use test conditions to careful craft specific update conditions.
1047+
For example, you can increment a counter without reading it if the existing
1048+
value matches what you expect. You can do this with no lost update risk,
1049+
even if the object has changed in other ways since you last wrote to it.
1050+
(If the test condition fails, you can fall back to reading the current value
1051+
and then write back the changed number).
1052+
1053+
However:
1054+
1055+
* you need more local (client) logic to build the patch; it helps a lot if you have
1056+
a library implementation of JSON Patch, or even for making a JSON Patch specifically against Kubernetes
1057+
* as the author of client software, you need to be careful when building the patch
1058+
(the HTTP request body) not to drop fields (the order of operations matters)
1059+
1060+
#### HTTP PATCH using Server-Side Apply {#update-mechanism-server-side-apply}
1061+
1062+
Server-Side Apply has some clear benefits:
1063+
1064+
* A single round trip: it rarely requires making a `GET` request first.
1065+
* and you can still detect conflicts for unexpected changes
1066+
* you have the option to force override a conflict, if appropriate
1067+
* Client implementations are easy to make
1068+
* You get an atomic create-or-update operation without extra effort
1069+
(similar to `UPSERT` in some SQL dialects)
1070+
1071+
However:
1072+
1073+
* Server-Side Apply does not work at all for field changes that depend on a current value of the object
1074+
* You can only apply updates to objects. Some resources in the Kubernetes HTTP API are
1075+
not objects (they do not have a `.metadata` field), and Server-Side Apply
1076+
is only relevant for Kubernetes objects.
1077+
9511078
## Resource versions
9521079

9531080
Resource versions are strings that identify the server's internal version of an

0 commit comments

Comments
 (0)