This solution provides an easy start with Container Fleets on Amazon GameLift. You can use any game server Linux binary you have, and you are not required to integrate with the Amazon GameLift Server SDK to get started. We also utilize AWS CloudFormation and AWS CodeBuild to create the required Amazon GameLift resources, and to deploy new game server versions on the fleet. You don't need to install any tools locally, and can simply upload your game server build to Amazon S3 and deploy with a single button in the CodeBuild project.
When you want to take advantage of the full features of the Amazon GameLift Server SDK, you can follow the instructions to integrate with the Amazon GameLift Server SDK directly.
Total time for deploying the solution utilizing your existing Linux server build is around 15-30 minutes.
Clone this repository and open the correct folder by running the following command in CloudShell:
git clone https://github.com/aws/amazon-gamelift-toolkit.git
cd amazon-gamelift-toolkit/containers-starter-kit/
You should also open the containers-starter-kit
folder in your favorite IDE or editor.
- Open the AWS CloudFormation console in your browser and select Create stack -> With new resources
- Select Upload template and upload the
fleet_deployment_pipeline.yml
file, and select Next - Enter the Stack Name. You can use any name you want. For quick testing, just set the the Port and Protocol fields to match your game server's configuration and select Next.
- Acknowledge the creation of IAM resources, and select Next. Then review and select Submit
NOTE: The fleet is configured to be development environment friendly, ie. it doesn't protect game sessions from terminations. Same applies to the game server version updates we are doing. It's worth enabling protection for both the fleet (NewGameSessionProtectionPolicy), as well as the deployments (--new-game-session-protection-policy) in production.
- Copy your game server Linux build to the
ServerBuild
folder. This is typically an Unreal or Unity headless server build, but it can be any binary that runs on Linux. - Open
wrapper.sh
and set- The port you're using for your game server (
PORT=1234
) - Your game server binary path (
SERVER_BINARY_PATH=ServerBuild/yourgameserverbinaryhere
). For Unreal games, reference the full path to the binary. If you use the .sh launcher, follow the instructions in wrapper.sh to make both the shell script and the binary executable.
- The port you're using for your game server (
- Create a zip file called
gameserver.zip
that contains all the files compressed from the root of thecontainers-starter-kit
folder (including the SdkGoWrapper and ServerBuild subfolders). NOTE: This zip file should not include the parent folder itself. You need to include all the files and folders inside the parent folder for the zip (such as wrapper.h, Dockerfile, and the subfolders).
NOTE: The Dockerfile is configured to run as a custom non-root user to support Unreal Engine server builds. If you run a Unreal server binary directly, the above works as is. If you however want to run the yourgameserver.sh
file, make sure to modify the wrapper to make that executable too (see wrapper.sh notes).
In case your game server requires additional packages or configuration on the container, see Customizing the Dockerfile.
- In the CloudFormation console, select Outputs in your stack, and open the link for GameServerBuildBucket in a new tab
- Upload
gameserver.zip
by selecting Upload, then dragging yourgameserver.zip
to the upload area and selecting Upload again - After the upload is complete, go back to the CloudFormation console, open the link for GameServerCodeBuildProject in a new tab
- Select Start build to start the build of your container image and the Amazon GameLift Container Group Definition that will be automatically deployed to the fleet created before
NOTE: Uploading a large build (such as an Unreal server) can be slow through the browser. It's a lot faster using the AWS CLI.
You can follow the build process in CodeBuild to make sure it succeeds without errors. If you want to see the steps of the build process, select the Build Details tab and review the BuildSpec. This includes setting up the SDK, building your container, and deploying a new container group to the fleet. After the build succeeds, you can use the Amazon GameLift console to review the deployment of the container group to your Amazon GameLift fleet. Once the fleet is active, you can move on to testing with a game session.
- Open AWS CloudShell in the AWS Management console in your browser (or use the AWS CLI locally)
- Create a game session by running the following command with your Fleet ID and the region you used when deploying the solution
aws gamelift create-game-session --fleet-id <YOURFLEETIDHERE> --location <YOURREGION> --maximum-player-session-count 10
- You will receive an IP and a Port for the game session along with other information. Use the port and IP to connect to the session from your game client. Optimally your game server should terminate after it has completed hosting a session, which will trigger the game session to terminate and be replaced with a new container.
Your game server can retrieve the initial game session data, as well as updated data (matchmaking backfills) by making a GET
HTTP request to the localhost endpoint provided by the wrapper:
localhost:8090/gamesessiondata
The response always contains a JSON string with the game session info, but the fields are empty if there is no game session assigned to the process yet. When the game session is updated with more players by FlexMatch (in case you're using it), the updated game session is automatically returned.
The game session data JSON string value has the following format:
{
"GameSessionId": "arn:aws:gamelift:REGION::gamesession/FLEET/GAMESESSION",
"GameSessionData": "DATA",
"Name": "NAME",
"MatchmakerData": "{\"matchId\":\"ID\",\"matchmakingConfigurationArn\":\"arn:aws:gamelift:REGION:ACCOUNT:matchmakingconfiguration/NAME\",\"teams\":[{\"NAME\":\"VALUE\",\"players\":[{\"playerId\":\"123\",\"attributes\":{\"NAME\":{\"attributeType\":\"TYPE\",\"valueAttribute\":\"VALUE\"}}}]}],\"autoBackfillMode\":\"AUTOMATIC|MANUAL\",\"autoBackfillTicketId\":\"auto-backfill-TICKETID\"}",
"FleetId": "containerfleet-FLEETID",
"Location": "",
"MaximumPlayerSessionCount": 123,
"IpAddress": "1.2.3.4",
"Port": 1234,
"DnsName": "DNS.REGION.compute.amazonaws.com",
"GameProperties": {
"NAME": "VALUE"
},
"StatusReason": "VALUE"
}
NOTE: While this localhost endpoint provides you basic information, it is recommended to integrate with the Amazon GameLift Server SDK when you want to fully utilize the capabilities of the service including player session validation, deep health checks etc.
In case your Amazon GameLift Containers fleet doesn't become active when doing a deployment, the best place to look at is the Amazon CloudWatch Logs console, and finding the log group with your fleet ID. The log output contains both the output of the sidecar process managing the GameLift Server Go SDK, as well as the output of your actual game server binary.
Typical issues
- The game server binary can't be run (wrong name, missing dependencies etc.). This will result in the wrapper to terminate immediately and will fail the deployment
- The game server binary exits too fast. You're expected to wait for actual players to connect, and only terminate the process after the session is played
The log output should be able to give you insights in where it's failing.
The solution consists of a few key components. These components include
- SdkGoWrapper which is automatically built as part of the CodeBuild project. It utilizes the Amazon GameLift Server SDK for Go, and automatically registers and terminates your game server process
- wrapper.sh which runs the SdkGoWrapper in the background, registering the port you have defined to Amazon GameLift. It also runs your game server binary, and waits for it to terminate. Once it terminates, it will signal the SdkGoWrapper to correctly terminate the game session from Amazon GameLift
- Dockerfile which includes the setup for creating a container image that contains the built SdkGoWrapper and your game server binary. It utilizes the
wrapper.sh
as the entry point of the container - fleet_deployment_pipeline.yml which deploys an Amazon S3 bucket for game server build hosting, as well as the Amazon GameLift container fleet that will host your game server builds. It also deploys an AWS CodeBuild project which builds your container image, uploads it to Amazon ECR, and deploys a new Container Group Definition version to your fleet
The Go SDK Wrapper we use manages the communication to the Amazon GameLift service on behalf of your game server. It automatically replies healthy to health checks, and automatically activates the game sessions as requests come in. Once it receives the SIGINT
signal from the wrapper.sh
, it will call ProcessEnding
to make sure GameLift immediately replaces the container with a new one and terminates a running game session.
The wrapper does not pass any game session information to the game server process itself, as it is running on the side. If you need deeper integration to the game session data of Amazon GameLift, you should see Customization below to integrate with the Amazon GameLift Server SDK directly.
There are several aspects of the solution you might want to customize.
If you want to install any additional packages required by your game server, or want to use a different base image, you can customize the Dockerfile
to do this. The default implementation first installs Go for the wrapper, and then copies the SDKGoWrapper, your game server, and the wrapper.sh
file over to the container environment. I then makes sure the wrapper is executable and uses it as the entry point of your game server container.
Any changes you make to the Dockerfile will be picked up by the CodeBuild build automation when you upload a new zip package to S3 and start a new build.
The Amazon GameLift Server SDKs provide a number of benefits to the simple wrapper approach we're using. These include ability to receive game session data, including updates when backfilling more players with GameLift FlexMatch. It also allows you to implement a deep health check that considers the internal health state of your game server, and allows you to validate player session ID's.
To make use of the Server SDK, integrate the appropriate version to your game server following the guidelines of each SDK. Then make the following changes:
- In the
Dockerfile
, replace thewrapper.sh
in theCMD
command with your game server binary directly - (OPTIONAL): To optimize the build process, remove all the steps related to the wrapper in the CodeBuild Project definition in
fleet_deployment_pipeline.yml
and update the CloudFormation stack with your new version. You can removegolang
from theruntime-versions
and remove the following steps from the build steps:
# REMOVE THESE
- cd SdkGoWrapper
- mkdir gamelift-server-sdk
- cd gamelift-server-sdk
- wget https://gamelift-server-sdk-release.s3.us-west-2.amazonaws.com/go/GameLift-Go-ServerSDK-5.2.0.zip
- unzip -q GameLift-Go-ServerSDK-5.2.0.zip
- cd ..
- go mod tidy
- go build
- cd ..
# KEEP BELOW THIS