Documentation
¶
Index ¶
- Constants
- Variables
- func GetNodeDetails(ctx context.Context, r client.Reader, nodeName string) (string, string, int, error)
- func IsNodeReadyAndSchedulable(node *corev1.Node) bool
- func NewGameServerForGameServerBuild(gsb *mpsv1alpha1.GameServerBuild, portRegistry *PortRegistry) (*mpsv1alpha1.GameServer, error)
- func NewPodForGameServer(gs *mpsv1alpha1.GameServer) *corev1.Pod
- type AllocateArgs
- type AllocationApiServer
- type GameServerBuildReconciler
- type GameServerForQueue
- type GameServerQueue
- func (h GameServerQueue) Len() int
- func (h GameServerQueue) Less(i, j int) bool
- func (h *GameServerQueue) Pop() interface{}
- func (h *GameServerQueue) PopFromQueue() *GameServerForQueue
- func (h *GameServerQueue) Push(x interface{})
- func (h *GameServerQueue) PushToQueue(gs *GameServerForQueue)
- func (h GameServerQueue) Swap(i, j int)
- type GameServerQueueForBuild
- type GameServerReconciler
- type GameServersQueue
- type MutexMap
- type PortRegistry
- type RequestMultiplayerServerResponse
Constants ¶
const ( InitContainerName = "initcontainer" GameServerKind = "GameServer" GameServerBuildKind = "GameServerBuild" DataVolumeName = "gsdkdata" DataVolumeMountPath = "/gsdkdata" DataVolumeMountPathWin = "c:\\gsdkdata" RandStringSize = 5 LabelBuildID = "BuildID" LabelBuildName = "BuildName" LabelOwningGameServer = "OwningGameServer" LabelOwningOperator = "OwningOperator" LabelNodeName = "NodeName" GsdkConfigFile = DataVolumeMountPath + "/Config/gsdkConfig.json" LogDirectory = DataVolumeMountPath + "/GameLogs/" CertificatesDirectory = DataVolumeMountPath + "/GameCertificates" GsdkConfigFileWin = DataVolumeMountPathWin + "\\Config\\gsdkConfig.json" LogDirectoryWin = DataVolumeMountPathWin + "\\GameLogs\\" CertificatesDirectoryWin = DataVolumeMountPathWin + "\\GameCertificates" DaemonSetPort int32 = 56001 LabelGameServerNode string = "mps.playfab.com/gameservernode" )
const ( ActiveServerStatus = "active" StandingByServerStatus = "standingby" InitializingServerStatus = "initializing" PendingServerStatus = "pending" )
const SafeToEvictPodAttribute string = "cluster-autoscaler.kubernetes.io/safe-to-evict"
Variables ¶
var ( GameServersCreatedCounter = registry.NewCounterVec( prometheus.CounterOpts{ Namespace: "thundernetes", Name: "gameservers_created_total", Help: "Number of GameServers created", }, []string{"BuildName"}, ) GameServersSessionEndedCounter = registry.NewCounterVec( prometheus.CounterOpts{ Namespace: "thundernetes", Name: "gameservers_sessionended_total", Help: "Number of GameServer sessions ended", }, []string{"BuildName"}, ) GameServersCrashedCounter = registry.NewCounterVec( prometheus.CounterOpts{ Namespace: "thundernetes", Name: "gameservers_crashed_total", Help: "Number of GameServers sessions crashed", }, []string{"BuildName"}, ) GameServersDeletedCounter = registry.NewCounterVec( prometheus.CounterOpts{ Namespace: "thundernetes", Name: "gameservers_deleted_total", Help: "Number of GameServers deleted", }, []string{"BuildName"}, ) CurrentGameServerGauge = registry.NewGaugeVec( prometheus.GaugeOpts{ Namespace: "thundernetes", Name: "gameservers_current_state_per_build", Help: "Gameserver gauges by state per build", }, []string{"BuildName", "state"}, ) AllocationsCounter = registry.NewCounterVec( prometheus.CounterOpts{ Namespace: "thundernetes", Name: "allocations_total", Help: "Number of GameServers allocations", }, []string{"BuildName"}, ) )
var InitContainerImage string
var InitContainerImageWin string
Functions ¶
func GetNodeDetails ¶ added in v0.4.0
func GetNodeDetails(ctx context.Context, r client.Reader, nodeName string) (string, string, int, error)
GetNodeDetails returns the Public IP of the node and the node age in days if the Node does not have a Public IP, method returns the internal one
func IsNodeReadyAndSchedulable ¶ added in v0.3.0
IsNodeReadyAndSchedulable returns true if the node is ready and schedulable
func NewGameServerForGameServerBuild ¶
func NewGameServerForGameServerBuild(gsb *mpsv1alpha1.GameServerBuild, portRegistry *PortRegistry) (*mpsv1alpha1.GameServer, error)
NewGameServerForGameServerBuild creates a GameServer for a GameServerBuild
func NewPodForGameServer ¶
func NewPodForGameServer(gs *mpsv1alpha1.GameServer) *corev1.Pod
NewPodForGameServer returns a Kubernetes Pod struct for a specified GameServer Pod has the same name as the GameServer It also sets a label called "GameServer" with the value of the corresponding GameServer resource
Types ¶
type AllocateArgs ¶ added in v0.4.0
type AllocateArgs struct { SessionID string `json:"sessionID"` BuildID string `json:"buildID"` SessionCookie string `json:"sessionCookie"` InitialPlayers []string `json:"initialPlayers"` }
AllocateArgs contains information necessary to allocate a GameServer
type AllocationApiServer ¶ added in v0.4.0
type AllocationApiServer struct { Client client.Client // CrtBytes is the PEM-encoded certificate CrtBytes []byte // KeyBytes is the PEM-encoded key KeyBytes []byte // contains filtered or unexported fields }
AllocationApiServer is a helper struct that implements manager.Runnable interface so it can be added to our Manager
func NewAllocationApiServer ¶ added in v0.4.0
func NewAllocationApiServer(crt, key []byte, cl client.Client) *AllocationApiServer
func (*AllocationApiServer) Reconcile ¶ added in v0.4.0
Reconcile gets triggered when there is a change on a game server object
func (*AllocationApiServer) SetupWithManager ¶ added in v0.4.0
func (s *AllocationApiServer) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the allocation api controller with the manager
func (*AllocationApiServer) Start ¶ added in v0.4.0
func (s *AllocationApiServer) Start(ctx context.Context) error
Start starts the HTTP(S) allocation API service if user has provided public/private cert details, it will create a TLS-auth HTTPS server otherwise it will create a HTTP server with no auth
type GameServerBuildReconciler ¶
type GameServerBuildReconciler struct { client.Client Scheme *runtime.Scheme PortRegistry *PortRegistry Recorder record.EventRecorder }
GameServerBuildReconciler reconciles a GameServerBuild object
func (*GameServerBuildReconciler) Reconcile ¶
func (r *GameServerBuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile is part of the main kubernetes reconciliation loop which aims to move the current state of the cluster closer to the desired state. For more details, check Reconcile and its Result here: - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile
func (*GameServerBuildReconciler) SetupWithManager ¶
func (r *GameServerBuildReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type GameServerForQueue ¶ added in v0.4.0
type GameServerForQueue struct { Name string Namespace string BuildID string NodeAge int ResourceVersion string }
GameServerForQueue is a helper struct that encapsulates all the details we need from a GameServer object in order to store it on the queue
type GameServerQueue ¶ added in v0.4.0
type GameServerQueue []*GameServerForQueue
GameServerQueue implements a PriorityQueue for GameServer objects GameServers are sorted in the queue in ascending order based on the NodeAge field this queue is used by the allocation algorithm, to prioritize allocations on the Nodes that are newer based on https://pkg.go.dev/container/heap
func (GameServerQueue) Len ¶ added in v0.4.0
func (h GameServerQueue) Len() int
Len returns the number of elements in the heap
func (GameServerQueue) Less ¶ added in v0.4.0
func (h GameServerQueue) Less(i, j int) bool
Less returns true if the GameServerForHeap with index i is in a newer Node (smaller NodeAge) compared to the GameServerForHeap with index j
func (*GameServerQueue) Pop ¶ added in v0.4.0
func (h *GameServerQueue) Pop() interface{}
Pop pops the top interface{} element off the heap this is written just to help implement the heap interface PopFromQueue should be used instead
func (*GameServerQueue) PopFromQueue ¶ added in v0.4.0
func (h *GameServerQueue) PopFromQueue() *GameServerForQueue
PopFromQueue pops the top GameServerForHeap off the heap It should be used instead of heap.Pop
func (*GameServerQueue) Push ¶ added in v0.4.0
func (h *GameServerQueue) Push(x interface{})
Push pushes a interface{} element onto the heap this is written just to help implement the heap interface PopFromQueue should be used instead
func (*GameServerQueue) PushToQueue ¶ added in v0.4.0
func (h *GameServerQueue) PushToQueue(gs *GameServerForQueue)
PushToQueue pushes a GameServerForHeap onto the heap It should be used instead of heap.Push
func (GameServerQueue) Swap ¶ added in v0.4.0
func (h GameServerQueue) Swap(i, j int)
Swap swaps the GameServerForHeap with index i and the GameServerForHeap with index j
type GameServerQueueForBuild ¶ added in v0.4.0
type GameServerQueueForBuild struct {
// contains filtered or unexported fields
}
GameServerQueueForBuild encapsulates a queue of GameServerForQueue for a specific GameServerBuild also contains a map of all the GameServers for that GameServerBuild
func NewGameServersPerBuildQueue ¶ added in v0.4.0
func NewGameServersPerBuildQueue() *GameServerQueueForBuild
NewGameServersPerBuildQueue returns a new priority queue for a single GameServerBuild
func (*GameServerQueueForBuild) PopFromQueue ¶ added in v0.4.0
func (gsqb *GameServerQueueForBuild) PopFromQueue() *GameServerForQueue
PopFromQueue pops the top GameServerForQueue off the queue
func (*GameServerQueueForBuild) PushToQueue ¶ added in v0.4.0
func (gsqb *GameServerQueueForBuild) PushToQueue(gs *GameServerForQueue)
PushToQueue pushes a GameServerForQueue onto the queue
func (*GameServerQueueForBuild) RemoveFromQueue ¶ added in v0.4.0
func (gsqb *GameServerQueueForBuild) RemoveFromQueue(namespace, name string)
RemoveFromQueue removes a GameServer from the queue based on the provided namespace/name tuple
type GameServerReconciler ¶
type GameServerReconciler struct { client.Client Scheme *runtime.Scheme Recorder record.EventRecorder PortRegistry *PortRegistry GetNodeDetailsProvider func(ctx context.Context, r client.Reader, nodeName string) (string, string, int, error) // we abstract this for testing purposes }
GameServerReconciler reconciles a GameServer object
func (*GameServerReconciler) Reconcile ¶
func (r *GameServerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile is part of the main kubernetes reconciliation loop which aims to move the current state of the cluster closer to the desired state. For more details, check Reconcile and its Result here: - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile
func (*GameServerReconciler) SetupWithManager ¶
func (r *GameServerReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type GameServersQueue ¶ added in v0.4.0
type GameServersQueue struct {
// contains filtered or unexported fields
}
GameServersQueue encapsulates a map of GameServersPerBuildHeaps essentially a set of PriorityQueues, one for each GameServerBuild
func NewGameServersQueue ¶ added in v0.4.0
func NewGameServersQueue() *GameServersQueue
NewGameServersQueue returns a new GameServersQueue
func (*GameServersQueue) PopFromQueue ¶ added in v0.4.0
func (gsq *GameServersQueue) PopFromQueue(buildID string) *GameServerForQueue
PopFromQueue pops the top GameServerForHeap off the queue
func (*GameServersQueue) PushToQueue ¶ added in v0.4.0
func (gsq *GameServersQueue) PushToQueue(gs *GameServerForQueue)
PushToQueue pushes a GameServerForQueue onto the queue
func (*GameServersQueue) RemoveFromQueue ¶ added in v0.4.0
func (gsq *GameServersQueue) RemoveFromQueue(namespace, name string)
RemoveFromQueue removes a GameServer from the queue based on the provided namespace/name tuple
type MutexMap ¶ added in v0.4.0
type MutexMap struct {
// contains filtered or unexported fields
}
Simple async map implementation using a mutex used to manage the expected GameServer creations and deletions
type PortRegistry ¶
type PortRegistry struct { NodeCount int // the number of Ready and Schedulable nodes in the cluster HostPortsPerNode map[int32]int // a slice for the entire port range. increases by 1 for each registered port Min int32 // Minimum Port Max int32 // Maximum Port // contains filtered or unexported fields }
PortRegistry implements a custom map for the port registry
func NewPortRegistry ¶
func NewPortRegistry(client client.Client, gameServers *mpsv1alpha1.GameServerList, min, max int32, nodeCount int, useSpecificNodePool bool, setupLog logr.Logger) (*PortRegistry, error)
NewPortRegistry initializes the map[port]counter that holds the port registry The way that this works is the following: We keep a map (HostPortsPerNode) of all the port numbers every time a new port is requested, we check if the counter for this port is less than the number of Nodes if it is, we increase it by one. If not, we check the next port. the nextPortNumber facilitates getting the next port (port+1), since getting the same port again would cause the GameServer Pod to be placed on a different Node, to avoid collision. This would have a negative impact in cases where we want as many GameServers as possible on the same Node. We also set up a Kubernetes Watch for the Nodes When a new Node is added or removed to the cluster, we modify the NodeCount variable
func (*PortRegistry) DeregisterServerPorts ¶
func (pr *PortRegistry) DeregisterServerPorts(ports []int32) error
DeregisterServerPorts deregisters all host ports so they can be re-used by additional game servers
func (*PortRegistry) GetNewPort ¶
func (pr *PortRegistry) GetNewPort() (int32, error)
GetNewPort returns and registers a new port for the designated game server One may wonder what happens if two GameServer Pods get assigned the same HostPort The answer is that we will not have a collision, since Kubernetes is pretty smart and will place the Pod on a different Node, to prevent it
func (*PortRegistry) Reconcile ¶ added in v0.3.0
Reconcile runs when a Node is created/deleted or the node status changes
func (*PortRegistry) SetupWithManager ¶ added in v0.3.0
func (pr *PortRegistry) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager registers the PortRegistry controller with the manager we care to watch for changes in the Node objects, only if they are "Ready" and "Schedulable"
type RequestMultiplayerServerResponse ¶ added in v0.4.0
RequestMultiplayerServerResponse contains details that are returned on a successful GameServer allocation call