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

Rolling updates for Fleets #213

Merged
merged 1 commit into from
May 23, 2018

Conversation

markmandel
Copy link
Member

This implements a configurable rolling update strategy for Fleets that also ensures that Allocated GameServers are not interrupted.

Also includes updates to documentation.

Closes #70

@markmandel markmandel added the kind/feature New features for Agones label May 18, 2018
@markmandel markmandel added this to the 0.2 milestone May 18, 2018
// rollingUpdateDeployment will do the rolling update of the old GameServers
// through to the new ones, based on the fleet.Spec.Strategy.RollingUpdate configuration
// and return the replica count for the active GameServerSet
func (c *Controller) rollingUpdateDeployment(fleet *stablev1alpha1.Fleet, active *stablev1alpha1.GameServerSet, rest []*stablev1alpha1.GameServerSet) (int32, error) {
Copy link
Member Author

Choose a reason for hiding this comment

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

@enocom particularly love your eyes on this function, and the functions it calls - it's a bit complicated, so if you can see anything that could improve the code / readability, would definitely be interested.

@agones-bot
Copy link
Collaborator

Build Succeeded 👏

Build Id: afe860aa-044d-48d9-91d6-26c692369fb1

The following development artifacts have been built, and will exist for the next 30 days:

Copy link
Contributor

@enocom enocom left a comment

Choose a reason for hiding this comment

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

There's an opportunity to move error-case checking into if blocks, and happy path code outside of if blocks to have a more idiomatic control flow, i.e., error code is indented, happy path is left most. Otherwise, LGTM.

func (c *Controller) rollingUpdateActive(fleet *stablev1alpha1.Fleet, active *stablev1alpha1.GameServerSet, rest []*stablev1alpha1.GameServerSet) (int32, error) {
replicas := active.Spec.Replicas

if active.Spec.Replicas < fleet.Spec.Replicas && active.Spec.Replicas == active.Status.Replicas {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would invert this boolean expression such that the body becomes return replicas, nil as on line 381 below. That way the control flow of the function handles errors within if statements and happy paths outside. Does that make sense?

unavailable := int32(r)

for _, gsSet := range rest {
if gsSet.Status.Replicas > 0 && gsSet.Status.Replicas == gsSet.Spec.Replicas {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same thing here as above. If you invert the boolean check, your if statement can become much smaller with a continue in the body, and the code outside the if statement can be moved below, which makes understanding the flow easier.

Copy link
Member Author

@markmandel markmandel left a comment

Choose a reason for hiding this comment

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

Excellent suggestions as always. PTAL - I think this is much easier to parse (assuming I got your intentions right)

func (c *Controller) rollingUpdateActive(fleet *stablev1alpha1.Fleet, active *stablev1alpha1.GameServerSet, rest []*stablev1alpha1.GameServerSet) (int32, error) {
replicas := active.Spec.Replicas

// if the active spec replicas are greater than or equal the fleet spec replicas, then we don't
Copy link
Member Author

Choose a reason for hiding this comment

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

@enocom made the inversion here, and also put in some text to help explain the logic. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

Very nice. It takes a bit of getting used to, but the resulting code has a better flow with errors handled to the right.

for _, gsSet := range rest {
// if the status.Replicas are less than or equal to 0, then that means we are done
// scaling this GameServerSet down, and can therefore exit/move to the next one.
if gsSet.Status.Replicas <= 0 {
Copy link
Member Author

Choose a reason for hiding this comment

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

@enocom the inversion here breaks this out into two sections, with slightly different logic - which I think is much easier to read 👍 and parse. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it reads better for sure. And the comments are very helpful.

@agones-bot
Copy link
Collaborator

Build Succeeded 👏

Build Id: 53a0801a-9358-4780-9643-ae87a11ceb48

The following development artifacts have been built, and will exist for the next 30 days:

@enocom enocom requested a review from EricFortin May 22, 2018 15:35
if gsSet.Status.Replicas <= 0 {
continue
}
// If the Status.Replicas does not equal the Status.Replicas for this GameServerSet, this means
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the Spec.Replicas does not equal ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. Done!

This implements a configurable rolling update strategy
for Fleets that also ensures that Allocated GameServers
are not interuppted.

Also includes updates to documentation.

Closes googleforgames#70
@agones-bot
Copy link
Collaborator

Build Failed 😱

Build Id: 37ec19e1-73e1-4aa5-b516-fe707fade650

Build Logs
starting build "37ec19e1-73e1-4aa5-b516-fe707fade650"

FETCHSOURCE
Initialized empty Git repository in /workspace/.git/
From https://source.developers.google.com/p/agones-images/r/agones
 * branch            d40969172add747d7811cc6ec4f557317884ed69 -> FETCH_HEAD
HEAD is now at d409691 Rolling updates for Fleets
BUILD
Starting Step #0
Step #0: Already have image (with digest): ubuntu
Finished Step #0
Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/docker
Step #1: Sending build context to Docker daemon  131.1MB

Step #1: Step 1/3 : FROM gcr.io/cloud-builders/docker
Step #1:  ---> 633138f1b9a2
Step #1: Step 2/3 : RUN apt-get install make
Step #1:  ---> Running in 452cf02cf60b
Step #1: Reading package lists...
Step #1: Building dependency tree...
Step #1: Reading state information...
Step #1: Suggested packages:
Step #1:   make-doc
Step #1: The following NEW packages will be installed:
Step #1:   make
Step #1: 0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
Step #1: Need to get 151 kB of archives.
Step #1: After this operation, 365 kB of additional disk space will be used.
Step #1: Get:1 http://archive.ubuntu.com/ubuntu xenial/main amd64 make amd64 4.1-6 [151 kB]
Step #1: Fetched 151 kB in 0s (264 kB/s)
Step #1: Selecting previously unselected package make.
Step #1: (Reading database ... 
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 11239 files and directories currently installed.)
Step #1: Preparing to unpack .../archives/make_4.1-6_amd64.deb ...
Step #1: Unpacking make (4.1-6) ...
Step #1: Setting up make (4.1-6) ...
Step #1: Removing intermediate container 452cf02cf60b
Step #1:  ---> aba6879f181a
Step #1: Step 3/3 : ENTRYPOINT ["/usr/bin/make"]
Step #1:  ---> Running in 2c6f7e30f607
Step #1: Removing intermediate container 2c6f7e30f607
Step #1:  ---> c87e1be0de6b
Step #1: Successfully built c87e1be0de6b
Step #1: Successfully tagged make-docker:latest
Finished Step #1
Starting Step #2
Step #2: Already have image: make-docker
Step #2: docker pull gcr.io/agones-images/agones-build:e52ce865fb && docker tag gcr.io/agones-images/agones-build:e52ce865fb agones-build:e52ce865fb
Step #2: e52ce865fb: Pulling from agones-images/agones-build
Step #2: c73ab1c6897b: Pulling fs layer
Step #2: 3091fac74ac3: Pulling fs layer
Step #2: 32ec8f15f1df: Pulling fs layer
Step #2: 8a19269d40b4: Pulling fs layer
Step #2: e6425ad9525a: Pulling fs layer
Step #2: 16df2efc4858: Pulling fs layer
Step #2: 2b2d73ab4219: Pulling fs layer
Step #2: 5f2d382df949: Pulling fs layer
Step #2: 5b739d0afd39: Pulling fs layer
Step #2: eb921739ae12: Pulling fs layer
Step #2: 2022ec0c796a: Pulling fs layer
Step #2: 3ee570d976e5: Pulling fs layer
Step #2: 59f7198d9c1c: Pulling fs layer
Step #2: 08501ff593d9: Pulling fs layer
Step #2: a5d32e6825a2: Pulling fs layer
Step #2: 42602390dd8d: Pulling fs layer
Step #2: 8a19269d40b4: Waiting
Step #2: e6425ad9525a: Waiting
Step #2: 16df2efc4858: Waiting
Step #2: 2b2d73ab4219: Waiting
Step #2: 5f2d382df949: Waiting
Step #2: 5b739d0afd39: Waiting
Step #2: eb921739ae12: Waiting
Step #2: 2022ec0c796a: Waiting
Step #2: 3ee570d976e5: Waiting
Step #2: 59f7198d9c1c: Waiting
Step #2: 08501ff593d9: Waiting
Step #2: a5d32e6825a2: Waiting
Step #2: 42602390dd8d: Waiting
Step #2: c73ab1c6897b: Verifying Checksum
Step #2: c73ab1c6897b: Download complete
Step #2: 8a19269d40b4: Verifying Checksum
Step #2: 8a19269d40b4: Download complete
Step #2: c73ab1c6897b: Pull complete
Step #2: e6425ad9525a: Verifying Checksum
Step #2: e6425ad9525a: Download complete
Step #2: 3091fac74ac3: Verifying Checksum
Step #2: 3091fac74ac3: Download complete
Step #2: 16df2efc4858: Verifying Checksum
Step #2: 16df2efc4858: Download complete
Step #2: 5f2d382df949: Verifying Checksum
Step #2: 5f2d382df949: Download complete
Step #2: 2b2d73ab4219: Verifying Checksum
Step #2: 2b2d73ab4219: Download complete
Step #2: eb921739ae12: Verifying Checksum
Step #2: eb921739ae12: Download complete
Step #2: 5b739d0afd39: Verifying Checksum
Step #2: 5b739d0afd39: Download complete
Step #2: 3ee570d976e5: Verifying Checksum
Step #2: 3ee570d976e5: Download complete
Step #2: 59f7198d9c1c: Verifying Checksum
Step #2: 59f7198d9c1c: Download complete
Step #2: 08501ff593d9: Verifying Checksum
Step #2: 08501ff593d9: Download complete
Step #2: 3091fac74ac3: Pull complete
Step #2: a5d32e6825a2: Verifying Checksum
Step #2: a5d32e6825a2: Download complete
Step #2: 2022ec0c796a: Verifying Checksum
Step #2: 2022ec0c796a: Download complete
Step #2: 42602390dd8d: Verifying Checksum
Step #2: 42602390dd8d: Download complete
Step #2: 32ec8f15f1df: Verifying Checksum
Step #2: 32ec8f15f1df: Download complete
Step #2: 32ec8f15f1df: Pull complete
Step #2: 8a19269d40b4: Pull complete
Step #2: e6425ad9525a: Pull complete
Step #2: 16df2efc4858: Pull complete
Step #2: 2b2d73ab4219: Pull complete
Step #2: 5f2d382df949: Pull complete
Step #2: 5b739d0afd39: Pull complete
Step #2: eb921739ae12: Pull complete
Step #2: 2022ec0c796a: Pull complete
Step #2: 3ee570d976e5: Pull complete
Step #2: 59f7198d9c1c: Pull complete
Step #2: 08501ff593d9: Pull complete
Step #2: a5d32e6825a2: Pull complete
Step #2: 42602390dd8d: Pull complete
Step #2: Digest: sha256:0344289d4121c2024d5b7d8790a8f3a5043b2149c0632928a2d4d9d0b8473f24
Step #2: Status: Downloaded newer image for gcr.io/agones-images/agones-build:e52ce865fb
Finished Step #2
Starting Step #3
Step #3: Already have image: make-docker
Step #3: mkdir -p ~/.kube
Step #3: mkdir -p /workspace/build//.config/gcloud
Step #3: docker run --rm -v /workspace/build//.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v /workspace:/go/src/agones.dev/agones -w /go/src/agones.dev/agones  agones-build:e52ce865fb bash -c \
Step #3: 	"/root/gen-lint-exclude.sh && gometalinter --config .exclude.gometalinter.json --deadline 100s -t --skip vendor ./..."
Step #3: WARNING: deadline exceeded by linter megacheck (try increasing --deadline)
Step #3: WARNING: deadline exceeded by linter gas (try increasing --deadline)
Step #3: make: *** [lint] Error 2
Step #3: Makefile:136: recipe for target 'lint' failed
Finished Step #3
ERROR
ERROR: build step 3 "make-docker" failed: exit status 2

@agones-bot
Copy link
Collaborator

Build Succeeded 👏

Build Id: a9267b94-3a73-4d49-9642-169ba958de16

The following development artifacts have been built, and will exist for the next 30 days:

Copy link
Collaborator

@EricFortin EricFortin left a comment

Choose a reason for hiding this comment

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

It took me some time but LGTM!

@enocom enocom merged commit 20a7af5 into googleforgames:master May 23, 2018
@markmandel markmandel deleted the feature/fleet-rolling branch May 23, 2018 23:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature New features for Agones
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants