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
+
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
+
237
295
### Custom Resources
238
296
239
297
By default, Server Side Apply treats custom resources as unstructured data. All
@@ -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