From 7e0f6f859f21e67ec79a91b4f3544615a4251359 Mon Sep 17 00:00:00 2001 From: Brendan Burns Date: Fri, 10 Apr 2015 16:11:12 -0700 Subject: [PATCH] Suggest a simple rolling update. --- docs/design/simple-rolling-update.md | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/design/simple-rolling-update.md diff --git a/docs/design/simple-rolling-update.md b/docs/design/simple-rolling-update.md new file mode 100644 index 00000000000..43b086ae8a9 --- /dev/null +++ b/docs/design/simple-rolling-update.md @@ -0,0 +1,92 @@ +## Simple rolling update +This is a lightweight design document for simple rolling update in ```kubectl``` + +Complete execution flow can be found [here](#execution-details). + +### Lightweight rollout +Assume that we have a current replication controller named ```foo``` and it is running image ```image:v1``` + +```kubectl rolling-update rc foo [foo-v2] --image=myimage:v2``` + +If the user doesn't specify a name for the 'next' controller, then the 'next' controller is renamed to +the name of the original controller. + +Obviously there is a race here, where if you kill the client between delete foo, and creating the new version of 'foo' you might be surprised about what is there, but I think that's ok. +See [Recovery](#recovery) below + +If the user does specify a name for the 'next' controller, then the 'next' controller is retained with its existing name, +and the old 'foo' controller is deleted. For the purposes of the rollout, we add a unique-ifying label ```kubernetes.io/deployment``` to both the ```foo``` and ```foo-next``` controllers. +The value of that label is the hash of the complete JSON representation of the```foo-next``` or```foo``` controller. The name of this label can be overridden by the user with the ```--deployment-label-key``` flag. + +#### Recovery +If a rollout fails or is terminated in the middle, it is important that the user be able to resume the roll out. +To facilitate recovery in the case of a crash of the updating process itself, we add the following annotations to each replicaController in the ```kubernetes.io/``` annotation namespace: + * ```desired-replicas``` The desired number of replicas for this controller (either N or zero) + * ```update-partner``` A pointer to the replicaiton controller resource that is the other half of this update (syntax `````` the namespace is assumed to be identical to the namespace of this replication controller.) + +Recovery is achieved by issuing the same command again: + +``` +kubectl rolling-update rc foo [foo-v2] --image=myimage:v2 +``` + +Whenever the rolling update command executes, the kubectl client looks for replication controllers called ```foo``` and ```foo-next```, if they exist, an attempt is +made to roll ```foo``` to ```foo-next```. If ```foo-next``` does not exist, then it is created, and the rollout is a new rollout. If ```foo``` doesn't exist, then +it is assumed that the rollout is nearly completed, and ```foo-next``` is renamed to ```foo```. Details of the execution flow are given below. + + +### Aborting a rollout +Abort is assumed to want to reverse a rollout in progress. + +```kubectl rolling-update rc foo [foo-v2] --abort``` + +This is really just semantic sugar for: + +```kubectl rolling-update rc foo-v2 foo``` + +With the added detail that it moves the ```desired-replicas``` annotation from ```foo-v2``` to ```foo``` + + +### Execution Details + +For the purposes of this example, assume that we are rolling from ```foo``` to ```foo-next``` where the only change is an image update from `v1` to `v2` + +If the user doesn't specify a ```foo-next``` name, then it is either discovered from the ```update-partner``` annotation on ```foo```. If that annotation doesn't exist, +then ```foo-next``` is synthesized using the pattern ```-``` + +#### Initialization + * If ```foo``` and ```foo-next``` do not exist: + * Exit, and indicate an error to the user, that the specified controller doesn't exist. + * Goto Rollout + * If ```foo``` exists, but ```foo-next``` does not: + * Create ```foo-next``` populate it with the ```v2``` image, set ```desired-replicas``` to ```foo.Spec.Replicas``` + * Goto Rollout + * If ```foo-next``` exists, but ```foo``` does not: + * Assume that we are in the rename phase. + * Goto Rename + * If both ```foo``` and ```foo-next``` exist: + * Assume that we are in a partial rollout + * If ```foo-next``` is missing the ```desired-replicas``` annotation + * Populate the ```desired-replicas``` annotation to ```foo-next``` using the current size of ```foo``` + * Goto Rollout + +#### Rollout + * While size of ```foo-next``` < ```desired-replicas``` annotation on ```foo-next``` + * increase size of ```foo-next``` + * if size of ```foo``` > 0 + decrease size of ```foo``` + * Goto Rename + +#### Rename + * delete ```foo``` + * create ```foo``` that is identical to ```foo-next``` + * delete ```foo-next``` + +#### Abort + * If ```foo-next``` doesn't exist + * Exit and indicate to the user that they may want to simply do a new rollout with the old version + * If ```foo``` doesn't exist + * Exit and indicate not found to the user + * Otherwise, ```foo-next``` and ```foo``` both exist + * Set ```desired-replicas``` annotation on ```foo``` to match the annotation on ```foo-next``` + * Goto Rollout with ```foo``` and ```foo-next``` trading places.