Here we will take an existing open-source multiplayer game and then show how we can open and edit it using Visual Studio, and then deploy it directly from VS onto our back-end, by using GitHub Actions.
Microsoft Game Stack is a collection of tools and services, including tools like Microsoft Azure, PlayFab, Xbox Services, and Visual Studio. Game developers of all sizes, from indie studios to AAA teams, can use these tools to build and launch amazing games. When we’re building games with real-time multiplayer features, a smooth and automated workflow, from development to production environment deployment, saves a lot of time and effort for the developers. Plus, it reduces the chances for errors in the process.
In this article, we’re going to build on the Azure Kubernetes Service cluster from the previous part of this series. We’ll use GitHub Actions to automatically deploy a fully playable open-source multiplayer snake game whenever new code is pushed to the repository from Visual Studio Code.
Requirements
To follow along with this guide, you’ll need an Azure account with a subscription, a GitHub account, and the following software installed on your computer:
You’ll also need an AKS cluster that is ready for container deployment. If you don’t have one, you can follow the steps to create an AKS cluster in the previous part of the series.
Creating a Fork of the Multiplayer Snake Game
For this example, we’re going to use a cool open-source multiplayer snake game built on Node.js, Express, and Socket.io by Simon Diep on GitHub.
Be sure you’re signed into GitHub, and then click the Fork button at the top-right of the page to have your own copy of the repository for making new changes.
Next, open up Visual Studio Code and navigate to Source Control on the left bar. Click Clone Repository, select Clone from GitHub, and authorize access to your GitHub account if you need to. Then, search for the node-multiplayer-snake
repository and choose a folder to download the source code into.
With the game code now on your computer, we just need to install dependencies to test and make sure everything is correct. We can do this by opening the terminal directly inside VS Code with the keyboard shortcut ^ + ` (or Ctrl + `), and then typing npm install
.
Next, run the project locally with npm start
and open the game in a web browser at http://localhost:3000. You should see the snake game, with arrow keys for controls.
Setting up GitHub Actions
With the game server ready, we can now set up the GitHub repository to build the Docker image and deploy it to our AKS cluster.
Open your GitHub repository from a web browser and click Actions in your GitHub repository, and then select set up a workflow yourself to create a new workflow.
Overwrite the provided template with the template inside this Build-and-Deploy-Docker-Image workflow sample. Then, in the env
section of the workflow file, set the REGISTRY_NAME
to your Azure Container Registry name, CLUSTER_NAME
to the AKS cluster name, and the CLUSTER_RESOURCE_GROUP
to your resource group name.
It should look something like this:
# Environment variables available to all jobs and steps in this workflow
env:
REGISTRY_NAME: msgsdeployregistry
CLUSTER_NAME: ms-gs-deploy-app
CLUSTER_RESOURCE_GROUP: ms-gs-deploy
NAMESPACE: default
Now you can commit this workflow file.
Next, we will need to add three GitHub repository secrets, for REGISTRY_USERNAME
, REGISTRY_PASSWORD
, and AZURE_CREDENTIALS
.
To add secrets, navigate to the repository Settings, scroll down, and click on Secrets.
The following command in a terminal window creates an Active Directory Service Principal and will give us the registry username and password values to use:
az ad sp create-for-rbac --skip-assignment
This will return a JSON object of values that looks a bit like this:
{
"appId": "14c2e46b-abdc-4c06-0c13-1d4e7bd3b203",
"displayName": "azure-cli-2021-09-20-06-39-00",
"name": "http://azure-cli-2021-09-20-06-39-00",
"password": "agJMg1LpRv654~ErFoI~_YbIxFP2PZ_Z9f",
"tenant": "fa928ab4-e149-41d6-af72-1dcc537cfd29"
}
The appId
is our value to use for REGISTRY_USERNAME
and the password
is the value we need to use as our REGISTRY_PASSWORD
. Create and save these repository secrets in the repository.
The Azure credentials secret value is a full JSON object that can be retrieved using the following command:
az ad sp create-for-rbac --sdk-auth
The output will look like this:
{
"clientId": "41e027f8-6620-4695-842d-8be259090b1f",
"clientSecret": "PYcqJ7K_.EaqjoQVgmY_4-wt6Eshj03Z2j",
"subscriptionId": "de4b56e1-ab1c-489b-afc6-d286c13f7485",
"tenantId": "fa928ab4-e149-41d6-af72-1dcc537cfd29",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"}
Copy and save the whole JSON object into the last repository secret, and click Add secret. Here, we named the secret AZURE_CREDENTIALS
.
Let’s verify that the registry username and password give us proper access to the Azure Container Registry. This ensures that GitHub can push the built images to it.
We’ll do this across two commands.
First, set the ACR_ID
variable using your resource group name, and the ACR name in this command:
ACR_ID=$(az acr show --resource-group {YOUR-RESOURCE-GROUP} --name {ACR-NAME} --query "id" --output tsv)
For example:
ACR_ID=$(az acr show --resource-group ms-gs-deploy --name msgsdeployregistry --query "id" --output tsv)
Then, assign the Contributor
role to the username (appId
) created earlier, like this:
az role assignment create --assignee {appId} --role Contributor --scope $ACR_ID
Here’s an example:
az role assignment create --assignee 14c2e46b-abdc-4c06-0c13-1d4e7bd3b203 --role Contributor --scope $ACR_ID
Build and Deployment Configurations
We are almost ready! We need a Dockerfile
in the repository, used in building the repository into a Docker container, and "service.yml" and "deployment.yml" manifest files to specify how it should be deployed to the AKS cluster.
Create a Dockerfile
in the project folder, which will copy the project files into a /src folder. Then, install the dependencies, expose port 3000, and then start the project. You can simply use the same Dockerfile from the previous project if you wish. It will look a bit like this:
FROM node:14-alpine
WORKDIR /src
COPY package*.json ./
RUN npm install --production
COPY . /src
EXPOSE 3000
CMD [ "npm", "start" ]
Next, create a folder named "manifests" inside the project folder and create the following two files: "service.yml" and "deployment.yml." Be sure to replace the login server address to match your ACR for the container image (for example, "msgsdeployregistry.azurecr.io"), and you can specify your app name instead of "test-app," if you wish.
The "service.yml" file should contain the following code:
apiVersion: v1
kind: Service
metadata:
name: test-app
spec:
type: LoadBalancer
ports:
- port: 3000
selector:
app: test-app
Our "deployment.yml" file should look like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app
spec:
replicas: 1
selector:
matchLabels:
app: test-app
template:
metadata:
labels:
app: test-app
spec:
containers:
- name: test-app
image: msgsdeployregistry.azurecr.io/myimage:latest
ports:
- containerPort: 3000
Finally, you can commit and push these files from VS Code.
And that’s it! You can open the GitHub Actions page and select the main workflow to watch the action live as the image automatically builds and deploys to your AKS cluster.
After deployment is completed, you can open a web browser to the external IP address of the cluster’s Load Balancer to play the game hosted from the cloud.
To get the IP address, run this command:
kubectl get service test-app --watch
What’s Next?
Great job! You’re now able to edit your game server code and automatically deploy it with a simple push to your GitHub repository. For more complex projects, you could update the workflow to only deploy on changes to the main or even connect to GitHub webhooks for notifications to a messaging app.
In the final part of this series, we’ll explore how to use PlayFab to add events and gather data from our game for LiveOps and Analytics.
Optional: Cleaning up
If you’re done after this demo and would like to stop here, you can use the following command to delete your resources on Azure to avoid any unexpected server costs:
az group delete --name {YOUR-RESOURCE-GROUP} --yes --no-wait