controllers

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2022 License: Apache-2.0 Imports: 42 Imported by: 0

Documentation

Index

Constants

View Source
const (
	InitContainerName = "initcontainer"

	GameServerKind      = "GameServer"
	GameServerBuildKind = "GameServerBuild"

	DataVolumeName         = "gsdkdata"
	DataVolumeMountPath    = "/gsdkdata"
	DataVolumeMountPathWin = "c:\\gsdkdata"
	RandStringSize         = 5

	LabelBuildID          = "BuildID"
	LabelBuildName        = "BuildName"
	LabelOwningGameServer = "mps.playfab.com/OwningGameServer"
	LabelOwningOperator   = "mps.playfab.com/OwningOperator"
	LabelNodeName         = "NodeName"

	GsdkConfigFile    = DataVolumeMountPath + "/Config/gsdkConfig.json"
	GsdkConfigFileWin = DataVolumeMountPathWin + "\\Config\\gsdkConfig.json"

	LogDirectory    = DataVolumeMountPath + "/GameLogs/"
	LogDirectoryWin = DataVolumeMountPathWin + "\\GameLogs\\"

	CertificatesDirectory    = DataVolumeMountPath + "/GameCertificates"
	CertificatesDirectoryWin = DataVolumeMountPathWin + "\\GameCertificates"

	GameSharedContentDirectory    = DataVolumeMountPath + "/GameSharedContent"
	GameSharedContentDirectoryWin = DataVolumeMountPathWin + "\\GameSharedContent"

	DaemonSetPort int32 = 56001

	LabelGameServerNode string = "mps.playfab.com/gameservernode"
)
View Source
const (
	ActiveServerStatus       = "active"
	StandingByServerStatus   = "standingby"
	InitializingServerStatus = "initializing"
	PendingServerStatus      = "pending"
)
View Source
const SafeToEvictPodAttribute string = "cluster-autoscaler.kubernetes.io/safe-to-evict"

Variables

View Source
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 crashed",
		},
		[]string{"BuildName"},
	)
	GameServersUnhealthyCounter = registry.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "thundernetes",
			Name:      "gameservers_unhealthy_total",
			Help:      "Number of GameServers marked as Unhealthy",
		},
		[]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"},
	)
	AllocationsTimeTakenDuration = registry.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: "thundernetes",
			Name:      "allocations_time_taken_duration",
			Help:      "Average time it took to allocate a GameServer",
		},
		[]string{"BuildName"},
	)
	AllocationsRetriesCounter = registry.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "thundernetes",
			Name:      "allocations_retried",
			Help:      "The number of times allocation had to be retried",
		},
		[]string{"BuildName"},
	)
	Allocations429ErrorsCounter = registry.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "thundernetes",
			Name:      "allocations_429",
			Help:      "The number of 429 (too many requests) errors during allocation",
		},
		[]string{"BuildName"},
	)
	Allocations404ErrorsCounter = registry.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "thundernetes",
			Name:      "allocations_404",
			Help:      "The number of 404 (not found) errors during allocation",
		},
		[]string{"BuildName"},
	)
	Allocations500ErrorsCounter = registry.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "thundernetes",
			Name:      "allocations_500",
			Help:      "The number of 500 (internal) errors during allocation",
		},
		[]string{"BuildName"},
	)
	Allocations409ErrorsCounter = registry.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "thundernetes",
			Name:      "allocations_409",
			Help:      "The number of 409 (request conflict) errors during allocation",
		},
		[]string{"BuildName"},
	)
)

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

func IsNodeReadyAndSchedulable(node *corev1.Node) bool

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, initContainerImageLinux, initContainerImageWin string) *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, port int32) *AllocationApiServer

func (*AllocationApiServer) Reconcile added in v0.4.0

func (s *AllocationApiServer) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)

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 ByState added in v0.5.0

type ByState []mpsv1alpha1.GameServer

ByState is a slice of GameServers

func (ByState) Len added in v0.5.0

func (gs ByState) Len() int

Len is the number of elements in the collection

func (ByState) Less added in v0.5.0

func (gs ByState) Less(i, j int) bool

Less helps sort the GameServer slice by the following order first are the Initializing GameServers and then the StandingBy everything else goes last

func (ByState) Swap added in v0.5.0

func (gs ByState) Swap(i, j int)

Swap swaps the elements at the passed indexes

type GameServerBuildReconciler

type GameServerBuildReconciler struct {
	client.Client
	Scheme       *k8sruntime.Scheme
	PortRegistry *PortRegistry
	Recorder     record.EventRecorder
	// contains filtered or unexported fields
}

GameServerBuildReconciler reconciles a GameServerBuild object

func NewGameServerBuildReconciler added in v0.6.0

func NewGameServerBuildReconciler(mgr manager.Manager, portRegistry *PortRegistry) *GameServerBuildReconciler

NewGameServerBuildReconciler returns a pointer to a new GameServerBuildReconciler

func (*GameServerBuildReconciler) Reconcile

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 GameServerExpectations added in v0.6.0

type GameServerExpectations struct {
	// contains filtered or unexported fields
}

func NewGameServerExpectations added in v0.6.0

func NewGameServerExpectations(c client.Reader) *GameServerExpectations

NewGameServerExpectations returns a pointer to a new GameServerExpectations struct

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                  *k8sruntime.Scheme
	Recorder                record.EventRecorder
	PortRegistry            *PortRegistry
	InitContainerImageLinux string
	InitContainerImageWin   string
	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 NewGameServerReconciler added in v0.6.0

func NewGameServerReconciler(mgr manager.Manager,
	portRegistry *PortRegistry,
	getNodeDetailsProvider func(ctx context.Context, r client.Reader, nodeName string) (string, string, int, error),
	initContainerImageLinux string,
	initContainerImageWin string) *GameServerReconciler

NewGameServerReconciler returns a pointer to a new GameServerReconciler

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 {
	HostPortsUsage         map[int32]int      // Number of times each HostPort in the [Min,Max] range is used
	HostPortsPerGameServer map[string][]int32 // Map of GameServer namespace/names to the list of ports that are assigned to it
	NodeCount              int                // the number of Ready and Schedulable nodes in the cluster
	Min                    int32              // Minimum Port
	Max                    int32              // Maximum Port
	FreePortsCount         int                // the number of free ports. Originally it equals [Min,Max] * NodeCount
	// 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 (HostPortsUsage) 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 so that when a new Node is added or removed to the cluster, we modify the NodeCount variable

func (*PortRegistry) DeregisterPorts added in v0.6.0

func (pr *PortRegistry) DeregisterPorts(namespace, name string) ([]int32, error)

DeregisterPorts deregisters all host ports so they can be re-used by additional game servers

func (*PortRegistry) GetNewPorts added in v0.6.0

func (pr *PortRegistry) GetNewPorts(namespace, name string, count int) ([]int32, error)

GetNewPorts returns and registers a slice of ports with "count" length that will be used by a GameServer It returns an error if there are no available ports You may wonder what happens if two GameServer Pods get assigned the same HostPort 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

func (pr *PortRegistry) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)

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

type RequestMultiplayerServerResponse struct {
	IPV4Address string
	Ports       string
	SessionID   string
}

RequestMultiplayerServerResponse contains details that are returned on a successful GameServer allocation call

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL