Skip to main content

Deploying Locally

danger

Make sure you have a Redwood-specific version of Rancher Desktop; it will have (Redwood) listed in the title and versions. If you don't have these, you'll need to follow the steps on uninstalling the current version and installing the new version.

How to check if you have the Redwood version

Redwood label in Rancher Desktop versions

Deploying Redwood uses the provided Infrastructure-as-Code (IaC); the same workflow is used to deploy to a local development Kubernetes cluster as well as production ones.

If you installed all of the prerequisites properly, you're ready to test deploying the Redwood backend to your local Kubernetes cluster (which Rancher Desktop hosts within WSL). Altogether, this setup gives us a Linux environment that has Docker and Kubernetes, which is very similar to what deploying to a cloud provider would look like.

Redwood Configuration

While it's not strictly required to set up a configuration environment for development for just getting started, it will be convenient to have it when you inevitably want to change something.

  1. Create a new folder in config/node for the Kubernetes dev environment (e.g. redwood-demo-kubernetes [k8s is a common abbreviation for Kubernetes])

  2. Create a _config.json file in that folder (e.g. config/node/redwood-demo-kubernetes/_config.json) with the parentNames pointing to the environment folder you created earlier and the provided kubernetes environment.

    For example:

    {
    "parentNames": ["kubernetes", "redwood-demo"]
    }
    note

    You might have started to noticed the inheritance pattern we've been introducing for configuration. In our examples, we have the config env redwood-demo-kubernetes inherit from redwood-demo. Later, when we deploy to a cloud, you'll see that we'll introduce a config env redwood-demo-production that inherits from redwood-demo-kubernetes. This pattern isn't required, but it can prevent issues where a config variable was added for development but not for production.

    You can read more about configuration inheritance here.

  3. The documentation used to have you override realm.instances.default.game-servers.provider to "local" in your base config environment, but this override is actually redundant and conflicts with the kubernetes parent config environment. You can either remove it from your original config (e.g. config/node/redwood-demo/realm/instances/default.yaml) or override it in this new config environment (e.g. realm-demo-kubernetes) such that the associated config variablerealm.instances.default.game-servers.provider is set to "agones".

Pulumi Configuration

Pulumi can run in different modes:

  • Storing the Pulumi state locally
    • This is the default for easy onboarding, but you should consider other options for teams and nearing launch
  • Storing in another self-managed backend (e.g. S3, Azure Blob Storage, or Google Cloud Storage)
  • Storing the Pulumi state in an instance of Pulumi Cloud
info

By default, Redwood is configured to store the Pulumi state locally, which is just fine when you're getting started. You may want to consider switching to use Pulumi Cloud (you can self-host or use Pulumi's managed service that's very affordable with a great free tier). We prefer using Pulumi Cloud over the other self-managed options like S3 due to the better integration and auditable records. However, having a shareable backend state is critical for teams and ensuring that your Pulumi deployment state isn't lost in the event of a personal computer loss.

  1. In the folder you created above, create a deployment/pulumi.yaml file (e.g. config/node/redwood-demo-kubernetes/deployment/pulumi.yaml) with the contents:

    project: "<project-name>"

    For example:

    project: "redwood-demo"
    note

    If you're using Pulumi Cloud, you'll also need to add to the file:

    local-mode: false
    org: "<pulumi-org-name>"

    Redwood is pre-configured to work with Pulumi's managed service when local-mode is false, but if you are self-hosting Pulumi Cloud, you can also change the URL to your Pulumi Cloud instance:

    url: "https://yourpulumicloud.com"
    note

    Some IDEs (e.g. VSCode) will error about pulumi.yaml having a syntax error because it's referring to another schema that Pulumi has for files named pulumi.yaml. You can prevent this, at least in VSCode, by adding this line to the top of the file:

    # yaml-language-server: $schema=./pulumi.yaml

Deploying

Deploying locally for basic configurations is fairly straight forward:

  1. Ensure Rancher Desktop is running

  2. Open a terminal to the RedwoodBackend directory

  3. Install the NodeJS dependencies by running the below command:

    yarn
    note

    yarn will automatically trigger a build, but you can recompile manually by running yarn build.

  4. Skip this if you have a Standard License of Redwood. If you have access to the full source code of Redwood, you need to package the sidecar:

    yarn pkg:sidecar
  5. Copy the folder generated when you packaged the Linux Server to RedwoodBackend/dist; it will have the name LinuxServer

    Copying the LinuxServer folder to the dist folder

  6. Deploy the Redwood backend by running the below command:

    yarn deploy <config-environment>

    Where <config-environment> is the folder you created above (e.g. redwood-demo-kubernetes).

    This command will do the following:

    1. Create the necessary Docker images
    2. Deploy the necessary dependencies to the local Kubernetes cluster
    3. Deploy the Redwood images to the local Kubernetes cluster
    note

    Docker images are not automatically created in yarn deploy if you're inheriting from the staging or production configuration environments. You will need to use the yarn docker command beforehand to create them. You can read more about this in Deploying to the Cloud.

  7. You may be prompted if you want to create the configured Pulumi stack. By default the stack is dev, but you can override this in the above pulumi.yaml file with stack: "<stack-name>". If the name of the stack looks right, press the Enter key.

  8. Pulumi will start generating a preview of the deployment; no changes are made and you'll be prompted if the proposed changes should be applied. Press the Up arrow to select yes and press the Enter key:

    Created stack 'incanta/dev-mike'
    Previewing update (incanta/dev-mike)

    View in Browser (Ctrl+O): https://app.pulumi.com/incanta/redwood-demo/dev-mike/previews/2f235049-fc1c-49c7-9172-f20f374aed82

    Type Name Plan
    + pulumi:pulumi:Stack redwood-demo-dev-mike create
    + ├─ docker:index:Image yourcr.com/container/redwood-dev-image create
    + ├─ docker:index:Image yourcr.com/container/game-server-image create
    + ├─ pulumi:providers:kubernetes k8s-provider-local create
    + ├─ kubernetes:core/v1:ConfigMap game-server-config-map-local create
    + ├─ kubernetes:helm.sh/v3:Release redis create
    + ├─ kubernetes:helm.sh/v3:Release ingress create
    + ├─ kubernetes:helm.sh/v3:Release open-match create
    + ├─ kubernetes:helm.sh/v3:Release mongo create
    + ├─ kubernetes:helm.sh/v3:Release agones-local create
    + ├─ kubernetes:core/v1:ConfigMap director-frontend-config-map-local create
    + ├─ kubernetes:core/v1:ServiceAccount realm-backend-account-local create
    + ├─ kubernetes:core/v1:ConfigMap director-backend-config-map-local create
    + ├─ kubernetes:rbac.authorization.k8s.io/v1:Role gameservers-allocations-role-local create
    + ├─ kubernetes:core/v1:ConfigMap match-function-config-map-local create
    + ├─ kubernetes:networking.k8s.io/v1:Ingress director-ingress-local create
    + ├─ kubernetes:agones.dev/v1:Fleet agones-fleet-local create
    + ├─ kubernetes:apps/v1:StatefulSet director-frontend-local create
    + ├─ kubernetes:autoscaling.agones.dev/v1:FleetAutoscaler agones-fleet-autoscaler-local create
    + ├─ kubernetes:apps/v1:StatefulSet match-function-local create
    + ├─ kubernetes:rbac.authorization.k8s.io/v1:RoleBinding read-gameservers-write-allocation-local create
    + ├─ kubernetes:core/v1:Service director-frontend-debug-local create
    + ├─ kubernetes:core/v1:Service director-frontend-local create
    + ├─ kubernetes:core/v1:Service match-function-debug-local create
    + ├─ kubernetes:core/v1:Service match-function-local create
    + ├─ kubernetes:apps/v1:StatefulSet director-backend-local create
    + ├─ kubernetes:core/v1:Service realm-backend-local create
    + ├─ kubernetes:core/v1:Service director-backend-debug-local create
    + └─ kubernetes:core/v1:Service director-backend-local create
    Outputs:
    k8sId: "Local Deployment"

    Resources:
    + 29 to create

    Do you want to perform this update? [Use arrows to move, type to filter]
    yes
    > no
    details
    note

    You can skip Pulumi previews with the -s or --skip-preview arg or still see the preview but automatically accept it with -y or --yes.

  9. The deployment will be finished when the output stops changing and you see the final output similar to the below:

    Outputs:
    k8sId: "Local Deployment"

    Resources:
    + 32 created

    Duration: 2m8s

Testing

Testing with a local Kubernetes deployment is very similar to testing without Kubernetes. The Unreal client tries to connect to the Director Frontend at ws://localhost:3001, so all you need to do is forward the port from within Rancher Desktop.

Port Forwarding Tab

Port Forwarding for Director Frontend

Deploying to the Cloud

success

You now have a local Kubernetes cluster that hosts the same microservices that get deployed a production environment on the cloud. Most of your development and testing will be done locally, but it's important to test deploying to the cloud well before it's time to release your game.

Whenever you're ready to test deploying to the cloud, you can read more about it here.