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

minor corrections to the documentation #191

Merged
merged 1 commit into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ If you currently have [Prometheus](https://prometheus.io) & [Grafana](https://gr

Thundernetes requires a Kubernetes cluster with Public IP per Node. We've tested it extensively on [Azure Kubernetes Service - AKS](https://docs.microsoft.com/azure/aks/intro-kubernetes) as well as in local clusters using [kind](https://kind.sigs.k8s.io/). You also need to have ports 10000-12000 open in your cluster, since these are the ports that Thundernetes by default will set up on your Kubernetes Nodes so they can receive game network traffic and forward to your game server Pod.

> You can use a Kubernetes cluster without a Public IP. However, you would need to configure your own network architecture if you want to access your game servers. For example, if you use a cloud provider's Load Balancer, you would need to configure routes from Load Balancer's public endpoints to the internal ones on your Kubernetes cluster. Check [here](https://github.com/dgkanatsios/thundernetescontrib/tree/main/traefikingress) for an example controller with [traefik](https://github.com/traefik/traefik) ingress controller for HTTP-based game servers (e.g. WebGL).
> _**NOTE**_: You can use a Kubernetes cluster without a Public IP. However, you would need to configure your own network architecture if you want to access your game servers. For example, if you use a cloud provider's Load Balancer, you would need to configure routes from Load Balancer's public endpoints to the internal ones on your Kubernetes cluster. Check [here](https://github.com/dgkanatsios/thundernetescontrib/tree/main/traefikingress) for an example controller with [traefik](https://github.com/traefik/traefik) ingress controller for HTTP-based game servers (e.g. WebGL).

Moreover, Thundernetes requires ports in the range 10000-12000 to be open in the cluster for external connections (i.e. in the case of Azure Kubernetes Service, this port range must allow incoming traffic in the corresponding Network Security Group). This port range is configurable, check [here](howtos/configureportrange.md) for details.

Each GameServerBuild contains the *portsToExpose* field, which contains information about the port(s) that each GameServer listens to for incoming client connections. When the GameServer Pod is created, each port in the *portsToExpose* field will be assigned a port in the (default) range 10000-12000 (let's call it an external port) via a PortRegistry mechanism in the Thundernetes controller. Game clients can send traffic to this external port and this will be forwarded to the game server container port. Once the GameServer session ends, the port is returned back to the pool of available ports and may be re-used in the future.

> Each port that is allocated by the PortRegistry is assigned to HostPort field of the Pod's definition. The fact that Nodes in the cluster have a Public IP makes this port accessible outside the cluster.
> Thundernetes supports `hostNetwork` networking for the GameServer Pods, if requested in the GameServerBuild Pod definition.
> _**NOTE**_: Each port that is allocated by the PortRegistry is assigned to HostPort field of the Pod's definition. The fact that Nodes in the cluster have a Public IP makes this port accessible outside the cluster.
> _**NOTE**_: Thundernetes supports `hostNetwork` networking for the GameServer Pods, if requested in the GameServerBuild Pod definition.

## GameServer allocation

Expand Down
2 changes: 1 addition & 1 deletion docs/gameserverbuild.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ nav_order: 7

GameServerBuild defines the specification and auto-scaling configuration of the GameServers that you want to run in the cluster. Each version of your game server should have its own GameServerBuild.

> A GameServerBuild is equivalent to a Build region in MPS. GameServer containers that work in Thundernetes should work in a similar way on PlayFab Multiplayer Servers service.
> _**NOTE**_: A GameServerBuild is equivalent to a Build region in MPS. GameServer containers that work in Thundernetes should work in a similar way on PlayFab Multiplayer Servers service.

Here you can see the YAML that can be used to create a GameServerBuild in Thundernetes. The only fields that you should change after the GameServerBuild is created are the *standingBy* and the *max* ones. The other fields should be considered immutable.

Expand Down
4 changes: 2 additions & 2 deletions docs/gameserverlifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ You can view the states of your GameServers by typing `kubectl get gs`. The stat

GameServer Pods in the Initializing or StandingBy state can be taken down during a cluster scale-down. Thundernetes makes every effort to prevent Active GameServer Pods from being taken down, since this would have the undesirable effect of breaking an existing game. Moreover, as mentioned, GameServer can never transition back to StandingBy state from Active state. The only way to get a new game server in StandingBy state is if the GameServer process exits. You should gracefully exit your game server process when the game session is done and the last connected player has exited the game.

> If the game server process crashes for more than `crashesToMarkUnhealthy` times (specified in the GameServerBuild spec, default value 5), then no more operations will be performed on the GameServerBuild.
> _**NOTE**_: If the game server process crashes for more than `crashesToMarkUnhealthy` times (specified in the GameServerBuild spec, default value 5), then no more operations will be performed on the GameServerBuild.

> User is responsible for collecting logs while the Pod is running. Check [here](howtos/gameserverlogs.md) on how to do this.
> _**NOTE**_: User is responsible for collecting logs while the Pod is running. Check [here](howtos/gameserverlogs.md) on how to do this.

## Verifying GSDK integration with your game server

Expand Down
2 changes: 1 addition & 1 deletion docs/howtos/nodepools.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ spec:
...
```

> For more information on the NodeAgent process running in the DaemonSet, check the architecture document [here](../architecture.md#gsdk-integration).
> _**NOTE**_: For more information on the NodeAgent process running in the DaemonSet, check the architecture document [here](../architecture.md#gsdk-integration).

## Limit the number of available ports

Expand Down
20 changes: 11 additions & 9 deletions docs/howtos/runlocalmultiplayeragent.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,28 @@ To run LocalMultiplayerAgent to test your game servers for Thundernetes, you'll
}
```

> Some notes:
> _**NOTE**_: Some notes:
> 1. You must set `RunContainer` to true.
> 2. Modify `imageDetails` with your game server Docker image details. Image may be built locally (using [docker build](https://docs.docker.com/engine/reference/commandline/build/) command) or be hosted in a remote container registry. If you host it on a remote container registry, you must provide the username and password for the registry.
> 3. `StartGameCommand` and `AssetDetails` are optional. You don't normally use them when you use a Docker container since all game assets + start game server command can be packaged in the corresponding [Dockerfile](https://docs.docker.com/engine/reference/builder/).
> 4. Last, but definitely not least, pay attention to the casing on your `OutputFolder` variable, since Linux containers are case sensitive. If casing is wrong, you might see a Docker exception similar to *error while creating mount source path '/host_mnt/c/output/UnityServerLinux/PlayFabVmAgentOutput/2020-01-30T12-47-09/GameLogs/a94cfbb5-95a4-480f-a4af-749c2d9cf04b': mkdir /host_mnt/c/output: file exists*

## Verifying GSDK integration

- After you perform all the previous steps, you can then run the LocalMultiPlayerAgent with the command `LocalMultiplayerAgent.exe -lcow` (lcow stands for *Linux Containers On Windows*)
- If the GSDK is integrated correctly, **LocalMultiplayerAgent** prints the following outputs:
- `CurrentGameState - Initializing` (this is optional and may not show up if your game server directly calls `GSDK::ReadyForPlayers` and does not call `GSDK::Start`)
- `CurrentGameState - StandingBy`
- `CurrentGameState - Active`
- `CurrentGameState - Terminating`
- At this point, LocalMultiplayerAgent will try to execute the GSDK shutdown callback which **is not** required for Thundernetes. You can either implement it (by exiting the game server process manually) or simply cancel LocalMultiplayerAgent execution and then manually delete the game server container (by executing `docker rm -f <containerName>`).
After you perform all the previous steps, you can then run the LocalMultiPlayerAgent with the command `LocalMultiplayerAgent.exe -lcow` (lcow stands for *Linux Containers On Windows*).

If the GSDK is integrated correctly, **LocalMultiplayerAgent** prints the following outputs:
- `CurrentGameState - Initializing` (this is optional and may not show up if your game server directly calls `GSDK::ReadyForPlayers` and does not call `GSDK::Start`)
- `CurrentGameState - StandingBy`
- `CurrentGameState - Active`
- `CurrentGameState - Terminating`

At this point, LocalMultiplayerAgent will try to execute the GSDK shutdown callback which **is not** required for Thundernetes. You can either implement it (by exiting the game server process manually) or simply cancel LocalMultiplayerAgent execution and then manually delete the game server container (by executing `docker rm -f <containerName>`).

### Testing connection to your game

When your game server executable is running and **LocalMultiplayerAgent** prints `CurrentGameState - Active`, you can connect to your game server using IP address **127.0.0.1** and port `NodePort` on which your game server is listening.

After `NumHeartBeatsForActivateResponse` heartbeats, **LocalMultiplayerAgent** requests the game server to move from standby to active.

> You can also check the (very similar) MPS instructions [here](https://docs.microsoft.com/en-us/gaming/playfab/features/multiplayer/servers/locally-debugging-game-servers-and-integration-with-playfab#using-localmultiplayeragent-with-linux-containers).
> _**NOTE**_: You can also check the (very similar) MPS instructions [here](https://docs.microsoft.com/en-us/gaming/playfab/features/multiplayer/servers/locally-debugging-game-servers-and-integration-with-playfab#using-localmultiplayeragent-with-linux-containers).
10 changes: 5 additions & 5 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ nav_order: 2

We've tested Thundernetes on the latest versions of Azure Kubernetes Service (AKS) and [kind](https://kind.sigs.k8s.io/) but it can theoretically be installed on any Kubernetes cluster supporting Public IP per Node (which is something you want if you want to expose your game servers outside the cluster). Read the relevant section depending on where you want to install Thundernetes.

> If you are using Windows, we recommend using [Windows Subsystem for Linux](https://docs.microsoft.com/windows/wsl/install) to run the CLI commands listed below.
> _**NOTE**_: If you are using Windows, we recommend using [Windows Subsystem for Linux](https://docs.microsoft.com/windows/wsl/install) to run the CLI commands listed below.

## Create an Azure Kubernetes Service cluster with a Public IP per Node

Expand Down Expand Up @@ -39,7 +39,7 @@ kubectl cluster-info

Thundernetes requires VMs to have Public IPs (so game servers can be accessible) and be able to accept network traffic at port range 10000-12000 from the Internet.

> This port range is configurable, check [here](howtos/configureportrange.md) for details.
> _**NOTE**_: This port range is configurable, check [here](howtos/configureportrange.md) for details.

To open the ports you need to perform the following steps *after your AKS cluster gets created*:

Expand Down Expand Up @@ -156,7 +156,7 @@ This sample, located [here](https://github.com/playfab/thundernetes/samples/netc
kubectl apply -f https://github.com/PlayFab/thundernetes/main/samples/netcore/sample.yaml
```

> To read about the fields that you need to specify for a GameServerBuild, you can check [this document](gameserverbuild.md).
> _**NOTE**_: To read about the fields that you need to specify for a GameServerBuild, you can check [this document](gameserverbuild.md).

Try using `kubectl get gs` to see the running game servers, you should see something similar to this:

Expand All @@ -175,7 +175,7 @@ NAME STANDBY ACTIVE CRASHES HEALTH
gameserverbuild-sample-netcore 2/2 0 0 Healthy
```

> `gs` and `gsb` are just short names for GameServer and GameServerBuild, respectively. You could just type `kubectl get gameserver` or `kubectl get gameserverbuild` instead.
> _**NOTE**_: `gs` and `gsb` are just short names for GameServer and GameServerBuild, respectively. You could just type `kubectl get gameserver` or `kubectl get gameserverbuild` instead.

To scale your GameServerBuild, you can do `kubectl edit gsb gameserverbuild-sample-netcore` and edit the max/standingBy numbers.

Expand All @@ -198,7 +198,7 @@ The arguments to the allocation call are two:
* buildID: this must be the same as the buildID configured in the GameServerBuild
* sessionID: a GUID that you can use to identify the game server session. Must be unique for each game server you allocate. If you try to allocate using a sessionID that is in use, the call will return the details of the existing game server.

> The allocation call is equivalent to calling [RequestMultiplayerServer](https://docs.microsoft.com/rest/api/playfab/multiplayer/multiplayer-server/request-multiplayer-server) in PlayFab Multiplayer Servers.
> _**NOTE**_: The allocation call is equivalent to calling [RequestMultiplayerServer](https://docs.microsoft.com/rest/api/playfab/multiplayer/multiplayer-server/request-multiplayer-server) in PlayFab Multiplayer Servers.

Result of the allocate call is the IP/Port of the server in JSON format.

Expand Down
14 changes: 6 additions & 8 deletions docs/usingwrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,20 @@ title: Using a wrapper utility
nav_order: 4
---

# Using a wrapper utility
# Using a wrapper utility (wrappingGsdk)

## Mpswrapper

Your game server needs to be integrated with the Game Server SDK ([GSDK](https://github.com/PlayFab/gsdk)) in order to work with Thundernetes. However, if you want to try your game server withoug integrating with GSDK you can use a wrapper utility application which:
Your game server needs to be integrated with the Game Server SDK ([GSDK](https://github.com/PlayFab/gsdk)) in order to work with Thundernetes. However, if you want to try your game server without integrating with GSDK you can use a wrapper utility application which:

- integrates with GSDK
- starts and monitors ("wraps") your game server executable

We have built such a utility (called 'mpswrapper') [here](https://github.com/PlayFab/MpsSamples/tree/master/wrappingGsdk). Mpswrapper is also published as container image on GitHub Container Registry [here](https://github.com/PlayFab/MpsSamples/pkgs/container/mpswrapper) which should be used as the container image in the GameServerBuild definition.
We have built such a utility (called 'wrappingGsdk') [here](https://github.com/PlayFab/MpsSamples/tree/master/wrappingGsdk). This utility is also published as container image under the name `mpswrapper` on GitHub Container Registry [here](https://github.com/PlayFab/MpsSamples/pkgs/container/mpswrapper) which should be used as the container image in the GameServerBuild definition.

The game server needs to be built and packaged in a place where your Kubernetes cluster can access it. Kubernetes workloads can use [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) to access data external to the Pod. For this sample, we will demonstrate the use of [Azure Files](https://azure.microsoft.com/en-us/services/storage/files/) storage to place the game server files but you are free to use the storage service of your choice.

> Azure Files **Premium** is recommended for optimal performance.
> _**NOTE**_: Azure Files **Premium** is recommended for optimal performance if you are running on Azure.

Your game server should *NOT* be integrated with GSDK, since the mpswrapper application is already integrated. It should be compiled as a Linux executable.
Your game server should *NOT* be integrated with GSDK, since the `wrappingGsdk` application is already integrated. It should be compiled as a Linux executable.

As soon as you create an Azure Files account, create a Files share and copy your game server there. You should make sure that Kubernetes knows how to authenticate to your Azure Storage account. One way to do that is create a [Kubernetes Secret](https://kubernetes.io/docs/concepts/configuration/secret/) using the below script:

Expand Down Expand Up @@ -54,6 +52,6 @@ volumes:

### Links

- Mpswrapper code is [here](https://github.com/PlayFab/MpsSamples/tree/master/wrappingGsdk) and the latest container image version can be found [here](https://github.com/PlayFab/MpsSamples/pkgs/container/mpswrapper)
- `WrappingGsdk` code is [here](https://github.com/PlayFab/MpsSamples/tree/master/wrappingGsdk) and the latest container image version can be found [here](https://github.com/PlayFab/MpsSamples/pkgs/container/mpswrapper)
- Instructions on how to mount an Azure Files share on your Kubernetes Pods can be found [here](https://docs.microsoft.com/en-us/azure/aks/azure-files-volume)
- You can find a sample YAML file [here](https://github.com/playfab/thundernetes/blob/main/samples/fileshare/sample.yaml)
2 changes: 1 addition & 1 deletion docs/yourgameserver.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ if (initialConfig?.ContainsKey(ListeningPortKey) == true)
// instantiate your game server with the value of the listeningPort
```

> Unfortunately, it is still necessary to provide a `containerPort` value in the GameServerBuild YAML, since it is required for GameServerBuild validation. However, as mentioned, this provided value is used nowhere since it's overwritten by the `hostPort` value.
> _**NOTE**_: Unfortunately, it is still necessary to provide a `containerPort` value in the GameServerBuild YAML, since it is required for GameServerBuild validation. However, as mentioned, this provided value is used nowhere since it's overwritten by the `hostPort` value.

## Game server image upgrades

Expand Down