Permalink
Browse files

GameServerAllocation implementation

This implements the `GameServerAllocation` as designed in #436,
which decouples Allocation from Fleets, and provides much more flexible
functionality.

This also moves FleetAllocation to deprecated, and includes notes that it will
be removed in +2 releases.

Closes #436
  • Loading branch information...
markmandel committed Dec 6, 2018
1 parent 6f64c0f commit 37635982c2699fac76bc5528db7d71797e37b44f
Showing with 6,308 additions and 316 deletions.
  1. +9 −0 Gopkg.lock
  2. +5 −1 Gopkg.toml
  3. +4 −1 cmd/controller/main.go
  4. +119 −10 docs/create_fleet.md
  5. +73 −8 docs/fleet_spec.md
  6. +2 −2 examples/fleet.yaml
  7. +2 −0 examples/fleetallocation.yaml
  8. +61 −0 examples/gameserverallocation.yaml
  9. +0 −3 examples/simple-udp/fleet.yaml
  10. +1 −2 examples/simple-udp/fleetallocation.yaml
  11. +32 −0 examples/simple-udp/gameserverallocation.yaml
  12. +1 −2 examples/xonotic/fleetallocation.yaml
  13. +32 −0 examples/xonotic/gameserverallocation.yaml
  14. +1 −0 install/helm/agones/scripts/delete_agones_resources.sh
  15. +2 −0 install/helm/agones/templates/admissionregistration.yaml
  16. +36 −0 install/helm/agones/templates/crds/_selector.yaml
  17. +79 −0 install/helm/agones/templates/crds/gameserverallocation.yaml
  18. +1 −1 install/helm/agones/templates/hooks/sa.yaml
  19. +7 −0 install/helm/agones/templates/serviceaccounts/controller.yaml
  20. +127 −0 install/yaml/install.yaml
  21. +5 −4 pkg/apis/stable/v1alpha1/fleetallocation.go
  22. +53 −26 pkg/apis/stable/v1alpha1/gameserver.go
  23. +19 −6 pkg/apis/stable/v1alpha1/gameserver_test.go
  24. +120 −0 pkg/apis/stable/v1alpha1/gameserverallocation.go
  25. +77 −0 pkg/apis/stable/v1alpha1/gameserverallocation_test.go
  26. +2 −0 pkg/apis/stable/v1alpha1/register.go
  27. +138 −30 pkg/apis/stable/v1alpha1/zz_generated.deepcopy.go
  28. +140 −0 pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_gameserverallocation.go
  29. +4 −0 pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_stable_client.go
  30. +174 −0 pkg/client/clientset/versioned/typed/stable/v1alpha1/gameserverallocation.go
  31. +2 −0 pkg/client/clientset/versioned/typed/stable/v1alpha1/generated_expansion.go
  32. +5 −0 pkg/client/clientset/versioned/typed/stable/v1alpha1/stable_client.go
  33. +2 −0 pkg/client/informers/externalversions/generic.go
  34. +89 −0 pkg/client/informers/externalversions/stable/v1alpha1/gameserverallocation.go
  35. +7 −0 pkg/client/informers/externalversions/stable/v1alpha1/interface.go
  36. +8 −0 pkg/client/listers/stable/v1alpha1/expansion_generated.go
  37. +94 −0 pkg/client/listers/stable/v1alpha1/gameserverallocation.go
  38. +4 −3 pkg/fleetallocation/controller.go
  39. +6 −6 pkg/fleetallocation/controller_test.go
  40. +4 −3 pkg/fleetallocation/find.go
  41. +39 −39 pkg/fleetallocation/find_test.go
  42. +196 −0 pkg/gameserverallocations/allocationcounter.go
  43. +192 −0 pkg/gameserverallocations/allocationcounter_test.go
  44. +394 −0 pkg/gameserverallocations/controller.go
  45. +771 −0 pkg/gameserverallocations/controller_test.go
  46. +17 −0 pkg/gameserverallocations/doc.go
  47. +33 −0 pkg/gameserverallocations/find.go
  48. +21 −0 pkg/gameserverallocations/helper_test.go
  49. +14 −14 pkg/gameservers/controller.go
  50. +32 −32 pkg/gameservers/controller_test.go
  51. +4 −4 pkg/gameservers/health.go
  52. +12 −12 pkg/gameservers/health_test.go
  53. +14 −14 pkg/gameservers/portallocator_test.go
  54. +9 −7 pkg/gameserversets/controller.go
  55. +20 −20 pkg/gameserversets/controller_test.go
  56. +2 −2 pkg/gameserversets/gameserversets.go
  57. +7 −7 pkg/gameserversets/gameserversets_test.go
  58. +16 −16 pkg/metrics/controller_test.go
  59. +2 −2 pkg/metrics/gameservers.go
  60. +4 −4 pkg/metrics/util_test.go
  61. +9 −9 pkg/sdkserver/sdkserver.go
  62. +12 −12 pkg/sdkserver/sdkserver_test.go
  63. +186 −6 test/e2e/fleet_test.go
  64. +2 −2 test/e2e/fleetautoscaler_test.go
  65. +7 −2 test/e2e/framework/framework.go
  66. +4 −4 test/e2e/gameserver_test.go
  67. +259 −0 test/e2e/gameserveralloction_test.go
  68. +25 −0 vendor/github.com/evanphx/json-patch/LICENSE
  69. +292 −0 vendor/github.com/evanphx/json-patch/README.md
  70. +39 −0 vendor/github.com/evanphx/json-patch/cmd/json-patch/file_flag.go
  71. +56 −0 vendor/github.com/evanphx/json-patch/cmd/json-patch/main.go
  72. +383 −0 vendor/github.com/evanphx/json-patch/merge.go
  73. +585 −0 vendor/github.com/evanphx/json-patch/merge_test.go
  74. +682 −0 vendor/github.com/evanphx/json-patch/patch.go
  75. +421 −0 vendor/github.com/evanphx/json-patch/patch_test.go

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -83,11 +83,15 @@
[[constraint]]
branch = "master"
name = "github.com/joonix/log"

[[constraint]]
name = "go.opencensus.io"
version = "0.18.0"

[[override]]
name = "github.com/prometheus/client_golang"
version = "0.9.2"

[[constraint]]
name = "github.com/evanphx/json-patch"
version = "4.1.0"
@@ -30,6 +30,7 @@ import (
"agones.dev/agones/pkg/fleetallocation"
"agones.dev/agones/pkg/fleetautoscalers"
"agones.dev/agones/pkg/fleets"
"agones.dev/agones/pkg/gameserverallocations"
"agones.dev/agones/pkg/gameservers"
"agones.dev/agones/pkg/gameserversets"
"agones.dev/agones/pkg/metrics"
@@ -133,11 +134,13 @@ func main() {
fleetController := fleets.NewController(wh, health, kubeClient, extClient, agonesClient, agonesInformerFactory)
faController := fleetallocation.NewController(wh, allocationMutex,
kubeClient, extClient, agonesClient, agonesInformerFactory)
gasController := gameserverallocations.NewController(wh, health, allocationMutex, kubeClient,
kubeInformationFactory, extClient, agonesClient, agonesInformerFactory)
fasController := fleetautoscalers.NewController(wh, health,
kubeClient, extClient, agonesClient, agonesInformerFactory)

rs := []runner{
wh, gsController, gsSetController, fleetController, faController, fasController, metricsController, server,
wh, gsController, gsSetController, fleetController, faController, fasController, metricsController, gasController, server,
}

stop := signals.NewStopChannel()
@@ -3,6 +3,23 @@
This guide covers how you can quickly get started using Agones to create a Fleet
of warm GameServers ready for you to allocate out of and play on!


Table of Contents
=================

* [Prerequisites](#prerequisites)
* [Objectives](#objectives)
* [1. Create a Fleet](#1-create-a-fleet)
* [2. Fetch the Fleet status](#2-fetch-the-fleet-status)
* [3. Scale up the Fleet](#3-scale-up-the-fleet)
* [4. Allocate a Game Server from the Fleet](#4-allocate-a-game-server-from-the-fleet)
* [GameServerAllocation](#gameserverallocation)
* [FleetAllocation](#fleetallocation)
* [5. Scale down the Fleet](#5-scale-down-the-fleet)
* [6. Connect to the GameServer](#6-connect-to-the-gameserver)
* [7. Deploy a new version of the GameServer on the Fleet](#7-deploy-a-new-version-of-the-gameserver-on-the-fleet)
* [Next Steps](#next-steps)

## Prerequisites

The following prerequisites are required to create a GameServer:
@@ -146,14 +163,106 @@ simple-udp-xvp4n-i6bnm 36s

### 4. Allocate a Game Server from the Fleet

Since we have a fleet of warm gameservers, we need a way to request one of them for usage!

We can do this through a `FleetAllocation`, which will both return to us a `GameServer` (assuming one is available)
and also move it to the `Allocated` state.
Since we have a fleet of warm gameservers, we need a way to request one of them for usage, and mark that it has
players access it (and therefore, it should not be deleted until they are finished with it).

In production, you would likely do this through a [Kubernetes API call](./access_api.md), but we can also
> In production, you would likely do the following through a [Kubernetes API call](./access_api.md), but we can also
do this through `kubectl` as well, and ask it to return the response in yaml so that we can see what has happened.
#### GameServerAllocation

⚠️⚠️⚠️ **This is currently a development feature and has not been released** ⚠️⚠️⚠️

We can do allocation of a GameServer for usage through a `GameServerAllocation`, which will both
return to us the details of a `GameServer` (assuming one is available), and also move it to the `Allocated` state,
which demarcates that it has players on it, and should not be removed until `SDK.Shutdown()` is called, or it is manually deleted.

It is worth noting that there is nothing specific that ties a `GameServerAllocation`. A `GameServerAllocation` uses
a [lable selector](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) to determine what
group of `GameServers` it will attempt to allocate out of. That being said, a `Fleet` and `GameServerAllocation`
are often used in conjunction.

[This example](../examples/simple-udp/gameserverallocation.yaml) uses the label selector to specifically target the `simple-udp` fleet that we just created.

```
kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/agones/master/examples/simple-udp/gameserverallocation.yaml -o yaml
```

For the full details of the YAML file head to the [Fleet Specification Guide](./fleet_spec.md#gameserver-allocation-specification)

You should get back a response that looks like the following:

```yaml
apiVersion: stable.agones.dev/v1alpha1
kind: GameServerAllocation
metadata:
creationTimestamp: 2018-12-31T22:52:41Z
generateName: simple-udp-
generation: 1
name: simple-udp-czw2b
namespace: default
ownerReferences:
- apiVersion: stable.agones.dev/v1alpha1
blockOwnerDeletion: true
controller: true
kind: GameServer
name: simple-udp-sdhzn-r4d6x
uid: b0ad460b-0d4e-11e9-9986-dcbf85d40d0b
resourceVersion: "4085"
selfLink: /apis/stable.agones.dev/v1alpha1/namespaces/default/gameserverallocations/simple-udp-czw2b
uid: c7547505-0d4e-11e9-9986-dcbf85d40d0b
spec:
metadata: {}
required:
matchLabels:
stable.agones.dev/fleet: simple-udp
scheduling: Packed
status:
address: 192.168.122.205
gameServerName: simple-udp-sdhzn-r4d6x
nodeName: minikube
ports:
- name: default
port: 7623
state: Allocated
```

If you look at the `status` section, there are several things to take note of. The `state` value will tell if
a `GameServer` was allocated or not. If a `GameServer` could not be found, this will be set to `UnAllocated`.

However, we see that the `status.state` value was set to `Allocated`.
This means you have been successfully allocated a `GameServer` out of the fleet, and you can now connect your players to it!

You can see various immutable details of the `GameServer` in the status - the `address`, `ports` and the name
of the `GameServer`, in case you want to use it to retrieve more details.

We can also check to see how many `GameServers` you have `Allocated` vs `Ready` with the following command
("gs" is shorthand for "gameserver").

```
kubectl get gs
```

This will get you a list of all the current `GameSevers` and their `Status.State`.

```
NAME STATE ADDRESS PORT NODE AGE
simple-udp-sdhzn-kcmh6 Ready 192.168.122.205 7191 minikube 52m
simple-udp-sdhzn-pdpk5 Ready 192.168.122.205 7752 minikube 53m
simple-udp-sdhzn-r4d6x Allocated 192.168.122.205 7623 minikube 52m
simple-udp-sdhzn-wng5k Ready 192.168.122.205 7709 minikube 53m
simple-udp-sdhzn-wnhsw Ready 192.168.122.205 7478 minikube 52m
```

#### FleetAllocation

> Fleet Allocation is **deprecated** in version 0.8.0, and will be removed in the 0.10.0 release.
Migrate to using GameServer Allocation instead.

We can do allocation of a GameServer for usage through a `FleetAllocation`, which will both return to us a `GameServer` (assuming one is available)
and also move it to the `Allocated` state.

```
kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/agones/master/examples/simple-udp/fleetallocation.yaml -o yaml
```
@@ -356,9 +465,9 @@ You have now deployed a new version of your game!

## Next Steps

You can now create a fleet autoscaler to automatically resize your fleet based on the actual usage.
- Have a look at the [GameServerAllocation specification](./fleet_spec.md#gameserver-allocation-specification), and see
how the extra functionality can enable smoke testing, server information communication, and more.
- You can now create a fleet autoscaler to automatically resize your fleet based on the actual usage.
See [Create a Fleet Autoscaler](./create_fleetautoscaler.md).

Or if you want to try to use your own GameServer container make sure you have properly integrated the [Agones SDK](../sdks/).

If you would like to learn how to programmatically allocate a Game Server from the fleet using the Agones API, see the [Allocator Service](./create_allocator_service.md) tutorial.
- Or if you want to try to use your own GameServer container make sure you have properly integrated the [Agones SDK](../sdks/).
- If you would like to learn how to programmatically allocate a Game Server from the fleet using the Agones API, see the [Allocator Service](./create_allocator_service.md) tutorial.
@@ -54,8 +54,8 @@ This is a very common pattern in the Kubernetes ecosystem.
The `spec` field is the actual `Fleet` specification and it is composed as follow:

- `replicas` is the number of `GameServers` to keep Ready or Allocated in this Fleet
- `scheduling` defines how GameServers are organised across the cluster. Currently only affects Allocation, but will expand
in future releases. Options include:
- `scheduling` defines how GameServers are organised across the cluster. Affects backing Pod scheduling, as well as scale
down mechanics.
"Packed" (default) is aimed at dynamic Kubernetes clusters, such as cloud providers, wherein we want to bin pack
resources. "Distributed" is aimed at static Kubernetes clusters, wherein we want to distribute resources across the entire
cluster. See [Scheduling and Autoscaling](scheduling_autoscaling.md) for more details.
@@ -69,24 +69,89 @@ The `spec` field is the actual `Fleet` specification and it is composed as follo
- `template` a full `GameServer` configuration template.
See the [GameServer](./gameserver_spec.md) reference for all available fields.

# GameServer Allocation Specification

⚠️⚠️⚠️ **This is currently a development feature and has not been released** ⚠️⚠️⚠️

A `GameServerAllocation` is used to atomically allocate a GameServer out of a set of GameServers.
This could be a single Fleet, multiple Fleets, or a self managed group of GameServers.

A full `GameServerAllocation` specification is available below and in the
[example folder](../examples/gameserverallocation.yaml) for reference:


```yaml
apiVersion: "stable.agones.dev/v1alpha1"
kind: GameServerAllocation
metadata:
generateName: simple-udp-
spec:
required:
matchLabels:
game: my-game
matchExpressions:
- {key: tier, operator: In, values: [cache]}
# ordered list of preferred allocations
# This also support `matchExpressions`
preferred:
- matchLabels:
stable.agones.dev/fleet: green-fleet
- matchLabels:
stable.agones.dev/fleet: blue-fleet
# defines how GameServers are organised across the cluster.
# Options include:
# "Packed" (default) is aimed at dynamic Kubernetes clusters, such as cloud providers, wherein we want to bin pack
# resources
# "Distributed" is aimed at static Kubernetes clusters, wherein we want to distribute resources across the entire
# cluster
scheduling: Packed
# Optional custom metadata that is added to the game server at allocation
# You can use this to tell the server necessary session data
metadata:
labels:
mode: deathmatch
annotations:
map: garden22
```

We recommend using `metadata > generateName`, to declare to Kubernetes that a unique
name for the `GameServerAllocation` is generated when the `GameServerAllocation` is created.

The `spec` field is the actual `GameServerAllocation` specification and it is composed as follow:

- `required` is a [label selector](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
(matchLabels and/or matchExpressions) from which to choose GameServers from.
GameServers still have the hard requirement to be `Ready` to be allocated from
- `preferred` is an order list of [label selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
out of the `required` set.
If the first selector is not matched, the selection attempts the second selector, and so on.
This is useful for things like smoke testing of new game servers.
- `scheduling` defines how GameServers are organised across the cluster, in this case specifically when allocating
`GameServers` for usage.
"Packed" (default) is aimed at dynamic Kubernetes clusters, such as cloud providers, wherein we want to bin pack
resources. "Distributed" is aimed at static Kubernetes clusters, wherein we want to distribute resources across the entire
cluster. See [Scheduling and Autoscaling](scheduling_autoscaling.md) for more details.

- `metadata` is an optional list of custom labels and/or annotations that will be used to patch
the game server's metadata in the moment of allocation. This can be used to tell the server necessary session data

# Fleet Allocation Specification

> Fleet Allocation is **deprecated** in version 0.8.0, and will be removed in the 0.10.0 release.
Migrate to using GameServer Allocation instead.
A `FleetAllocation` is used to allocate a `GameServer` out of an existing `Fleet`

A full `FleetAllocation` specification is available below and in the
[example folder](../examples/fleetallocation.yaml) for reference :
[example folder](../examples/fleetallocation.yaml) for reference:

```yaml
apiVersion: "stable.agones.dev/v1alpha1"
kind: FleetAllocation
metadata:
generateName: fleet-allocation-example-
spec:
# The name of the fleet to allocate from. Must be an existing Fleet in the same namespace
# as this FleetAllocation
fleetName: fleet-example
# Custom metadata that is added to game server status in the moment of allocation
# You can use this to tell the server necessary session data
metadata:
labels:
mode: deathmatch
@@ -102,4 +167,4 @@ The `spec` field is the actual `FleetAllocation` specification and it is compose
- `fleetName` is the name of an existing Fleet. If this doesn't exist, an error will be returned
when the `FleetAllocation` is created
- `metadata` is an optional list of custom labels and/or annotations that will be used to patch
the game server's metadata in the moment of allocation.
the game server's metadata in the moment of allocation. This can be used to tell the server necessary session data
@@ -27,8 +27,8 @@ metadata:
spec:
# the number of GameServers to keep Ready or Allocated in this Fleet
replicas: 2
# defines how GameServers are organised across the cluster. Currently only affects Allocation, but will expand
# in future releases. Options include:
# defines how GameServers are organised across the cluster.
# Options include:
# "Packed" (default) is aimed at dynamic Kubernetes clusters, such as cloud providers, wherein we want to bin pack
# resources
# "Distributed" is aimed at static Kubernetes clusters, wherein we want to distribute resources across the entire
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

#
# (Deprecated: See GameServerAllocation for a replacement)
#
# Full example of a FleetAllocation - this is used to allocate a GameServer
# out of a Fleet so it can be handed to a set of players to play on.
Oops, something went wrong.

0 comments on commit 3763598

Please sign in to comment.