@@ -5,7 +5,6 @@ weight: 25
5
5
min-kubernetes-server-version : 1.16
6
6
---
7
7
<!--
8
- ---
9
8
title: Server-Side Apply
10
9
reviewers:
11
10
- smarterclayton
@@ -15,7 +14,6 @@ reviewers:
15
14
content_type: concept
16
15
weight: 25
17
16
min-kubernetes-server-version: 1.16
18
- ---
19
17
-->
20
18
21
19
<!-- overview -->
@@ -25,15 +23,15 @@ min-kubernetes-server-version: 1.16
25
23
<!--
26
24
## Introduction
27
25
28
- Server Side Apply helps users and controllers manage their resources via
29
- declarative configurations. It allows them to create and/or modify their
26
+ Server Side Apply helps users and controllers manage their resources through
27
+ declarative configurations. Clients can create and/or modify their
30
28
[objects](/docs/concepts/overview/working-with-objects/kubernetes-objects/)
31
- declaratively, simply by sending their fully specified intent.
29
+ declaratively by sending their fully specified intent.
32
30
-->
33
31
## 简介 {#introduction}
34
32
35
33
服务器端应用协助用户、控制器通过声明式配置的方式管理他们的资源。
36
- 它发送完整描述的目标 (A fully specified intent),
34
+ 客户端可以发送完整描述的目标 (A fully specified intent),
37
35
声明式地创建和/或修改
38
36
[ 对象] ( /zh/docs/concepts/overview/working-with-objects/kubernetes-objects/ ) 。
39
37
@@ -84,7 +82,7 @@ Server side apply is meant both as a replacement for the original `kubectl
84
82
apply` and as a simpler mechanism for controllers to enact their changes.
85
83
86
84
If you have Server Side Apply enabled, the control plane tracks managed fields
87
- for all newlly created objects.
85
+ for all newly created objects.
88
86
-->
89
87
服务器端应用既是原有 ` kubectl apply ` 的替代品,
90
88
也是控制器发布自身变化的一个简化机制。
@@ -133,7 +131,7 @@ the appliers, results in a conflict. Shared field owners may give up ownership
133
131
of a field by removing it from their configuration.
134
132
135
133
Field management is stored in a`managedFields` field that is part of an object's
136
- [`metadata`](/docs/reference/generated/kubernetes-api/{{< latest- version >}}/#objectmeta-v1-meta).
134
+ [`metadata`](/docs/reference/generated/kubernetes-api/{{< param " version" >}}/#objectmeta-v1-meta).
137
135
138
136
A simple example of an object created by Server Side Apply could look like this:
139
137
-->
@@ -142,7 +140,8 @@ A simple example of an object created by Server Side Apply could look like this:
142
140
共享字段的所有者可以放弃字段的所有权,这只需从配置文件中删除该字段即可。
143
141
144
142
字段管理的信息存储在 ` managedFields ` 字段中,该字段是对象的
145
- [ ` metadata ` ] (/docs/reference/generated/kubernetes-api/{{< latest-version >}}/#objectmeta-v1-meta)中的一部分。
143
+ [ ` metadata ` ] (/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#objectmeta-v1-meta)
144
+ 中的一部分。
146
145
147
146
服务器端应用创建对象的简单示例如下:
148
147
@@ -356,15 +355,14 @@ would have failed due to conflicting ownership.
356
355
357
356
The merging strategy, implemented with Server Side Apply, provides a generally
358
357
more stable object lifecycle. Server Side Apply tries to merge fields based on
359
- the fact who manages them instead of overruling just based on values. This way
360
- it is intended to make it easier and more stable for multiple actors updating
361
- the same object by causing less unexpected interference.
358
+ the actor who manages them instead of overruling based on values. This way
359
+ multiple actors can update the same object without causing unexpected interference.
362
360
-->
363
361
# # 合并策略 {#merge-strategy}
364
362
365
363
由服务器端应用实现的合并策略,提供了一个总体更稳定的对象生命周期。
366
- 服务器端应用试图依据谁管理它们来合并字段,而不只是根据值来否决 。
367
- 这么做是为了多个参与者可以更简单、更稳定的更新同一个对象,且避免引起意外干扰 。
364
+ 服务器端应用试图依据负责管理它们的主体来合并字段,而不是根据值来否决 。
365
+ 这么做是为了多个主体可以更新同一个对象,且不会引起意外的相互干扰 。
368
366
369
367
<!--
370
368
When a user sends a "fully-specified intent" object to the Server Side Apply
@@ -387,7 +385,7 @@ merging, see
387
385
A number of markers were added in Kubernetes 1.16 and 1.17, to allow API
388
386
developers to describe the merge strategy supported by lists, maps, and
389
387
structs. These markers can be applied to objects of the respective type,
390
- in Go files or in the OpenAPI schema definition of the
388
+ in Go files or in the OpenAPI schema definition of the
391
389
[CRD](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io):
392
390
-->
393
391
Kubernetes 1.16 和 1.17 中添加了一些标记,
@@ -399,18 +397,116 @@ Kubernetes 1.16 和 1.17 中添加了一些标记,
399
397
<!--
400
398
| Golang marker | OpenAPI extension | Accepted values | Description | Introduced in |
401
399
|---|---|---|---|---|
402
- | `//+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 |
403
- | `//+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 |
400
+ | `//+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 |
401
+ | `//+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 |
404
402
| `//+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 |
405
403
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to structs; otherwise same usage and OpenAPI annotation as `//+mapType`.| 1.17 |
406
404
-->
407
405
| Golang 标记 | OpenAPI extension | 可接受的值 | 描述 | 引入版本 |
408
406
|---|---|---|---|---|
409
- | `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | 适用于 list。 `atomic` 和 ` set` 适用于只包含标量元素的 list。 `map` 适用于只包含嵌套类型的 list。 如果配置为 `atomic`, 合并时整个列表会被替换掉; 任何时候,唯一的管理器都把列表作为一个整体来管理。如果是 `set` 或 `map` ,不同的管理器也可以分开管理条目。 | 1.16 |
410
- | `//+listMapKey` | `x-kubernetes-list-map-keys` | 用来唯一标识条目的 map keys 切片 ,例如 `["port", "protocol"]` | 仅当 `+listType=map` 时适用。组合值的字符串切片必须唯一标识列表中的条目。尽管有多个 key ,`listMapKey` 是单数的,这是因为 key 需要在 Go 类型中单独的指定 。 | 1.16 |
407
+ | `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | 适用于 list。` set` 适用于仅包含标量元素的列表。这些元素必须是不重复的。 `map` 仅适用于包含嵌套类型的列表。列表中的键(参见 `listMapKey`)不可以重复。`atomic` 适用于任何类型的列表。 如果配置为 `atomic`,则合并时整个列表会被替换掉。 任何时候,只有一个管理器负责管理指定列表。如果配置为 `set` 或 `map`,不同的管理器也可以分开管理条目。 | 1.16 |
408
+ | `//+listMapKey` | `x-kubernetes-list-map-keys` | 字段名称的列表 ,例如, `["port", "protocol"]` | 仅当 `+listType=map` 时适用。取值为字段名称的列表,这些字段值的组合能够唯一标识列表中的条目。尽管可以存在多个键 ,`listMapKey` 是单数的,这是因为键名需要在 Go 类型中各自独立指定。键字段必须是标量 。 | 1.16 |
411
409
| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 map。 `atomic` 指 map 只能被单个的管理器整个的替换。 `granular` 指 map 支持多个管理器各自更新自己的字段。 | 1.17 |
412
410
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 structs;否则就像 `//+mapType` 有相同的用法和 openapi 注释.| 1.17 |
413
411
412
+ <!--
413
+ If `listType` is missing, the API server interprets a
414
+ ` patchMergeStrategy=merge` marker as a `listType=map` and the
415
+ corresponding `patchMergeKey` marker as a `listMapKey`.
416
+
417
+ The `atomic` list type is recursive.
418
+
419
+ These markers are specified as comments and don't have to be repeated as
420
+ field tags.
421
+ -->
422
+ 若未指定 `listType`,API 服务器将 `patchMergeStrategy=merge` 标记解释为
423
+ ` listType=map` 并且视对应的 `patchMergeKey` 标记为 `listMapKey` 取值。
424
+
425
+ ` atomic` 列表类型是递归的。
426
+
427
+ 这些标记都是用源代码注释的方式给出的,不必作为字段标签(tag)再重复。
428
+
429
+ <!--
430
+ # ## Compatibility across topology changes
431
+ -->
432
+ # ## 拓扑变化时的兼容性 {#compatibility-across-toplogy-changes}
433
+
434
+ <!--
435
+ On rare occurences, a CRD or built-in type author may want to change the
436
+ specific topology of a field in their resource without incrementing its
437
+ version. Changing the topology of types, by upgrading the cluster or
438
+ updating the CRD, has different consequences when updating existing
439
+ objects. There are two categories of changes : when a field goes from
440
+ ` map` /`set`/`granular` to `atomic` and the other way around.
441
+ -->
442
+ 在极少的情况下,CRD 或者内置类型的作者可能希望更改其资源中的某个字段的
443
+ 拓扑配置,同时又不提升版本号。
444
+ 通过升级集群或者更新 CRD 来更改类型的拓扑信息与更新现有对象的结果不同。
445
+ 变更的类型有两种:一种是将字段从 `map`/`set`/`granular` 更改为 `atomic`,
446
+ 另一种是做逆向改变。
447
+
448
+ <!--
449
+ When the `listType`, `mapType`, or `structType` changes from
450
+ ` map` /`set`/`granular` to `atomic`, the whole list, map or struct of
451
+ existing objects will end-up being owned by actors who owned an element
452
+ of these types. This means that any further change to these objects
453
+ would cause a conflict.
454
+ -->
455
+ 当 `listType`、`mapType` 或 `structType` 从 `map`/`set`/`granular` 改为
456
+ ` atomic` 时,现有对象的整个列表、映射或结构的属主都会变为这些类型的
457
+ 元素之一的属主。这意味着,对这些对象的进一步变更会引发冲突。
458
+
459
+ <!--
460
+ When a list, map, or struct changes from `atomic` to
461
+ ` map` /`set`/`granular`, the API server won't be able to infer the new
462
+ ownership of these fields. Because of that, no conflict will be produced
463
+ when objects have these fields updated. For that reason, it is not
464
+ recommended to change a type from `atomic` to `map`/`set`/`granular`.
465
+
466
+ Take for example, the custom resource :
467
+ -->
468
+ 当一个列表、映射或结构从 `atomic` 改为 `map`/`set`/`granular` 之一
469
+ 时,API 服务器无法推导这些字段的新的属主。因此,当对象的这些字段
470
+ 再次被更新时不会引发冲突。出于这一原因,不建议将某类型从 `atomic` 改为
471
+ ` map` /`set`/`granular`。
472
+
473
+ 以下面的自定义资源为例:
474
+
475
+ ` ` ` yaml
476
+ apiVersion: example.com/v1
477
+ kind: Foo
478
+ metadata:
479
+ name: foo-sample
480
+ managedFields:
481
+ - manager: manager-one
482
+ operation: Apply
483
+ apiVersion: example.com/v1
484
+ fields:
485
+ f:spec:
486
+ f:data: {}
487
+ spec:
488
+ data:
489
+ key1: val1
490
+ key2: val2
491
+ ` ` `
492
+
493
+ <!--
494
+ Before `spec.data` gets changed from `atomic` to `granular`,
495
+ ` manager-one` owns the field `spec.data`, and all the fields within it
496
+ (`key1` and `key2`). When the CRD gets changed to make `spec.data`
497
+ ` granular` , `manager-one` continues to own the top-level field
498
+ ` spec.data` (meaning no other managers can delete the map called `data`
499
+ without a conflict), but it no longer owns `key1` and `key2`, so another
500
+ manager can then modify or delete those fields without conflict.
501
+ -->
502
+ 在 `spec.data` 从 `atomic` 改为 `granular` 之前,`manager-one` 是
503
+ ` spec.data` 字段及其所包含字段(`key1` 和 `key2`)的属主。
504
+ 当对应的 CRD 被更改,使得 `spec.data` 变为 `granular` 拓扑时,
505
+ ` manager-one` 继续拥有顶层字段 `spec.data`(这意味着其他管理者想
506
+ 删除名为 `data` 的映射而不引起冲突是不可能的),但不再拥有
507
+ ` key1` 和 `key2`。因此,其他管理者可以在不引起冲突的情况下更改
508
+ 或删除这些字段。
509
+
414
510
<!--
415
511
# ## Custom Resources
416
512
@@ -435,7 +531,7 @@ type.
435
531
这些注解将在合并此类型的对象时使用。
436
532
437
533
<!--
438
- # ## Using Server-Side Apply in a controller
534
+ # # Using Server-Side Apply in a controller
439
535
440
536
As a developer of a controller, you can use server-side apply as a way to
441
537
simplify the update logic of your controller. The main differences with a
@@ -450,7 +546,7 @@ read-modify-write and/or patch are the following:
450
546
It is strongly recommended for controllers to always "force" conflicts, since they
451
547
might not be able to resolve or act on these conflicts.
452
548
-->
453
- # ## 在控制器中使用服务器端应用 {#using-server-side-apply-in-controller}
549
+ # # 在控制器中使用服务器端应用 {#using-server-side-apply-in-controller}
454
550
455
551
控制器的开发人员可以把服务器端应用作为简化控制器的更新逻辑的方式。
456
552
读-改-写 和/或 patch 的主要区别如下所示:
@@ -463,7 +559,7 @@ might not be able to resolve or act on these conflicts.
463
559
强烈推荐:设置控制器在冲突时强制执行,这是因为冲突发生时,它们没有其他解决方案或措施。
464
560
465
561
<!--
466
- # ## Transferring Ownership
562
+ # # Transferring Ownership
467
563
468
564
In addition to the concurrency controls provided by [conflict resolution](#conflicts),
469
565
Server Side Apply provides ways to perform coordinated
@@ -476,7 +572,7 @@ resource and its accompanying controller.
476
572
477
573
Say a user has defined deployment with `replicas` set to the desired value :
478
574
-->
479
- # ## 转移所有权 {#transferring-ownership}
575
+ # # 转移所有权 {#transferring-ownership}
480
576
481
577
除了通过[冲突解决方案](#conflicts)提供的并发控制,
482
578
服务器端应用提供了一些协作方式来将字段所有权从用户转移到控制器。
@@ -526,7 +622,7 @@ is not what the user wants to happen, even temporarily.
526
622
<!--
527
623
There are two solutions :
528
624
529
- - (easy ) Leave `replicas` in the configuration; when HPA eventually writes to that
625
+ - (basic ) Leave `replicas` in the configuration; when HPA eventually writes to that
530
626
field, the system gives the user a conflict over it. At that point, it is safe
531
627
to remove from the configuration.
532
628
@@ -539,9 +635,9 @@ First, the user defines a new configuration containing only the `replicas` field
539
635
-->
540
636
这里有两个解决方案:
541
637
542
- - (容易) 把 `replicas` 留在配置文件中;当 HPA 最终写入那个字段,
638
+ - (基本操作) 把 `replicas` 留在配置文件中;当 HPA 最终写入那个字段,
543
639
系统基于此事件告诉用户:冲突发生了。在这个时间点,可以安全的删除配置文件。
544
- - (高级 )然而,如果用户不想等待,比如他们想为合作伙伴保持集群清晰,
640
+ - (高级操作 )然而,如果用户不想等待,比如他们想为合作伙伴保持集群清晰,
545
641
那他们就可以执行以下步骤,安全的从配置文件中删除 `replicas`。
546
642
547
643
首先,用户新定义一个只包含 `replicas` 字段的配置文件:
@@ -561,13 +657,13 @@ kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment-replic
561
657
562
658
<!--
563
659
If the apply results in a conflict with the HPA controller, then do nothing. The
564
- conflict just indicates the controller has claimed the field earlier in the
660
+ conflict indicates the controller has claimed the field earlier in the
565
661
process than it sometimes does.
566
662
567
663
At this point the user may remove the `replicas` field from their configuration.
568
664
-->
569
665
如果应用操作和 HPA 控制器产生冲突,那什么都不做。
570
- 冲突只是表明控制器在更早的流程中已经对字段声明过所有权 。
666
+ 冲突表明控制器在更早的流程中已经对字段声明过所有权 。
571
667
572
668
在此时间点,用户可以从配置文件中删除 `replicas` 。
573
669
@@ -583,15 +679,15 @@ automatically deleted. No clean up is required.
583
679
这里不需要执行清理工作。
584
680
585
681
<!--
586
- # # Transferring Ownership Between Users
682
+ # ## Transferring Ownership Between Users
587
683
588
684
Users can transfer ownership of a field between each other by setting the field
589
685
to the same value in both of their applied configs, causing them to share
590
686
ownership of the field. Once the users share ownership of the field, one of them
591
687
can remove the field from their applied configuration to give up ownership and
592
688
complete the transfer to the other user.
593
689
-->
594
- # # 在用户之间转移所有权 {#transferring-ownership-between-users}
690
+ # ## 在用户之间转移所有权 {#transferring-ownership-between-users}
595
691
596
692
通过在配置文件中把一个字段设置为相同的值,用户可以在他们之间转移字段的所有权,
597
693
从而共享了字段的所有权。
@@ -763,7 +859,7 @@ Data: [{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]
763
859
<!--
764
860
This will overwrite the managedFields with a list containing a single empty
765
861
entry that then results in the managedFields being stripped entirely from the
766
- object. Note that just setting the managedFields to an empty list will not
862
+ object. Note that setting the managedFields to an empty list will not
767
863
reset the field. This is on purpose, so managedFields never get stripped by
768
864
clients not aware of the field.
769
865
@@ -772,9 +868,9 @@ than the managedFields, this will result in the managedFields being reset
772
868
first and the other changes being processed afterwards. As a result the
773
869
applier takes ownership of any fields updated in the same request.
774
870
-->
775
- 这一操作将用只包含一个空条目的 list 覆写 managedFields,
871
+ 这一操作将用只包含一个空条目的列表覆写 managedFields,
776
872
来实现从对象中整个的去除 managedFields。
777
- 注意,只把 managedFields 设置为空 list 并不会重置字段 。
873
+ 注意,只把 managedFields 设置为空列表并不会重置字段 。
778
874
这么做是有目的的,所以 managedFields 将永远不会被与该字段无关的客户删除。
779
875
780
876
在重置操作结合 managedFields 以外其他字段更改的场景中,
@@ -804,7 +900,8 @@ should have the same flag setting.
804
900
-->
805
901
# # 禁用此功能 {#disabling-the-feature}
806
902
807
- 服务器端应用是一个 beta 版特性,默认启用。
903
+ 服务器端应用是一个 Beta 版特性,默认启用。
808
904
要关闭此[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates),
809
905
你需要在启动 `kube-apiserver` 时包含参数 `--feature-gates ServerSideApply=false`。
810
- 如果你有多个 `kube-apiserver` 副本,他们都应该有相同的标记设置。
906
+ 如果你有多个 `kube-apiserver` 副本,它们的标志设置应该都相同。
907
+
0 commit comments