-
Notifications
You must be signed in to change notification settings - Fork 39.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
Support absence of source RC in RollingUpdater #7183
Support absence of source RC in RollingUpdater #7183
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project, in which case you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
@bgrant0607 @smarterclayton thoughts? |
If you haven't already seen it, take a look at: cc @brendandburns, who's also working on RCs |
oldRc.Spec.Replicas -= 1 | ||
} | ||
|
||
fmt.Printf("At beginning of loop: %s\n", rollingLabelFor(newRc, oldRc)) |
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.
FWIW, there should be a way to turn off this output, for this and all other kubectl operations.
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.
On Apr 23, 2015, at 6:32 PM, Brian Grant notifications@github.com wrote:
In pkg/kubectl/rolling_updater.go:
newRc.Spec.Replicas += 1
oldRc.Spec.Replicas -= 1
fmt.Printf("At beginning of loop: %s replicas: %d, %s replicas: %d\n",
oldName, oldRc.Spec.Replicas,
newName, newRc.Spec.Replicas)
fmt.Fprintf(out, "Updating %s replicas: %d, %s replicas: %d\n",
oldName, oldRc.Spec.Replicas,
newName, newRc.Spec.Replicas)
if oldRc != nil {
oldRc.Spec.Replicas -= 1
}
FWIW, there should be a way to turn off this output, for this and all other kubectl operations.fmt.Printf("At beginning of loop: %s\n", rollingLabelFor(newRc, oldRc))
Make RollingUpdater have an io.Writer member and write with Fprint
—
Reply to this email directly or view it on GitHub.
Is there any reason to add replicas gradually when there was no original RC? I'm aware of a few such cases internally, but it's not very common. It would decrease the modality of the code if that case just short-circuited by calling create. That said, this is not unreasonable, IMO. |
That's not unreasonable. I can think of a few cases as well (thundering herd style rollouts hammering a db) but it just seems unlikely.
|
Clayton and I had the same discussion the other day. Sounds like we all agree that we can just immediately scale up when there's no old RC for a transition. The code would definitely be less modal, which is a bonus. Thanks for the feedback! |
764e573
to
37f5e9e
Compare
Refactored based on yesterday's discussion. I've been taking a look at the simple rolling update doc and what I have here now doesn't quite fit the contract outlined by @brendanburns. For example, the document describes a "Rename" behavior for when there's no source RC, which is not represented in master or my branch. I take it the document is a plan for future work? |
I cc'd you on the pull that does that
|
37f5e9e
to
b5bbecd
Compare
I'll rebase this when #7279 lands. |
Just pointing out that I don't think there will be a way to express this scenario via the kubectl command line. I'm fine with that. In general, I'd like kubectl to be better factored for use as a library. |
b5bbecd
to
d4fc660
Compare
Rebased. |
Assigning to @brendandburns, since he's active in this part of the code at the moment. |
@brendanburns Any thoughts on this? |
Or @jlowdermilk, since he reviewed the other PRs. |
I don't quite understand the reason for using rolling-update if there's no existing rc... Why not just use |
@jlowdermilk It's to simplify a client layered on top, which mostly will be doing updates, except the first time, where it needs to create the RC. This may be useful for us, as well, for implementing Deployment (#1743). See discussion in #6996. |
@jlowdermilk @bgrant0607 Did you both reach consensus on this? |
@@ -138,11 +149,32 @@ func (r *RollingUpdater) Update(config *RollingUpdaterConfig) error { | |||
} | |||
} | |||
|
|||
if oldRc == nil { | |||
// There's no source RC, so just scale up the new immediately and return |
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 block is identical to the final resize step for the general case (line 208). Should make it a function to avoid code duplication.
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.
Extracted a function.
d4fc660
to
70e1f81
Compare
When performing a rolling update, scale up the new RC immediately in the absence of a source RC. This is to handle initial deployments and any other case where the source RC either never existed or was otherwise removed from the system. With no source RC, there's no reason to do a gradual transition.
70e1f81
to
2d68c1c
Compare
return rc, true, fmt.Errorf("Missing %s annotation for controller %s", DesiredReplicasAnnotation, name) | ||
} | ||
|
||
// If there's no source associated with the RC, don't validate association. |
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.
Hmmm. this logic needs tweaking; if the newRc has a sourceIdAnnotation but we didn't provide a sourceId, we should probably return an error, as that means we detected a partial rollout from an existing oldRc that the user (perhaps accidentally) didn't specify. I think the cases should be
- no sourceId provided, but newRc has sourceIdAnnotation: return error - partial rollout from oldName detected, but no starting rc specified.
- sourceId provided, but newRc doesn't have sourceIdAnnotation, or annotation doesn't match: return error - missing/unexpected annotation
- sourceId provided and matches newRc annotation: success, return rc
- sourceId not provided, and newRc has no annotation: success, return rc.
@jlowdermilk I'm starting to wonder whether it's really a big deal for consumers to just use a straight up resize for initial deployments and only use the rolling updater when there are two RC's to transition. You alluded to this previously. The modal complexity is starting to add up, especially since the rename stuff landed. What do you think? |
@ironcladlou, I think using resize for initial deployments makes the most sense from an end user perspective. IMO we should be optimizing the client for end users not layered clients. |
@bgrant0607 @smarterclayton Thoughts? The way this is headed, I'm prepared to retract this request and use a combination of resize and rolling updates to handle initial/subsequent rollouts. |
My overriding concern is having a simple, easy to use command that can do the "go from X to Y". Because the reality of the world intrudes, X may sometimes get deleted, or renamed, or disappear. If we want to make it easy to rely on rolling-update for the core of a true deployment object, and also be able to script and customize your deployment logic (using bash + rolling-update or Go plus the library), we should ensure that we don't end up with two completely different implementations of rolling updater - one we maintain, and the cobbled together nightmare in bash an end user who needs "small tweak X" has to maintain. If it's easy in bash to script "resize if it doesn't exist, tweak replicas slowly over time if it does", I think we're ok. If it requires deep knowledge of bash and the surface areas of our commands, I think we're not. /soapbox
|
Sorry, I've been OOO. I'll take a look by/on Monday. I agree that the TOOL should be targeted at end users, including use in scripts. However, the LIBRARY should support layered/embedded uses, only one of which is the tool. That said, we want the library to be flexible, but not overly complicated. One could imagine layering rolling update on top of resize, but resize is simple enough that it's probably not worth it. |
We also need to keep an eye on #7575. It's probably worth sketching out the matrix of scenarios we expect to support. |
#7575 was merged. |
The other rolling update PRs in flight have landed. This looks reasonably clean and self-contained. Please rebase, resolve comments, and get it merged. |
Is this PR still relevant? |
I think this particular implementation of the concept has fallen too far behind other refactors to remain useful without a lot of rework, and I'm presently focused on other aspects of rolling updates. If we agree the concept is still relevant/desired, does it make sense to "downgrade" the PR to an issue so that a later PR could address it? In any case, this PR is going to languish and should probably be closed for now. |
Closing as out of date. @ironcladlou, please open an issue for this feature so we can triage and get to it later. |
This is some POC work to show what's involved in changing RollingUpdater to support the absence of an "old" ReplicationController. These changes would also allow OpenShift to make use of RollingUpdater by pre-processing our RCs to include the annotations RollingUpdater expects.
I'm not crazy about having to set annotations, but I'd rather do that downstream than change the fundamental operating principals of this code. I'm also not entirely pleased with how this refactored code reads (feels modal), but at least there's something to talk about.
cc @smarterclayton @bgrant0607