Add transferring ownership section to api concepts
This commit is contained in:
@@ -414,12 +414,6 @@ object or is [combined](#merge-strategy), by the server, with the existing objec
|
||||
|
||||
The system supports multiple appliers collaborating on a single object.
|
||||
|
||||
This model of specifying intent makes it difficult to remove existing fields.
|
||||
When a field is removed from one's config and applied, the value will be kept
|
||||
(the system assumes that you don't care about that value anymore). If an item is
|
||||
removed from a list or a map, it will be removed if no other appliers care about
|
||||
its presence.
|
||||
|
||||
Changes to an object's fields are tracked through a "[field management](#field-management)"
|
||||
mechanism. When a field's value changes, ownership moves from its current
|
||||
manager to the manager making the change. When trying to apply an object, fields
|
||||
@@ -428,8 +422,14 @@ that have a different value and are owned by another manager will result in a
|
||||
collaborator's changes. Conflicts can be forced, in which case the value will be
|
||||
overridden, and the ownership will be transferred.
|
||||
|
||||
It is meant both as a replacement for the original `kubectl apply` and as a
|
||||
simpler mechanism to write controllers.
|
||||
If you remove a field from a configuration and apply the configuration, server side apply checks
|
||||
if there are any other field managers that also own the field. If the field is
|
||||
not owned by any other field managers, it is either deleted from the live
|
||||
object or reset to its default value, if it has one. The same rule applies to associative list or
|
||||
map items.
|
||||
|
||||
Server side apply is meant both as a replacement for the original `kubectl
|
||||
apply` and as a simpler mechanism for controllers to enact their changes.
|
||||
|
||||
### Field Management
|
||||
|
||||
@@ -448,8 +448,12 @@ to the Server Side Apply endpoint. When using Server-Side Apply, trying to
|
||||
change a field which is managed by someone else will result in a rejected
|
||||
request (if not forced, see [Conflicts](#conflicts)).
|
||||
|
||||
Field management is stored in a newly introduced `managedFields` field that is
|
||||
part of an object's
|
||||
When two or more appliers set a field to the same value, they share ownership of
|
||||
that field. Any subsequent attempt to change the value of the shared field, by any of
|
||||
the appliers, results in a conflict. Shared field owners may give up ownership
|
||||
of a field by removing it from their configuration.
|
||||
|
||||
Field management is stored in a`managedFields` field that is part of an object's
|
||||
[`metadata`](/docs/reference/generated/kubernetes-api/{{< latest-version >}}/#objectmeta-v1-meta).
|
||||
|
||||
A simple example of an object created by Server Side Apply could look like this:
|
||||
@@ -627,13 +631,88 @@ read-modify-write and/or patch are the following:
|
||||
It is strongly recommended for controllers to always "force" conflicts, since they
|
||||
might not be able to resolve or act on these conflicts.
|
||||
|
||||
### Transferring Ownership
|
||||
|
||||
In addition to the concurrency controls provided by [conflict
|
||||
resolution](#conflicts), Server Side Apply provides ways to perform coordinated
|
||||
field ownership transfers from users to controllers.
|
||||
|
||||
This is best explained by example. Let's look at how to safely transfer
|
||||
ownership of the `replicas` field from a user to a controller while enabling
|
||||
automatic horizontal scaling for a Deployment, using the HorizontalPodAutoscaler
|
||||
resource and its accompanying controller.
|
||||
|
||||
Say a user has defined deployment with `replicas` set to the desired value:
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment.yaml" >}}
|
||||
|
||||
And the user has created the deployment using server side apply like so:
|
||||
|
||||
```shell
|
||||
kubectl apply -f application/ssa/nginx-deployment.yaml --server-side
|
||||
```
|
||||
|
||||
Then later, HPA is enabled for the deployment, e.g.:
|
||||
|
||||
```
|
||||
kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10
|
||||
```
|
||||
|
||||
Now, the user would like to remove `replicas` from their configuration, so they
|
||||
don't accidentally fight with the HPA controller. However, there is a race: it
|
||||
might take some time before HPA feels the need to adjust `replicas`, and if
|
||||
the user removes `replicas` before the HPA writes to the field and becomes
|
||||
its owner, then apiserver will set `replicas` to 1, its default value. This
|
||||
is not what the user wants to happen, even temporarily.
|
||||
|
||||
There are two solutions:
|
||||
|
||||
- (easy) Leave `replicas` in the configuration; when HPA eventually writes to that
|
||||
field, the system gives the user a conflict over it. At that point, it is safe
|
||||
to remove from the configuration.
|
||||
|
||||
- (more advanced) If, however, the user doesn't want to wait, for example
|
||||
because they want to keep the cluster legible to coworkers, then they can take
|
||||
the following steps to make it safe to remove `replicas` from their
|
||||
configuration:
|
||||
|
||||
First, the user defines a new configuration containing only the `replicas` field:
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment-replicas-only.yaml" >}}
|
||||
|
||||
The user applies that configuration using the field manager name `handover-to-hpa`:
|
||||
|
||||
```shell
|
||||
kubectl apply -f application/ssa/nginx-deployment-replicas-only.yaml --server-side --field-manager=handover-to-hpa --validate=false
|
||||
```
|
||||
|
||||
If the apply results in a conflict with the HPA controller, then do nothing. The
|
||||
conflict just indicates the controller has claimed the field earlier in the
|
||||
process that it sometimes does.
|
||||
|
||||
At this point the user may remove the `replicas` field from their configuration.
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment-no-replicas.yaml" >}}
|
||||
|
||||
Note that whenever the HPA controller sets the `replicas` field to a new value,
|
||||
the temporary field manager will no longer own any fields and will be
|
||||
automatically deleted. No clean up is required.
|
||||
|
||||
### Transferring Ownership Between Users
|
||||
|
||||
Users can transfer ownership of a field between each other by setting the field
|
||||
to the same value in both of their applied configs, causing them to share
|
||||
ownership of the field. Once the users share ownership of the field, one of them
|
||||
can remove the field from their applied configuration to give up ownership and
|
||||
complete the transfer to the other user.
|
||||
|
||||
### Comparison with Client Side Apply
|
||||
|
||||
A consequence of the conflict detection and resolution implemented by Server
|
||||
Side Apply is that an applier always has up to date field values in their local
|
||||
state. If they don't, they get a conflict the next time they apply. Any of the
|
||||
three options to resolve conflicts results in the applied config being an up to
|
||||
date subset of the object on the server's fields.
|
||||
three options to resolve conflicts results in the applied configuration being an
|
||||
up to date subset of the object on the server's fields.
|
||||
|
||||
This is different from Client Side Apply, where outdated values which have been
|
||||
overwritten by other users are left in an applier's local config. These values
|
||||
|
||||
Reference in New Issue
Block a user