From ff21574cacea5c2df7969c6824a04aa7a9d3de0b Mon Sep 17 00:00:00 2001
From: Mark Mandel
Date: Tue, 19 May 2020 10:42:59 -0700
Subject: [PATCH] Player Tracking guide, and GameServer reference. (#1569)
Includes the guide for player tracking, explaining how the SDK commands
can be used for player user journeys.
Included is also updates to the GameServer references.
Also included a small fix in the comments wherein we were still
referencing the webhook from the previous design.
Work on #1033
---
examples/gameserver.yaml | 7 +
pkg/apis/agones/v1/gameserver.go | 3 +-
site/content/en/docs/Guides/feature-stages.md | 11 ++
.../content/en/docs/Guides/player-tracking.md | 126 ++++++++++++++++++
.../Reference/agones_crd_api_reference.html | 3 +-
site/content/en/docs/Reference/gameserver.md | 107 +++++++++++++++
6 files changed, 253 insertions(+), 4 deletions(-)
create mode 100644 site/content/en/docs/Guides/player-tracking.md
diff --git a/examples/gameserver.yaml b/examples/gameserver.yaml
index 26595c2324..8a90fa1eb7 100644
--- a/examples/gameserver.yaml
+++ b/examples/gameserver.yaml
@@ -76,6 +76,13 @@ spec:
# conflict with other TCP connections.
grpcPort: 9357
httpPort: 9358
+ # [Stage:Alpha]
+ # [FeatureFlag:PlayerTracking]
+ # Players provides the configuration for player tracking features.
+ # Commented out since Alpha, and disabled by default
+ # players:
+ # # set this GameServer's initial player capacity
+ # initialCapacity: 10
# Pod template configuration
# https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#podtemplate-v1-core
template:
diff --git a/pkg/apis/agones/v1/gameserver.go b/pkg/apis/agones/v1/gameserver.go
index 8cfb5a96d1..af70e1282a 100644
--- a/pkg/apis/agones/v1/gameserver.go
+++ b/pkg/apis/agones/v1/gameserver.go
@@ -156,8 +156,7 @@ type GameServerSpec struct {
Players *PlayersSpec `json:"players,omitempty"`
}
-// PlayersSpec tracks the initial player capacity, and what webhooks to send events to when there are
-// connection/disconnection events.
+// PlayersSpec tracks the initial player capacity
type PlayersSpec struct {
InitialCapacity int64 `json:"initialCapacity,omitempty"`
}
diff --git a/site/content/en/docs/Guides/feature-stages.md b/site/content/en/docs/Guides/feature-stages.md
index 539a2f7124..0cb0aa9188 100644
--- a/site/content/en/docs/Guides/feature-stages.md
+++ b/site/content/en/docs/Guides/feature-stages.md
@@ -24,11 +24,22 @@ that can be found in the [Helm configuration]({{< ref "/docs/Installation/Instal
The current set of `alpha` and `beta` feature gates are:
+{{% feature expiryVersion="1.5.0" %}}
| Feature Name | Gate | Default | Stage | Since |
|--------------|---------|---------|-------|-------|
| Multicluster Allocation* | N/A | Enabled | `Alpha` | 0.11.0 |
| Example Gate (not in use) | `Example` | Disabled | None | 0.13.0 |
| [Port Allocations to Multiple Containers]({{< ref "/docs/Reference/gameserver.md" >}}) | `ContainerPortAllocation` | Disabled | `Alpha` | 1.5.0 |
+{{% /feature %}}
+
+{{% feature publishVersion="1.6.0" %}}
+| Feature Name | Gate | Default | Stage | Since |
+|--------------|---------|---------|-------|-------|
+| Multicluster Allocation* | N/A | Enabled | `Alpha` | 0.11.0 |
+| Example Gate (not in use) | `Example` | Disabled | None | 0.13.0 |
+| [Port Allocations to Multiple Containers]({{< ref "/docs/Reference/gameserver.md" >}}) | `ContainerPortAllocation` | Disabled | `Alpha` | 1.5.0 |
+| [Player Tracking]({{< ref "/docs/Guides/player-tracking.md" >}}) | `PlayerTracking` | Disabled | `Alpha` | 1.6.0 |
+{{% /feature %}}
*Multicluster Allocation was started before this process was in place, and therefore is enabled by default,
and will not have a feature flag.
diff --git a/site/content/en/docs/Guides/player-tracking.md b/site/content/en/docs/Guides/player-tracking.md
new file mode 100644
index 0000000000..43a863b050
--- /dev/null
+++ b/site/content/en/docs/Guides/player-tracking.md
@@ -0,0 +1,126 @@
+---
+title: "Player Tracking"
+linkTitle: "Player Tracking"
+date: 2020-05-19
+weight: 30
+description: >
+ Track player connections, disconnections, counts and capacities through the Agones SDK
+---
+
+{{< alpha title="Player Tracking" gate="PlayerTracking" >}}
+
+## Managing GameServer Capacities
+
+To track your `GameServer` current player capacity, Agones gives you the ability to both set an initial capacity at
+`GameServer` creation, as well be able to change it during the lifecycle of the `GameServer` through the Agones SDK.
+
+To set the initial capacity, you can do so via `GameServer.Spec.Players.InitialCapacity` like so:
+
+```yaml
+apiVersion: "agones.dev/v1"
+kind: GameServer
+metadata:
+ name: "gs-example"
+spec:
+ # ...
+ players:
+ # set this GameServer's initial player capacity to 10
+ initialCapacity: 10
+```
+
+From there, if you need to change the capacity of the GameSever as gameplay is in progress, you can also do so via
+[`SDK.Alpha().SetPlayerCapacity(count)`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-setplayercapacity-count" >}})
+
+The current player capacity is represented in `GameServer.Status.Players.Capacity` resource value.
+
+We can see this in action, when we look at the Status section of a GameServer resource
+, wherein the capacity has been set to 20:
+
+```
+...
+Status:
+ Address: 14.81.195.72
+ Node Name: gke-test-cluster-default-6cd0ba67-1mps
+ Players:
+ Capacity: 20
+ Count: 0
+ Ids:
+ Ports:
+ Name: gameport
+ Port: 7983
+ Reserved Until:
+ State: Ready
+```
+
+From the SDK, the game server binary can also retrieve the current player capacity
+via [`SDK.Alpha().GetPlayerCapacity()`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-getplayercapacity" >}}).
+
+{{% alert title="Note" color="info" %}}
+Changing the capacity value here has no impact on players actually
+connected to or trying to connect to your server, as that is not a responsibility of Agones.
+
+This functionality is for tracking purposes only.
+{{% /alert %}}
+
+## Connecting and Disconnecting Players
+
+As players connect and disconnect from your game, the Player Tracking functions enable you to track which players
+are currently connected.
+
+It assumed that each player that connects has a unique token that identifies them as a player.
+
+When a player connects to the game server binary,
+calling [`SDK.Alpha().PlayerConnect(playerID)`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-playerconnect-playerid" >}})
+with the unique player token will register them as connected, and store their player id.
+
+At disconnection time,
+call [`SDK.Alpha().PlayerDisconnect(playerID)`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-playerdisconnect-playerid" >}})
+, which will deregister them and remove their player id from the list.
+
+Each of these `playerIDs` is stored on `GameServer.Status.Players.IDs`, and the current count of connected players
+can be seen in `GameServer.Status.Players.Count`.
+
+You can see this in action below in the `GameServer` Status section, where there are 4 players connected:
+
+```
+...
+Status:
+ Address: 39.82.196.74
+ Node Name: gke-test-cluster-default-6cd0ba77-1mps
+ Players:
+ Capacity: 10
+ Count: 4
+ Ids:
+ xy8a
+ m0ux
+ 71nj
+ lpq5
+ Ports:
+ Name: gameport
+ Port: 7166
+ Reserved Until:
+ State: Ready
+```
+
+{{% alert title="Note" color="info" %}}
+Calling `PlayerConnect` or `PlayerDisconnect` functions will not
+connect or disconnect players, as that is not under the control of Agones.
+
+This functionality is for tracking purposes only.
+{{% /alert %}}
+
+## Checking Player Data
+
+Not only is the connected player data stored on the `GameServer` resource, it is also stored in memory within the
+SDK, so that it can be used from within the game server binary as a realtime, thread safe, registry of connected
+players.
+
+Therefore, if you want to:
+
+* Get the current player count, call [`SDK.Alpha().GetPlayerCount()`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-getplayercount" >}})
+* Check if a specific player is connected, call [`SDK.Alpha().IsPlayerConnected(playerID)`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-isplayerconnected-playerid" >}})
+* Retrieve the full list of connected players, call [`SDK.Alpha().GetConnectedPlayers()`]({{< ref "/docs/Guides/Client SDKs/_index.md#alpha-getconnectedplayers" >}})
+
+## Next Steps
+
+* Review the [Player Tracking SDK Reference]({{< ref "/docs/Guides/Client SDKs/_index.md#player-tracking" >}})
diff --git a/site/content/en/docs/Reference/agones_crd_api_reference.html b/site/content/en/docs/Reference/agones_crd_api_reference.html
index c3b285a203..c2eafb515e 100644
--- a/site/content/en/docs/Reference/agones_crd_api_reference.html
+++ b/site/content/en/docs/Reference/agones_crd_api_reference.html
@@ -4050,8 +4050,7 @@
-
PlayersSpec tracks the initial player capacity, and what webhooks to send events to when there are
-connection/disconnection events.
+PlayersSpec tracks the initial player capacity
diff --git a/site/content/en/docs/Reference/gameserver.md b/site/content/en/docs/Reference/gameserver.md
index d52ce0f55c..4c2f13dbb7 100644
--- a/site/content/en/docs/Reference/gameserver.md
+++ b/site/content/en/docs/Reference/gameserver.md
@@ -9,6 +9,7 @@ description: >
A full GameServer specification is available below and in the {{< ghlink href="examples/gameserver.yaml" >}}example folder{{< /ghlink >}} for reference :
+{{% feature expiryVersion="1.5.0" %}}
```yaml
apiVersion: "agones.dev/v1"
kind: GameServer
@@ -79,6 +80,87 @@ spec:
image: gcr.io/agones-images/udp-server:0.19
imagePullPolicy: Always
```
+{{% /feature %}}
+
+{{% feature publishVersion="1.6.0" %}}
+```yaml
+apiVersion: "agones.dev/v1"
+kind: GameServer
+# GameServer Metadata
+# https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#objectmeta-v1-meta
+metadata:
+ # generateName: "gds-example" # generate a unique name, with the given prefix
+ name: "gds-example" # set a fixed name
+spec:
+ # if there is more than one container, specify which one is the game server
+ container: example-server
+ # Array of ports that can be exposed as direct connections to the game server container
+ ports:
+ # name is a descriptive name for the port
+ - name: default
+ # portPolicy has three options:
+ # - "Dynamic" (default) the system allocates a free hostPort for the gameserver, for game clients to connect to
+ # - "Static", user defines the hostPort that the game client will connect to. Then onus is on the user to ensure that the
+ # port is available. When static is the policy specified, `hostPort` is required to be populated
+ # - "Passthrough" dynamically sets the `containerPort` to the same value as the dynamically selected hostPort.
+ # This will mean that users will need to lookup what port has been opened through the server side SDK.
+ portPolicy: Static
+ # (Alpha) the name of the container to open the port on. Defaults to the game server container if omitted or empty.
+ container: simple-udp
+ # the port that is being opened on the game server process
+ containerPort: 7654
+ # the port exposed on the host, only required when `portPolicy` is "Static". Overwritten when portPolicy is "Dynamic".
+ hostPort: 7777
+ # protocol being used. Defaults to UDP. TCP is the only other option
+ protocol: UDP
+ # Health checking for the running game server
+ health:
+ # Disable health checking. defaults to false, but can be set to true
+ disabled: false
+ # Number of seconds after the container has started before health check is initiated. Defaults to 5 seconds
+ initialDelaySeconds: 5
+ # If the `Health()` function doesn't get called at least once every period (seconds), then
+ # the game server is not healthy. Defaults to 5
+ periodSeconds: 5
+ # Minimum consecutive failures for the health probe to be considered failed after having succeeded.
+ # Defaults to 3. Minimum value is 1
+ failureThreshold: 3
+ # Parameters for game server sidecar
+ sdkServer:
+ # sdkServer log level parameter has three options:
+ # - "Info" (default) The SDK server will output all messages except for debug messages
+ # - "Debug" The SDK server will output all messages including debug messages
+ # - "Error" The SDK server will only output error messages
+ logLevel: Info
+ # grpcPort and httpPort control what ports the sdkserver listens on.
+ # Starting with Agones 1.2 the default grpcPort is 9357 and the default
+ # httpPort is 9358. In earlier releases, the defaults were 59357 and 59358
+ # respectively but as these were in the ephemeral port range they could
+ # conflict with other TCP connections.
+ grpcPort: 9357
+ httpPort: 9358
+ # [Stage:Alpha]
+ # [FeatureFlag:PlayerTracking]
+ # Players provides the configuration for player tracking features.
+ # Commented out since Alpha, and disabled by default
+ # players:
+ # # set this GameServer's initial player capacity
+ # initialCapacity: 10
+ # Pod template configuration
+ # https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#podtemplate-v1-core
+ template:
+ # pod metadata. Name & Namespace is overwritten
+ metadata:
+ labels:
+ myspeciallabel: myspecialvalue
+ # Pod Specification
+ spec:
+ containers:
+ - name: simple-udp
+ image: gcr.io/agones-images/udp-server:0.19
+ imagePullPolicy: Always
+```
+{{% /feature %}}
Since Agones defines a new [Custom Resources Definition (CRD)](https://kubernetes.io/docs/concepts/api-extension/custom-resources/) we can define a new resource using the kind `GameServer` with the custom group `agones.dev` and API version `v1`.
@@ -89,6 +171,29 @@ The length of the `name` field of the Gameserver should not exceed 63 characters
The `spec` field is the actual GameServer specification and it is composed as follow:
+{{% feature expiryVersion="1.5.0" %}}
+- `container` is the name of container running the GameServer in case you have more than one container defined in the [pod](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/). If you do, this is a mandatory field. For instance this is useful if you want to run a sidecar to ship logs.
+- `ports` are an array of ports that can be exposed as direct connections to the game server container
+ - `name` is an optional descriptive name for a port
+ - `portPolicy` has three options:
+ - `Dynamic` (default) the system allocates a random free hostPort for the gameserver, for game clients to connect to.
+ - `Static`, user defines the hostPort that the game client will connect to. Then onus is on the user to ensure that the port is available. When static is the policy specified, `hostPort` is required to be populated.
+ - `Passthrough` dynamically sets the `containerPort` to the same value as the dynamically selected hostPort. This will mean that users will need to lookup what port to open through the server side SDK before starting communications.
+ - `container` (Alpha) the name of the container to open the port on. Defaults to the game server container if omitted or empty.
+ - `containerPort` the port that is being opened on the game server process, this is a required field for `Dynamic` and `Static` port policies, and should not be included in Passthrough
configuration.
+ - `protocol` the protocol being used. Defaults to UDP. TCP is the only other option.
+- `health` to track the overall healthy state of the GameServer, more information available in the [health check documentation]({{< relref "../Guides/health-checking.md" >}}).
+-`sdkServer` defines parameters for the game server sidecar
+ - `logging` field defines log level for SDK server. Defaults to "Info". It has three options:
+ - "Info" (default) The SDK server will output all messages except for debug messages
+ - "Debug" The SDK server will output all messages including debug messages
+ - "Error" The SDK server will only output error messages
+ - `grpcPort` the port that the SDK Server binds to for gRPC connections
+ - `httpPort` the port that the SDK Server binds to for HTTP gRPC gateway connections
+- `template` the [pod spec template](https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#podtemplatespec-v1-core) to run your GameServer containers, [see](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/#pod-templates) for more information.
+{{% /feature %}}
+
+{{% feature publishVersion="1.6.0" %}}
- `container` is the name of container running the GameServer in case you have more than one container defined in the [pod](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/). If you do, this is a mandatory field. For instance this is useful if you want to run a sidecar to ship logs.
- `ports` are an array of ports that can be exposed as direct connections to the game server container
- `name` is an optional descriptive name for a port
@@ -107,7 +212,9 @@ The `spec` field is the actual GameServer specification and it is composed as fo
- "Error" The SDK server will only output error messages
- `grpcPort` the port that the SDK Server binds to for gRPC connections
- `httpPort` the port that the SDK Server binds to for HTTP gRPC gateway connections
+- `players` (Alpha, behind "PlayerTracking" feature gate), sets this GameServer's initial player capacity
- `template` the [pod spec template](https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#podtemplatespec-v1-core) to run your GameServer containers, [see](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/#pod-templates) for more information.
+{{% /feature %}}
## GameServer State Diagram