Skip to content

Commit 34d243a

Browse files
author
Tim Bannister
committed
Add advice about choosing an update mechanism
Explain options for updating existing objects in the Kubernetes API.
1 parent 84d072e commit 34d243a

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,10 @@ See [Authorization Overview](/docs/reference/access-authn-authz/authorization/).
940940

941941
## Updates to existing resources {#patch-and-apply}
942942

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+
943947
You can overwrite (**update**) an existing resource - for example, a ConfigMap -
944948
using an HTTP PUT. For a PUT request, it is the client's responsibility to specify
945949
the `resourceVersion` (taking this from the object being updated). Kubernetes uses
@@ -1008,6 +1012,69 @@ at the HTTP level, the logical Kubernetes operation is always **patch**.
10081012

10091013
See [Server Side Apply](/docs/reference/using-api/server-side-apply/) for more details.
10101014

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+
10111078
## Resource versions
10121079

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

0 commit comments

Comments
 (0)