-
Notifications
You must be signed in to change notification settings - Fork 14.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Blog post for Server Side Apply to GA #28964
Conversation
✔️ Deploy Preview for kubernetes-io-main-staging ready! 🔨 Explore the source changes: 437f38b 🔍 Inspect the deploy log: https://app.netlify.com/sites/kubernetes-io-main-staging/deploys/610ab04948e06d0007bbd88c 😎 Browse the preview: https://deploy-preview-28964--kubernetes-io-main-staging.netlify.app |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi. Here's some early feedback. I hope it's useful.
👀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot, just a few small changes. Well written!
|
||
The new client-go support makes it much easier to use Server-side Apply in controllers. | ||
|
||
When authoring new controllers to use Server-side Apply, a good approach is to have the controller recreate the apply configuration for an object each time it reconciles that object. This ensures that the controller fully reconciles all the fields that it is responsible for. Controllers typically should unconditionally set all the fields they own by setting `Force: true` in the `ApplyOptions`. Controllers must also provide a `FieldManager` name that is unique to the reconciliation loop that apply is called from. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing this replaces deepEquals logic? Wouldn't this add additional load on the api server? But agree that this definitely simplifies the reconciler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on how this replaces deepEquals
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@apelisse , sorry about the confusion. I was asking if this phrase ('recreate the apply configuration for an object each time it reconciles') meant SSA is a replacement for performing deepEquals
before sending create/update request to k8s api server to avoid infinite reconcile loop?
Say, controller is reconciling a CRD and creating Statefulset. Such a controller will watch both CRD and Statefulset. When it performs create/update on the Statefulset, it is trigger the watch event to the controller triggering another reconcile loop. This loop would have performed a deepEquals
or something else to prevent repeated invocation of reconcile loop. SSA seems to avoid this, by not bumping up the resourceVersion. But the deepEquals
logic is now replaced with a SSA call that is over the network. Hence was wondering if this might add load to the api server. Please correct me if I've got something wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your assumptions are all reasonable and great. This should, in general, replace the deepEqual
since controllers shouldn't even have to download the object in the first place. We've spent a lot of time benchmarking and optimizating the apiserver so that this doesn't become a problem, thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
Hi. If this is ready for review, please retitle accordingly. The release blog team can assign a publication date. |
This blog is currently scheduled for publication on August 6th. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reads really well! I had one nit and suggested a few changes to how URLs were formed. I'm not sure if links to blogs can use the same form, so I didn't suggest changes there.
@Jefftree since this is in review, can you remove WIP from the PR title? Thanks! |
I'll get Prow to help |
To help reviewers, @Jefftree, would you be willing to update the PR description so that it is current? |
/wg api-expression |
Thanks, LGTM for me! |
@Jefftree one thing you might want to do is bump your repository's main branch to something more current (it's currently stale by 4763 commits). Anyway, I tested a merge locally and it still looks fine. |
LGTM label has been added. Git tree hash: 38fe2a9245503f4eeac7ff53729d7af7d38c381f
|
Co-authored-by: Tim Bannister <[email protected]>
Rebased on the latest main branch. Thanks |
This looks really good! /lgtm |
LGTM label has been added. Git tree hash: 380ddcd2087ce6b1d9c02dc0f85fb6904ec5bb5e
|
/approve Can unhold once Kubernetes v1.22 release is finished. |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: sftim The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/hold cancel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the great doc! I have some feedback. Not sure if it's the right place to send.
|
||
When authoring new controllers to use Server-side Apply, a good approach is to have the controller recreate the apply configuration for an object each time it reconciles that object. This ensures that the controller fully reconciles all the fields that it is responsible for. Controllers typically should unconditionally set all the fields they own by setting `Force: true` in the `ApplyOptions`. Controllers must also provide a `FieldManager` name that is unique to the reconciliation loop that apply is called from. | ||
|
||
When upgrading existing controllers to use Server-side Apply the same approach often works well--migrate the controllers to recreate the apply configuration each time it reconciles any object. Unfortunately, the controller might have multiple code paths that update different parts of an object depending on various conditions. Migrating a controller like this to Server-side Apply can be risky because if the controller forgets to include any fields in an apply configuration that is included in a previous apply request, a field can be accidently deleted. To ease this type of migration, client-go apply support provides a way to replace any controller reconciliation code that performs a "read/modify-in-place/update" (or patch) workflow with a "extract/modify-in-place/apply" workflow. Here's an example of the new workflow: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the controller forgets to include any fields in an apply configuration that is included in a previous apply request, a field can be accidently deleted
@Jefftree Could you elaborate why this could happen? Is it because the field previously had its field manager set to the controller-- and if the controller omits the field in a future apply, the server will think the controller wants to delete this field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. Since the field is owned by the controller, it is assumed that the controller cares about the field. Other apply requests to update this field will cause a conflict. Omitting a field from an apply request where the applier is the owner will cause the field to be deleted (assuming there are no other owners of the field). When a controller wants to update an object via apply, it should send all fields that it owns if there is no intent to delete any field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Thanks for the clarification!
|
||
It is strongly recommended that all [Custom Resource Definitions](/docs/concepts/extend-kubernetes/api-extension/custom-resources/) (CRDs) have a schema. CRDs without a schema are treated as unstructured data by Server-side Apply. Keys are treated as fields in a struct and lists are assumed to be atomic. | ||
|
||
CRDs that specify a schema are able to specify additional annotations in the schema. Please refer to the documentation on the full list of available annotations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please refer to the documentation on the full list of available annotations
Is the link to the documentation missing?
This adds the blog post for Server Side Apply moving to GA in 1.22