Scheduler
What is
Objectively, a Scheduler is a recipe, and contains all the information for creating game rooms and forwarding rooms information to other services.
Also, it's the core entity for operating game rooms in Maestro, since all game rooms are related to a specific scheduler.
A game can have multiple schedulers, and each scheduler can have multiple game rooms up and running.
How to Operate
To directly interact with a Scheduler, the user enqueues operations using the management API.
These operations are responsible for creating a scheduler or newer versions, switching an active version, adding/removing rooms, etc.
Because of that, everything that happens for a Scheduler can be tracked based on history of the operations executed for that scheduler and the order they were executed.
Versions
A Scheduler have versions, and each time we want to change scheduler properties, we end-up creating a new version to it.
Versions are directly calculated by Maestro, not sent by the client.
The client can only switch the active version based on the versions created by Maestro. To switch to an specific version, see this.
This version can either be a Minor or a Major change.
- Major version: Replace the game rooms in a switch active version event.
- Basically, any change under spec, that are related to the game room directly.
- Minor version: Don't replace game rooms in a switch active version event.
- Info such as MaxSurge or forwarders, that do not impact the game rooms.
Example
A complete Scheduler looks like this:
YAML
name: scheduler-test
game: game-test
state: creating
portRange:
start: 40000
end: 60000
maxSurge: 30%
spec:
terminationGracePeriod: '100s'
containers:
- name: alpine
image: alpine
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- '-c'
- >-
apk add curl && while true; do curl --request POST
{{maestro-rooms-api}}/scheduler/$MAESTRO_SCHEDULER_NAME/rooms/$MAESTRO_ROOM_ID/ping
--data-raw '{"status": "ready","timestamp": "12312312313"}' && sleep
1; done
environment:
- name: env-var-name
value: env-var-value
- name: env-var-field-ref
valueFrom:
fieldRef:
fieldPath: path
- name: secret-var-name
valueFrom:
secretKeyRef:
name: secret-name
key: secret-key
requests:
memory: 20Mi
cpu: 100m
limits:
memory: 200Mi
cpu: 200m
ports:
- name: port-name
protocol: tcp
port: 12345
toleration: maestro
affinity: maestro-dedicated
forwarders:
- name: test
enable: true
type: gRPC
address: {{host}}
options:
timeout: '1000'
metadata: {}
autoscaling:
enabled: true
min: 1
max: 10
policy:
type: roomOccupancy
parameters:
...
// Will vary according to the policy type.
JSON
{ "name": "scheduler-test", "game": "game-test", "portRange": { "start": 40000, "end": 60000 }, "annotations":{ "imageregistry":"https://dockerhub.com/" }, "maxSurge": "30%", "spec": { "terminationGracePeriod": '100s', "containers": [ { "name": "alpine", "image": "alpine", "imagePullPolicy": "IfNotPresent", "command": [ "/bin/sh", "-c", "apk add curl && while true; do curl --request POST {{maestro-rooms-api}}/scheduler/$MAESTRO_SCHEDULER_NAME/rooms/$MAESTRO_ROOM_ID/ping --data-raw '{"status": "ready","timestamp": "12312312313"}' && sleep 1; done" ], "environment": [ { "name": "env-var-name", "value": env-var-value }, { "name": "env-var-field-ref", "valueFrom": { "fieldRef": { "fieldPath": "path" } } }, { "name": "secret-var-name", "valueFrom": { "secretKeyRef": { "name": "secret-name", "key": "secret-key" } } } ], "requests": { "memory": "20Mi", "cpu": "100m" }, "limits": { "memory": "200Mi", "cpu": "200m" }, "ports": [ { "name": "port-name", "protocol": "tcp", "port": 12345, } ] } ], "toleration": "maestro", "affinity": "maestro-dedicated" }, "forwarders": [ { "name": "test", "enable": true, "type": "gRPC", "address": "{{host}}", "options": { "timeout": '1000', "metadata": {} } } ] "autoscaling": { "enabled": true, "min": 10, "max": 300, "policy": { "type": "roomOccupancy", "parameters": { ... // Will vary according to the policy type. } } } }
Structure
The scheduler is represented as:
name: String
game: String
createdAt: Timestamp
maxSurge: String | Integer
portRange: PortRange
forwarders: Forwarders
autoscaling: Autoscaling
spec: Spec
annotation: Map
- Name: Scheduler name. This name is unique and will be the same name used for the kubernetes namespace. It's offered by the user in the creation and cannot be changed in the future. It's used as an ID for the scheduler;
- game: Name of the game which will use the scheduler. The game is important since it's common to use multiple schedulers for a specific game. So you probably will want to fetch all the schedulers from a game;
- createdAt: Info about the scheduler creation time. Cannot be altered by the user;
- maxSurge: Value represented in percentage (%) or Integer. Offered by the user on the scheduler creation. Can be altered anytime. Used by Maestro to replace pods. Ex: If maxSurge = 3, the Switch Active Version (Major change) operation will replace pods from 3 to 3;
- portRange: Range of ports that can be used by Maestro to create GRUs for the specified scheduler. Can be altered by the user anytime. More info here; Mutually exclusive with the Spec.Containers.Ports.HostPortRange configuration.
- forwarders: Maestro can pass ahead info sent by the game rooms, such as Ping (Ready, Occupied, Terminating...), player and rooms events. The receivers can be configured here. More info here;
- autoscaling: Optional autoscaling policy configuration. More info here;
- spec: Specifications about the game rooms managed by the scheduler, such as containers and environment variables used by them, limits and images. More info here.
- annotations: Allows annotations for the scheduler's game room. Know more about annotations on Kubernetes here
PortRange
The PortRange is used to select a random port for a GRU between start and end.
- PortRange cannot be null or empty
Check if the ports offered are available and can be used. A firewall rule, for example, can affect the connection to the Game Room in the specific port.
It is represented as:
start: Integer
end: Integer
You must configure the port range either in .PortRange
or in .Spec.Containers.Ports.HostPortRange
- they are mutually exclusive configurations. If you want to configure a single port range for all container ports, use .PortRange
, otherwise use HostPortRange
in every Spec to configure the port range for each one - this is useful when avoiding port conflicts on different protocols in case the network doesn't support it, for example.
Forwarders
Forwarders are configured to pass ahead info offered by the game rooms to Maestro. More than one forwarder can be configured for a scheduler.
- Can be an empty list.
It is represented as:
- name: String
enable: Bool
type: String
address: String
options:
timeout: Integer
metadata: Object
- name: Name of the forwarder. Used only for reference (visibility and recognition);
- enable: Toggle to easily enable/disable the forwarder;
- type: Type of the forwarder. Right now, only accepts gRPC;
- address: Address used by the scheduler to forward events. E.g. 'api.example.com:8080';
- options: Optional parameters.
- timeout: Timeout value for an event to successfully be forwarded;
- metadata: Object that can contain any useful information for the game team. Will be forwarded with the events from Maestro.
Spec
Contains vital information about the game rooms. Be aware that the spec is the most related aspect of the scheduler interacting with the runtime. It might be important to understand the basics of kubernetes before deep diving into the Maestro scheduler itself.
- Cannot be empty or null.
It is represented as:
terminationGracePeriod: String
containers: Containers
toleration: String
affinity: String
- terminationGracePeriod: Required string value. Must be greater than 0 and have the unit set, i.e "100s". When a game room receives the signal to be deleted, it will take this value (in seconds) to be completely deleted;
- containers: Contain the information about the game room, such as the image and environment variables. This is a list since the game room can be compounded by more than two containers;
- toleration: Kubernetes specific. Represents the toleration value for all GRUs on the scheduler. See more;
- affinity: Kubernetes specific. Represents the affinity value for all GRUs on the scheduler. See more.
Containers
Contain the information about the game room, such as the image and environment variables.
- Cannot be an empty list.
It is represented as:
- name: String
image: String
imagePullPolicy: String
command: Array<String>
environment: EnvironemntVariables
requests:
memory: String
cpu: String
limits:
memory: String
cpu: String
ports: Ports
- name: Name of the container, used only for reference and can be changed by the user anytime.
- image: Docker image to be used for the container. Represented as a link.
- imagePullPolicy: Kubernetes specific. See here for reference.
- command: List of commands that should be executed by the image on execution. E.g. here.
- environment: List of environment variables. See here.
- requests and limits: Kubernetes specific. See here.
- ports: The list of ports your game server exposes. See here.
Environment Variables
List of environment variables used by the GRU.
- Can be an empty list.
There are, now, 3 supported formats by Maestro:
- Simple name-value format.
With Name/Value
- name: String
value: String
- Exposing pod fields (kubernetes specific). See here.
With FieldRef/FieldPath
- name: String
valueFrom:
fieldRef:
fieldPath: String
- Secrets as environment variables (kubernetes specific). See here.
With Secret
- name: String
valueFrom:
secretKeyRef:
name: String
key: String
Ports
The list of ports your game server exposes.
- Can be an empty list.
It is represented as:
- name: String
protocol: String
port: Integer
hostPortRange: PortRange
- name: Name of the port. Facilitates on recognition;
- protocol: Port protocol. Can be UDP, TCP or SCTP.;
- port: The port exposed.
- hostPortRange: The port range for the port to be allocated in the host. Mutually exclusive with the port range configured in the root structure.