You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | Applicable to lists. `atomic` and `set` apply to lists with scalar elements only. `map` applies to lists of nested types only. If configured as `atomic`, the entire list is replaced during merge; a single manager manages the list as a whole at any one time. If `set` or `map`, different managers can manage entries separately. | 1.16 |
233
-
| `//+listMapKey` | `x-kubernetes-list-map-keys` | Slice of map keys that uniquely identify entries for example `["port", "protocol"]` | Only applicable when `+listType=map`. A slice of strings whose values in combination must uniquely identify list entries. While there can be multiple keys, `listMapKey` is singular because keys need to be specified individually in the Go type. | 1.16 |
232
+
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | Applicable to lists. `set` applies to lists that include only scalar elements. These elements must be unique. `map` applies to lists of nested types only. The key values (see `listMapKey`) must be unique in the list. `atomic` can apply to any list. If configured as `atomic`, the entire list is replaced during merge. At any point in time, a single manager owns the list. If `set` or `map`, different managers can manage entries separately. | 1.16 |
233
+
| `//+listMapKey` | `x-kubernetes-list-map-keys` | List of field names, e.g. `["port", "protocol"]` | Only applicable when `+listType=map`. A list of field names whose values uniquely identify entries in the list. While there can be multiple keys, `listMapKey` is singular because keys need to be specified individually in the Go type. The key fields must be scalars. | 1.16 |
234
234
| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to maps. `atomic` means that the map can only be entirely replaced by a single manager. `granular` means that the map supports separate managers updating individual fields. | 1.17 |
235
235
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to structs; otherwise same usage and OpenAPI annotation as `//+mapType`.| 1.17 |
236
236
237
-
### Custom Resources
237
+
If `listType` is missing, the API server interprets a
238
+
`patchMergeStrategy=merge`marker as a `listType=map` and the
239
+
corresponding `patchMergeKey` marker as a `listMapKey`.
240
+
241
+
The `atomic` list type is recursive.
242
+
243
+
These markers are specified as comments and don't have to be repeated as
244
+
field tags.
245
+
246
+
### Compatibility across topology changes
247
+
248
+
On rare occurences, a CRD or built-in type author may want to change the
249
+
specific topology of a field in their resource without incrementing its
250
+
version. Changing the topology of types, by upgrading the cluster or
251
+
updating the CRD, has different consequences when updating existing
252
+
objects. There are two categories of changes: when a field goes from
253
+
`map`/`set`/`granular` to `atomic` and the other way around.
254
+
255
+
When the `listType`, `mapType`, or `structType` changes from
256
+
`map`/`set`/`granular` to `atomic`, the whole list, map or struct of
257
+
existing objects will end-up being owned by actors who owned an element
258
+
of these types. This means that any further change to these objects
259
+
would cause a conflict.
260
+
261
+
When a list, map, or struct changes from `atomic` to
262
+
`map`/`set`/`granular`, the API server won't be able to infer the new
263
+
ownership of these fields. Because of that, no conflict will be produced
264
+
when objects have these fields updated. For that reason, it is not
265
+
recommended to change a type from `atomic` to `map`/`set`/`granular`.
266
+
267
+
Take for example, the custom resource:
268
+
269
+
```yaml
270
+
apiVersion: example.com/v1
271
+
kind: Foo
272
+
metadata:
273
+
name: foo-sample
274
+
managedFields:
275
+
- manager: manager-one
276
+
operation: Apply
277
+
apiVersion: example.com/v1
278
+
fields:
279
+
f:spec:
280
+
f:data: {}
281
+
spec:
282
+
data:
283
+
key1: val1
284
+
key2: val2
285
+
```
286
+
287
+
Before `spec.data` gets changed from `atomic` to `granular`,
288
+
`manager-one`owns the field `spec.data`, and all the fields within it
289
+
(`key1` and `key2`). When the CRD gets changed to make `spec.data`
290
+
`granular`, `manager-one` continues to own the top-level field
291
+
`spec.data`(meaning no other managers can delete the map called `data`
292
+
without a conflict), but it no longer owns `key1` and `key2`, so another
293
+
manager can then modify or delete those fields without conflict.
294
+
295
+
## Custom Resources
238
296
239
297
By default, Server Side Apply treats custom resources as unstructured data. All
240
298
keys are treated the same as struct fields, and all lists are considered atomic.
@@ -245,7 +303,7 @@ that contains annotations as defined in the previous "Merge Strategy"
245
303
section, these annotations will be used when merging objects of this
246
304
type.
247
305
248
-
### Using Server-Side Apply in a controller
306
+
## Using Server-Side Apply in a controller
249
307
250
308
As a developer of a controller, you can use server-side apply as a way to
251
309
simplify the update logic of your controller. The main differences with a
@@ -260,7 +318,7 @@ read-modify-write and/or patch are the following:
260
318
It is strongly recommended for controllers to always "force" conflicts, since they
261
319
might not be able to resolve or act on these conflicts.
262
320
263
-
### Transferring Ownership
321
+
## Transferring Ownership
264
322
265
323
In addition to the concurrency controls provided by [conflict resolution](#conflicts),
266
324
Server Side Apply provides ways to perform coordinated
@@ -329,7 +387,7 @@ Note that whenever the HPA controller sets the `replicas` field to a new value,
329
387
the temporary field manager will no longer own any fields and will be
330
388
automatically deleted. No clean up is required.
331
389
332
-
## Transferring Ownership Between Users
390
+
### Transferring Ownership Between Users
333
391
334
392
Users can transfer ownership of a field between each other by setting the field
335
393
to the same value in both of their applied configs, causing them to share
@@ -458,4 +516,3 @@ Server Side Apply is a beta feature, so it is enabled by default. To turn this
458
516
you need to include the `--feature-gates ServerSideApply=false` flag when
459
517
starting `kube-apiserver`. If you have multiple `kube-apiserver` replicas, all
0 commit comments