Skip to content
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

[controller] Add logic to update StatefulSets #236

Merged
merged 7 commits into from
Sep 29, 2020

Conversation

jeromefroe
Copy link
Collaborator

This commit to the controller adds support for updating StatefulSet's when their image or config map are out of date with the ClusterSpec. After checking that the cluster is healthy, the controller will next check if any StatefulSet needs to be updated, and will then perform any needed updates one by one. To ensure that the controller will only perform updates when it is safe to do so, the controller will check for an annotation that must be set by a user to indicate the controller can perform an update.

@codecov
Copy link

codecov bot commented Sep 25, 2020

Codecov Report

Merging #236 into master will increase coverage by 0.61%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #236      +/-   ##
==========================================
+ Coverage   75.59%   76.20%   +0.61%     
==========================================
  Files          30       30              
  Lines        2118     2152      +34     
==========================================
+ Hits         1601     1640      +39     
+ Misses        392      379      -13     
- Partials      125      133       +8     

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update acaa0f1...03df9e9. Read the comment docs.

// ConfigMapName fields in the ClusterSpec don't match what's in the StatefulSet then
// this function will update the provided StatefulSet to match the desired state and
// return true.
func shouldUpdateStatefulSet(spec myspec.ClusterSpec, sts *appsv1.StatefulSet) (bool, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image and config updates are definitely the most common case we want to cover, so from that perspective this looks good. There are definitely other cases where the cluster CRD changes and we want to update the statefulsets, and I'm wondering how to address that here. Two thoughts:

  1. Any idea what happens if we try to DeepEqual the generated spec and the current spec on the cluster? I'm guessing the Kubernetes API makes some sort of transformations that make that not totally possible, but I'm curious.

  2. Assuming DeepEqual doesn't work, what do you think about a second annotation that will trigger an Update regardless of whether image and config has changed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've always had difficulties using DeepEqual in the past because the API server sets default (non-zero) values for so many fields. Based on this kubebuilder issue though, it seems that we could use DeepDerivative instead since it "is similar to DeepEqual except that unset fields in a1 are ignored ". That issue also mentions github.com/banzaicloud/k8s-objectmatcher as another alternative if DeepDerivative doesn't work for us. If neither package is sufficient though I'm not opposed to having a force-update annotation or something similar which will always trigger an update.

Copy link
Collaborator

@schallert schallert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🔥 (w/ 1 comment).

Can do this in another PR if you want but would love to have something in docs on using this.

// expected state. The method returns the updated StatefulSet if so, otherwise nil.
func updatedStatefulSet(
actual *appsv1.StatefulSet, cluster *myspec.M3DBCluster, isoGroup myspec.IsolationGroup,
) (*appsv1.StatefulSet, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we modify the return signature to be *StatefulSet, bool, error and use the bool as whether we upgraded rather than implicit nil?

@jeromefroe
Copy link
Collaborator Author

Can do this in another PR if you want but would love to have something in docs on using this.

Definitely! I tested the changes on a running cluster yesterday using a local build, but want to deploy the changes and do some more thorough testing today. So I'll update the docs after that once I've gotten a better handle on the UX.

@jeromefroe jeromefroe merged commit b25f1c7 into master Sep 29, 2020
@jeromefroe jeromefroe deleted the jerome/controller/update-statefulsets branch September 29, 2020 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants