diff --git a/install/helm/agones/templates/crds/_gameserverspecschema.yaml b/install/helm/agones/templates/crds/_gameserverspecschema.yaml index 09c1131e9f..03cd5db3fe 100644 --- a/install/helm/agones/templates/crds/_gameserverspecschema.yaml +++ b/install/helm/agones/templates/crds/_gameserverspecschema.yaml @@ -154,6 +154,21 @@ properties: title: The initial player capacity of this Game Server minimum: 0 {{- if .featureSafeToEvict }} + eviction: + type: object + title: Eviction tolerance of the game server + properties: + safe: + type: string + title: Game server supports termination via SIGTERM + description: | + - Never: The game server should run to completion. Agones sets Pod annotation `cluster-autoscaler.kubernetes.io/safe-to-evict: "false"` and label `agones.dev/safe-to-evict: "false"`, which matches a restrictive PodDisruptionBudget. + - OnUpgrade: On SIGTERM, the game server will exit within `terminationGracePeriodSeconds` or be terminated; Agones sets Pod annotation `cluster-autoscaler.kubernetes.io/safe-to-evict: "false"`, which blocks evictions by Cluster Autoscaler. Evictions from node upgrades proceed normally. + - Always: On SIGTERM, the game server will exit within `terminationGracePeriodSeconds` or be terminated, typically within 10m; Agones sets Pod annotation `cluster-autoscaler.kubernetes.io/safe-to-evict: "true"`, which allows evictions by Cluster Autoscaler. + enum: + - Always + - OnUpgrade + - Never immutableReplicas: type: integer title: Immutable count of Pods to a GameServer. Always 1. (Implementation detail of implementing the Scale subresource.) diff --git a/install/helm/agones/templates/crds/_gameserverstatus.yaml b/install/helm/agones/templates/crds/_gameserverstatus.yaml index 3d77aced52..f15f0db753 100644 --- a/install/helm/agones/templates/crds/_gameserverstatus.yaml +++ b/install/helm/agones/templates/crds/_gameserverstatus.yaml @@ -66,6 +66,15 @@ status: items: type: string {{- if .featureSafeToEvict }} + eviction: + type: object + properties: + safe: + type: string + enum: + - Always + - OnUpgrade + - Never immutableReplicas: type: integer title: Immutable count of Pods to a GameServer. Always 1. (Implementation detail of implementing the Scale subresource.) diff --git a/pkg/apis/agones/v1/apihooks.go b/pkg/apis/agones/v1/apihooks.go index 04bad0e75b..5bb65d9203 100644 --- a/pkg/apis/agones/v1/apihooks.go +++ b/pkg/apis/agones/v1/apihooks.go @@ -15,6 +15,8 @@ package v1 import ( + "agones.dev/agones/pkg/util/runtime" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -28,6 +30,9 @@ type APIHooks interface { // MutateGameServerPodSpec is called by createGameServerPod to allow for product specific pod mutation. MutateGameServerPodSpec(*GameServerSpec, *corev1.PodSpec) error + + // SetEviction is called by gs.Pod to enforce GameServer.Status.Eviction. + SetEviction(EvictionSafe, *corev1.Pod) error } var apiHooks APIHooks = generic{} @@ -45,3 +50,37 @@ type generic struct{} func (generic) ValidateGameServerSpec(*GameServerSpec) []metav1.StatusCause { return nil } func (generic) MutateGameServerPodSpec(*GameServerSpec, *corev1.PodSpec) error { return nil } + +// SetEviction sets disruptions controls based on GameServer.Status.Eviction. +func (generic) SetEviction(safe EvictionSafe, pod *corev1.Pod) error { + if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) { + return nil + } + if _, exists := pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation]; !exists { + switch safe { + case EvictionSafeAlways: + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = True + case EvictionSafeOnUpgrade, EvictionSafeNever: + // For EvictionSafeOnUpgrade and EvictionSafeNever, we block Cluster Autoscaler. + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = False + default: + return errors.Errorf("unknown eviction.safe value %q", string(safe)) + } + } + if _, exists := pod.ObjectMeta.Labels[SafeToEvictLabel]; !exists { + switch safe { + case EvictionSafeAlways, EvictionSafeOnUpgrade: + // For EvictionSafeAlways and EvictionSafeOnUpgrade, we use a label value + // that does not match the agones-gameserver-safe-to-evict-false PDB. But + // we go ahead and label it, in case someone wants to adopt custom logic + // for this group of game servers. + pod.ObjectMeta.Labels[SafeToEvictLabel] = True + case EvictionSafeNever: + // For EvictionSafeNever, match gones-gameserver-safe-to-evict-false PDB. + pod.ObjectMeta.Labels[SafeToEvictLabel] = False + default: + return errors.Errorf("unknown eviction.safe value %q", string(safe)) + } + } + return nil +} diff --git a/pkg/apis/agones/v1/apihooks_test.go b/pkg/apis/agones/v1/apihooks_test.go new file mode 100644 index 0000000000..ef89b1730b --- /dev/null +++ b/pkg/apis/agones/v1/apihooks_test.go @@ -0,0 +1,123 @@ +// Copyright 2022 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "testing" + + "agones.dev/agones/pkg/util/runtime" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestSetEviction(t *testing.T) { + runtime.FeatureTestMutex.Lock() + defer runtime.FeatureTestMutex.Unlock() + + emptyPodAnd := func(f func(*corev1.Pod)) *corev1.Pod { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{}, + Labels: map[string]string{}, + }, + } + f(pod) + return pod + } + for desc, tc := range map[string]struct { + featureFlags string + safeToEvict EvictionSafe + pod *corev1.Pod + wantPod *corev1.Pod + }{ + "SafeToEvict feature gate disabled => no change": { + featureFlags: "SafeToEvict=false", + // intentionally leave pod nil, it'll crash if anything's touched. + }, + "SafeToEvict: Always, no incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: EvictionSafeAlways, + pod: emptyPodAnd(func(*corev1.Pod) {}), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = True + pod.ObjectMeta.Labels[SafeToEvictLabel] = True + }), + }, + "SafeToEvict: OnUpgrade, no incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: EvictionSafeOnUpgrade, + pod: emptyPodAnd(func(*corev1.Pod) {}), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = False + pod.ObjectMeta.Labels[SafeToEvictLabel] = True + }), + }, + "SafeToEvict: Never, no incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: EvictionSafeNever, + pod: emptyPodAnd(func(*corev1.Pod) {}), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = False + pod.ObjectMeta.Labels[SafeToEvictLabel] = False + }), + }, + "SafeToEvict: Always, incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: EvictionSafeAlways, + pod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "just don't touch, ok?" + pod.ObjectMeta.Labels[SafeToEvictLabel] = "seriously, leave it" + }), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "just don't touch, ok?" + pod.ObjectMeta.Labels[SafeToEvictLabel] = "seriously, leave it" + }), + }, + "SafeToEvict: OnUpgrade, incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: EvictionSafeOnUpgrade, + pod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "better not touch" + pod.ObjectMeta.Labels[SafeToEvictLabel] = "not another one" + }), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "better not touch" + pod.ObjectMeta.Labels[SafeToEvictLabel] = "not another one" + }), + }, + "SafeToEvict: Never, incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: EvictionSafeNever, + pod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "a passthrough" + pod.ObjectMeta.Labels[SafeToEvictLabel] = "or is it passthru?" + }), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "a passthrough" + pod.ObjectMeta.Labels[SafeToEvictLabel] = "or is it passthru?" + }), + }, + } { + t.Run(desc, func(t *testing.T) { + err := runtime.ParseFeatures(tc.featureFlags) + assert.NoError(t, err) + + err = (generic{}).SetEviction(tc.safeToEvict, tc.pod) + assert.NoError(t, err) + assert.Equal(t, tc.wantPod, tc.pod) + }) + } +} diff --git a/pkg/apis/agones/v1/gameserver.go b/pkg/apis/agones/v1/gameserver.go index 80d1d1ca74..3d27ad2670 100644 --- a/pkg/apis/agones/v1/gameserver.go +++ b/pkg/apis/agones/v1/gameserver.go @@ -72,6 +72,16 @@ const ( // This will mean that users will need to lookup what port has been opened through the server side SDK. Passthrough PortPolicy = "Passthrough" + // EvictionSafeAlways means the game server supports termination via SIGTERM, and wants eviction signals + // from Cluster Autoscaler scaledown and node upgrades. + EvictionSafeAlways EvictionSafe = "Always" + // EvictionSafeOnUpgrade means the game server supports termination via SIGTERM, and wants eviction signals + // from node upgrades, but not Cluster Autoscaler scaledown. + EvictionSafeOnUpgrade EvictionSafe = "OnUpgrade" + // EvictionSafeNever means the game server should run to completion and may not understand SIGTERM. Eviction + // from ClusterAutoscaler and upgrades should both be blocked. + EvictionSafeNever EvictionSafe = "Never" + // ProtocolTCPUDP Protocol exposes the hostPort allocated for this container for both TCP and UDP. ProtocolTCPUDP corev1.Protocol = "TCPUDP" @@ -104,6 +114,13 @@ const ( // determine if a pod can safely be evicted to compact a cluster by moving pods between nodes // and scaling down nodes. PodSafeToEvictAnnotation = "cluster-autoscaler.kubernetes.io/safe-to-evict" + // SafeToEvictLabel is a label that, when "false", matches the restrictive PDB agones-gameserver-safe-to-evict-false. + SafeToEvictLabel = agones.GroupName + "/safe-to-evict" + + // True is the string "true" to appease the goconst lint. + True = "true" + // False is the string "false" to appease the goconst lint. + False = "false" ) var ( @@ -162,6 +179,9 @@ type GameServerSpec struct { // (Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features. // +optional Players *PlayersSpec `json:"players,omitempty"` + // (Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer. Defaults to "Never". + // +optional + Eviction Eviction `json:"eviction,omitempty"` // immutableReplicas is present in gameservers.agones.dev but omitted here (it's always 1). } @@ -170,12 +190,25 @@ type PlayersSpec struct { InitialCapacity int64 `json:"initialCapacity,omitempty"` } +// Eviction specifies the eviction tolerance of the GameServer +type Eviction struct { + // (Alpha, SafeToEvict feature flag) + // Game server supports termination via SIGTERM: + // - Always: Allow eviction for both Cluster Autoscaler and node drain for upgrades + // - OnUpgrade: Allow eviction for upgrades alone + // - Never (default): Pod should run to completion + Safe EvictionSafe `json:"safe,omitempty"` +} + // GameServerState is the state for the GameServer type GameServerState string // PortPolicy is the port policy for the GameServer type PortPolicy string +// EvictionSafe specified whether the game server supports termination via SIGTERM +type EvictionSafe string + // Health configures health checking on the GameServer type Health struct { // Disabled is whether health checking is disabled or not @@ -235,6 +268,8 @@ type GameServerStatus struct { // [FeatureFlag:PlayerTracking] // +optional Players *PlayerStatus `json:"players"` + // (Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer. + Eviction Eviction `json:"eviction,omitempty"` // immutableReplicas is present in gameservers.agones.dev but omitted here (it's always 1). } @@ -271,6 +306,7 @@ func (gss *GameServerSpec) ApplyDefaults() { gss.applyContainerDefaults() gss.applyPortDefaults() gss.applyHealthDefaults() + gss.applyEvictionDefaults() gss.applySchedulingDefaults() gss.applySdkServerDefaults() } @@ -330,6 +366,8 @@ func (gs *GameServer) applyStatusDefaults() { gs.Status.Players.Capacity = gs.Spec.Players.InitialCapacity } } + + gs.applyEvictionStatus() } // applyPortDefaults applies default values for all ports @@ -356,6 +394,25 @@ func (gss *GameServerSpec) applySchedulingDefaults() { } } +func (gss *GameServerSpec) applyEvictionDefaults() { + if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) { + return + } + if gss.Eviction.Safe == "" { + gss.Eviction.Safe = EvictionSafeNever + } +} + +func (gs *GameServer) applyEvictionStatus() { + if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) { + return + } + gs.Status.Eviction = gs.Spec.Eviction + if gs.Spec.Template.ObjectMeta.Annotations[PodSafeToEvictAnnotation] == "true" { + gs.Status.Eviction.Safe = EvictionSafeAlways + } +} + // Validate validates the GameServerSpec configuration. // devAddress is a specific IP address used for local Gameservers, for fleets "" is used // If a GameServer Spec is invalid there will be > 0 values in @@ -373,6 +430,16 @@ func (gss *GameServerSpec) Validate(devAddress string) ([]metav1.StatusCause, bo } } + if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) { + if gss.Eviction.Safe != "" { + causes = append(causes, metav1.StatusCause{ + Type: metav1.CauseTypeFieldValueNotSupported, + Field: "eviction.safe", + Message: fmt.Sprintf("Value cannot be set unless feature flag %s is enabled", runtime.FeatureSafeToEvict), + }) + } + } + if devAddress != "" { // verify that the value is a valid IP address. if net.ParseIP(devAddress) == nil { @@ -631,6 +698,9 @@ func (gs *GameServer) Pod(sidecars ...corev1.Container) (*corev1.Pod, error) { if err := apiHooks.MutateGameServerPodSpec(&gs.Spec, &pod.Spec); err != nil { return nil, err } + if err := apiHooks.SetEviction(gs.Status.Eviction.Safe, pod); err != nil { + return nil, err + } return pod, nil } @@ -660,13 +730,16 @@ func (gs *GameServer) podObjectMeta(pod *corev1.Pod) { ref := metav1.NewControllerRef(gs, SchemeGroupVersion.WithKind("GameServer")) pod.ObjectMeta.OwnerReferences = append(pod.ObjectMeta.OwnerReferences, *ref) - // This means that the autoscaler cannot remove the Node that this Pod is on. - // (and evict the Pod in the process). Only set the value if it has not already - // been configured in the pod template (to not override user specified behavior). - // We only set this for packed game servers, under the assumption that if - // game servers are distributed then the cluster autoscaler isn't likely running. - if _, exists := pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation]; !exists && gs.Spec.Scheduling == apis.Packed { - pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "false" + // When SafeToEvict=true, apiHooks.SetEviction manages disruption controls. + if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) { + // This means that the autoscaler cannot remove the Node that this Pod is on. + // (and evict the Pod in the process). Only set the value if it has not already + // been configured in the pod template (to not override user specified behavior). + // We only set this for packed game servers, under the assumption that if + // game servers are distributed then the cluster autoscaler isn't likely running. + if _, exists := pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation]; !exists && gs.Spec.Scheduling == apis.Packed { + pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation] = "false" + } } // Add Agones version into Pod Annotations diff --git a/pkg/apis/agones/v1/gameserver_test.go b/pkg/apis/agones/v1/gameserver_test.go index 01cd27973c..b6f7534f08 100644 --- a/pkg/apis/agones/v1/gameserver_test.go +++ b/pkg/apis/agones/v1/gameserver_test.go @@ -134,7 +134,20 @@ func TestGameServerApplyDefaults(t *testing.T) { ten := int64(10) + defaultGameServerAnd := func(f func(gss *GameServerSpec)) GameServer { + gs := GameServer{ + Spec: GameServerSpec{ + Ports: []GameServerPort{{ContainerPort: 999}}, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{Containers: []corev1.Container{ + {Name: "testing", Image: "testing/image"}, + }}}}, + } + f(&gs.Spec) + return gs + } type expected struct { + container string protocol corev1.Protocol state GameServerState policy PortPolicy @@ -142,6 +155,30 @@ func TestGameServerApplyDefaults(t *testing.T) { scheduling apis.SchedulingStrategy sdkServer SdkServer alphaPlayerCapacity *int64 + evictionSafeSpec EvictionSafe + evictionSafeStatus EvictionSafe + } + wantDefaultAnd := func(f func(e *expected)) expected { + e := expected{ + container: "testing", + protocol: "UDP", + state: GameServerStatePortAllocation, + policy: Dynamic, + scheduling: apis.Packed, + health: Health{ + Disabled: false, + FailureThreshold: 3, + InitialDelaySeconds: 5, + PeriodSeconds: 5, + }, + sdkServer: SdkServer{ + LogLevel: SdkServerLogLevelInfo, + GRPCPort: 9357, + HTTPPort: 9358, + }, + } + f(&e) + return e } data := map[string]struct { gameServer GameServer @@ -150,63 +187,25 @@ func TestGameServerApplyDefaults(t *testing.T) { expected expected }{ "set basic defaults on a very simple gameserver": { + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) {}), + expected: wantDefaultAnd(func(e *expected) {}), + }, + "PlayerTracking=true": { featureFlags: string(runtime.FeaturePlayerTracking) + "=true", - gameServer: GameServer{ - Spec: GameServerSpec{ - Players: &PlayersSpec{InitialCapacity: 10}, - Ports: []GameServerPort{{ContainerPort: 999}}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{ - {Name: "testing", Image: "testing/image"}, - }}}}, - }, - container: "testing", - expected: expected{ - protocol: "UDP", - state: GameServerStatePortAllocation, - policy: Dynamic, - scheduling: apis.Packed, - health: Health{ - Disabled: false, - FailureThreshold: 3, - InitialDelaySeconds: 5, - PeriodSeconds: 5, - }, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelInfo, - GRPCPort: 9357, - HTTPPort: 9358, - }, - alphaPlayerCapacity: &ten, - }, + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Players = &PlayersSpec{InitialCapacity: 10} + }), + expected: wantDefaultAnd(func(e *expected) { + e.alphaPlayerCapacity = &ten + }), }, "defaults on passthrough": { - gameServer: GameServer{ - Spec: GameServerSpec{ - Ports: []GameServerPort{{PortPolicy: Passthrough}}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{ - {Name: "testing", Image: "testing/image"}, - }}}}, - }, - container: "testing", - expected: expected{ - protocol: "UDP", - state: GameServerStatePortAllocation, - policy: Passthrough, - scheduling: apis.Packed, - health: Health{ - Disabled: false, - FailureThreshold: 3, - InitialDelaySeconds: 5, - PeriodSeconds: 5, - }, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelInfo, - GRPCPort: 9357, - HTTPPort: 9358, - }, - }, + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Ports[0].PortPolicy = Passthrough + }), + expected: wantDefaultAnd(func(e *expected) { + e.policy = Passthrough + }), }, "defaults are already set": { gameServer: GameServer{ @@ -235,165 +234,146 @@ func TestGameServerApplyDefaults(t *testing.T) { }, }, Status: GameServerStatus{State: "TestState"}}, - container: "testing2", - expected: expected{ - protocol: "TCP", - state: "TestState", - policy: Static, - scheduling: apis.Packed, - health: Health{ + expected: wantDefaultAnd(func(e *expected) { + e.container = "testing2" + e.protocol = "TCP" + e.state = "TestState" + e.health = Health{ Disabled: false, FailureThreshold: 10, InitialDelaySeconds: 11, PeriodSeconds: 12, - }, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelInfo, - GRPCPort: 9357, - HTTPPort: 9358, - }, - }, + } + }), }, "set basic defaults on static gameserver": { - gameServer: GameServer{ - Spec: GameServerSpec{ - Ports: []GameServerPort{{PortPolicy: Static}}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}}, - }, - container: "testing", - expected: expected{ - protocol: "UDP", - state: GameServerStateCreating, - policy: Static, - scheduling: apis.Packed, - health: Health{ - Disabled: false, - FailureThreshold: 3, - InitialDelaySeconds: 5, - PeriodSeconds: 5, - }, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelInfo, - GRPCPort: 9357, - HTTPPort: 9358, - }, - }, + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Ports[0].PortPolicy = Static + }), + expected: wantDefaultAnd(func(e *expected) { + e.state = GameServerStateCreating + e.policy = Static + }), }, "health is disabled": { - gameServer: GameServer{ - Spec: GameServerSpec{ - Ports: []GameServerPort{{ContainerPort: 999}}, - Health: Health{Disabled: true}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}}, - }, - container: "testing", - expected: expected{ - protocol: "UDP", - state: GameServerStatePortAllocation, - policy: Dynamic, - scheduling: apis.Packed, - health: Health{ - Disabled: true, - }, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelInfo, - GRPCPort: 9357, - HTTPPort: 9358, - }, - }, + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Health = Health{Disabled: true} + }), + expected: wantDefaultAnd(func(e *expected) { + e.health = Health{Disabled: true} + }), }, "convert from legacy single port to multiple": { - gameServer: GameServer{ - Spec: GameServerSpec{ - Ports: []GameServerPort{ - { - ContainerPort: 777, - HostPort: 777, - PortPolicy: Static, - Protocol: corev1.ProtocolTCP, - }, - }, - Health: Health{Disabled: true}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}}, - }, - container: "testing", - expected: expected{ - protocol: corev1.ProtocolTCP, - state: GameServerStateCreating, - policy: Static, - scheduling: apis.Packed, - health: Health{Disabled: true}, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelInfo, - GRPCPort: 9357, - HTTPPort: 9358, - }, - }, + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Ports[0] = GameServerPort{ + ContainerPort: 777, + HostPort: 777, + PortPolicy: Static, + Protocol: corev1.ProtocolTCP, + } + }), + expected: wantDefaultAnd(func(e *expected) { + e.protocol = "TCP" + e.state = GameServerStateCreating + }), }, "set Debug logging level": { - gameServer: GameServer{ - Spec: GameServerSpec{ - Ports: []GameServerPort{{ContainerPort: 999}}, - SdkServer: SdkServer{LogLevel: SdkServerLogLevelDebug}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{ - {Name: "testing", Image: "testing/image"}, - }}}}, - }, - container: "testing", - expected: expected{ - protocol: "UDP", - state: GameServerStatePortAllocation, - policy: Dynamic, - scheduling: apis.Packed, - health: Health{ - Disabled: false, - FailureThreshold: 3, - InitialDelaySeconds: 5, - PeriodSeconds: 5, - }, - sdkServer: SdkServer{ - LogLevel: SdkServerLogLevelDebug, - GRPCPort: 9357, - HTTPPort: 9358, - }, - }, + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.SdkServer = SdkServer{LogLevel: SdkServerLogLevelDebug} + }), + expected: wantDefaultAnd(func(e *expected) { + e.sdkServer.LogLevel = SdkServerLogLevelDebug + }), }, "set gRPC and HTTP ports on SDK Server": { - gameServer: GameServer{ - Spec: GameServerSpec{ - Ports: []GameServerPort{{ContainerPort: 999}}, - SdkServer: SdkServer{ - LogLevel: SdkServerLogLevelError, - GRPCPort: 19357, - HTTPPort: 19358, - }, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{Containers: []corev1.Container{ - {Name: "testing", Image: "testing/image"}, - }}}}, - }, - container: "testing", - expected: expected{ - protocol: "UDP", - state: GameServerStatePortAllocation, - policy: Dynamic, - scheduling: apis.Packed, - health: Health{ - Disabled: false, - FailureThreshold: 3, - InitialDelaySeconds: 5, - PeriodSeconds: 5, - }, - sdkServer: SdkServer{ + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.SdkServer = SdkServer{ LogLevel: SdkServerLogLevelError, GRPCPort: 19357, HTTPPort: 19358, - }, - }, + } + }), + expected: wantDefaultAnd(func(e *expected) { + e.sdkServer = SdkServer{ + LogLevel: SdkServerLogLevelError, + GRPCPort: 19357, + HTTPPort: 19358, + } + }), + }, + "SafeToEvict gate off => no SafeToEvict fields": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=false", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) {}), + expected: wantDefaultAnd(func(e *expected) {}), + }, + "SafeToEvict gate on => SafeToEvict: Never": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) {}), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeNever + e.evictionSafeStatus = EvictionSafeNever + }), + }, + "SafeToEvict: Always": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Eviction.Safe = EvictionSafeAlways + }), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeAlways + e.evictionSafeStatus = EvictionSafeAlways + }), + }, + "SafeToEvict: OnUpgrade": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Eviction.Safe = EvictionSafeOnUpgrade + }), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeOnUpgrade + e.evictionSafeStatus = EvictionSafeOnUpgrade + }), + }, + "SafeToEvict: Never": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Eviction.Safe = EvictionSafeNever + }), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeNever + e.evictionSafeStatus = EvictionSafeNever + }), + }, + "SafeToEvict: Always inferred from safe-to-evict=true": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Template.ObjectMeta.Annotations = map[string]string{PodSafeToEvictAnnotation: "true"} + }), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeNever + e.evictionSafeStatus = EvictionSafeAlways + }), + }, + "Nothing inferred from safe-to-evict=false": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Template.ObjectMeta.Annotations = map[string]string{PodSafeToEvictAnnotation: "false"} + }), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeNever + e.evictionSafeStatus = EvictionSafeNever + }), + }, + "safe-to-evict=false AND SafeToEvict: Always => SafeToEvict: Always": { + featureFlags: string(runtime.FeatureSafeToEvict) + "=true", + gameServer: defaultGameServerAnd(func(gss *GameServerSpec) { + gss.Eviction.Safe = EvictionSafeAlways + gss.Template.ObjectMeta.Annotations = map[string]string{PodSafeToEvictAnnotation: "false"} + }), + expected: wantDefaultAnd(func(e *expected) { + e.evictionSafeSpec = EvictionSafeAlways + e.evictionSafeStatus = EvictionSafeAlways + }), }, } @@ -411,7 +391,7 @@ func TestGameServerApplyDefaults(t *testing.T) { spec := test.gameServer.Spec assert.Contains(t, test.gameServer.ObjectMeta.Finalizers, agones.GroupName) - assert.Equal(t, test.container, spec.Container) + assert.Equal(t, test.expected.container, spec.Container) assert.Equal(t, test.expected.protocol, spec.Ports[0].Protocol) assert.Equal(t, test.expected.state, test.gameServer.Status.State) assert.Equal(t, test.expected.scheduling, test.gameServer.Spec.Scheduling) @@ -423,6 +403,8 @@ func TestGameServerApplyDefaults(t *testing.T) { assert.Nil(t, test.gameServer.Spec.Players) assert.Nil(t, test.gameServer.Status.Players) } + assert.Equal(t, test.expected.evictionSafeSpec, spec.Eviction.Safe) + assert.Equal(t, test.expected.evictionSafeStatus, test.gameServer.Status.Eviction.Safe) }) } } @@ -1265,67 +1247,116 @@ func TestGameServerPodWithMultiplePortAllocations(t *testing.T) { } func TestGameServerPodObjectMeta(t *testing.T) { + runtime.FeatureTestMutex.Lock() + defer runtime.FeatureTestMutex.Unlock() + fixture := &GameServer{ObjectMeta: metav1.ObjectMeta{Name: "lucy"}, Spec: GameServerSpec{Container: "goat"}} - f := func(t *testing.T, gs *GameServer, pod *corev1.Pod) { - assert.Equal(t, gs.ObjectMeta.Name, pod.ObjectMeta.Name) - assert.Equal(t, gs.ObjectMeta.Namespace, pod.ObjectMeta.Namespace) - assert.Equal(t, GameServerLabelRole, pod.ObjectMeta.Labels[RoleLabel]) - assert.Equal(t, "gameserver", pod.ObjectMeta.Labels[agones.GroupName+"/role"]) - assert.Equal(t, gs.ObjectMeta.Name, pod.ObjectMeta.Labels[GameServerPodLabel]) - assert.Equal(t, "goat", pod.ObjectMeta.Annotations[GameServerContainerAnnotation]) - assert.True(t, metav1.IsControlledBy(pod, gs)) - } - - t.Run("packed", func(t *testing.T) { - gs := fixture.DeepCopy() - gs.Spec.Scheduling = apis.Packed - pod := &corev1.Pod{} - - gs.podObjectMeta(pod) - f(t, gs, pod) - - assert.Equal(t, "false", pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation]) - }) + for desc, tc := range map[string]struct { + featureFlags string + scheduling apis.SchedulingStrategy + wantSafe string + }{ + "packed, SafeToEvict=false": { + featureFlags: "SafeToEvict=false", + scheduling: apis.Packed, + wantSafe: "false", + }, + "distributed, SafeToEvict=false": { + featureFlags: "SafeToEvict=false", + scheduling: apis.Distributed, + }, + "packed, SafeToEvict=true": { + featureFlags: "SafeToEvict=true", + scheduling: apis.Packed, + }, + "distributed, SafeToEvict=true": { + featureFlags: "SafeToEvict=true", + scheduling: apis.Distributed, + }, + } { + t.Run(desc, func(t *testing.T) { + err := runtime.ParseFeatures(tc.featureFlags) + assert.NoError(t, err) - t.Run("distributed", func(t *testing.T) { - gs := fixture.DeepCopy() - gs.Spec.Scheduling = apis.Distributed - pod := &corev1.Pod{} + gs := fixture.DeepCopy() + gs.Spec.Scheduling = tc.scheduling + pod := &corev1.Pod{} - gs.podObjectMeta(pod) - f(t, gs, pod) + gs.podObjectMeta(pod) - assert.Equal(t, "", pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation]) - }) + assert.Equal(t, gs.ObjectMeta.Name, pod.ObjectMeta.Name) + assert.Equal(t, gs.ObjectMeta.Namespace, pod.ObjectMeta.Namespace) + assert.Equal(t, GameServerLabelRole, pod.ObjectMeta.Labels[RoleLabel]) + assert.Equal(t, "gameserver", pod.ObjectMeta.Labels[agones.GroupName+"/role"]) + assert.Equal(t, gs.ObjectMeta.Name, pod.ObjectMeta.Labels[GameServerPodLabel]) + assert.Equal(t, "goat", pod.ObjectMeta.Annotations[GameServerContainerAnnotation]) + assert.True(t, metav1.IsControlledBy(pod, gs)) + assert.Equal(t, tc.wantSafe, pod.ObjectMeta.Annotations[PodSafeToEvictAnnotation]) + }) + } } func TestGameServerPodAutoscalerAnnotations(t *testing.T) { + runtime.FeatureTestMutex.Lock() + defer runtime.FeatureTestMutex.Unlock() + testCases := []struct { + featureFlags string description string scheduling apis.SchedulingStrategy setAnnotation bool expectedAnnotation string }{ { - description: "Packed", + featureFlags: "SafeToEvict=false", + description: "Packed, SafeToEvict=false", scheduling: apis.Packed, expectedAnnotation: "false", }, { - description: "Distributed", + featureFlags: "SafeToEvict=false", + description: "Distributed, SafeToEvict=false", scheduling: apis.Distributed, expectedAnnotation: "", }, { - description: "Packed with autoscaler annotation", + featureFlags: "SafeToEvict=false", + description: "Packed with autoscaler annotation, SafeToEvict=false", scheduling: apis.Packed, setAnnotation: true, expectedAnnotation: "true", }, { - description: "Distributed with autoscaler annotation", + featureFlags: "SafeToEvict=false", + description: "Distributed with autoscaler annotation, SafeToEvict=false", + scheduling: apis.Distributed, + setAnnotation: true, + expectedAnnotation: "true", + }, + { + featureFlags: "SafeToEvict=true", + description: "Packed, SafeToEvict=true", + scheduling: apis.Packed, + expectedAnnotation: "false", + }, + { + featureFlags: "SafeToEvict=true", + description: "Distributed, SafeToEvict=true", + scheduling: apis.Distributed, + expectedAnnotation: "false", + }, + { + featureFlags: "SafeToEvict=true", + description: "Packed with autoscaler annotation, SafeToEvict=true", + scheduling: apis.Packed, + setAnnotation: true, + expectedAnnotation: "true", + }, + { + featureFlags: "SafeToEvict=true", + description: "Distributed with autoscaler annotation, SafeToEvict=true", scheduling: apis.Distributed, setAnnotation: true, expectedAnnotation: "true", @@ -1335,9 +1366,13 @@ func TestGameServerPodAutoscalerAnnotations(t *testing.T) { fixture := &GameServer{ ObjectMeta: metav1.ObjectMeta{Name: "logan"}, Spec: GameServerSpec{Container: "sheep"}, + Status: GameServerStatus{Eviction: Eviction{Safe: EvictionSafeNever}}, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { + err := runtime.ParseFeatures(tc.featureFlags) + assert.NoError(t, err) + gs := fixture.DeepCopy() gs.Spec.Scheduling = tc.scheduling if tc.setAnnotation { diff --git a/pkg/cloudproduct/gke/gke.go b/pkg/cloudproduct/gke/gke.go index fce5ec8346..bbd9169b76 100644 --- a/pkg/cloudproduct/gke/gke.go +++ b/pkg/cloudproduct/gke/gke.go @@ -38,8 +38,9 @@ const ( noWorkloadDefaulter = "failed to get MutatingWebhookConfigurations/workload-defaulter.config.common-webhooks.networking.gke.io (error expected if not on GKE Autopilot)" hostPortAssignmentAnnotation = "autopilot.gke.io/host-port-assignment" - errPortPolicyMustBeDynamic = "PortPolicy must be Dynamic on GKE Autopilot" - errSchedulingMustBePacked = "Scheduling strategy must be Packed on GKE Autopilot" + errPortPolicyMustBeDynamic = "portPolicy must be Dynamic on GKE Autopilot" + errSchedulingMustBePacked = "scheduling strategy must be Packed on GKE Autopilot" + errEvictionSafeOnUpgradeInvalid = "eviction.safe OnUpgrade not supported on GKE Autopilot" ) var logger = runtime.NewLoggerWithSource("gke") @@ -127,6 +128,14 @@ func (*gkeAutopilot) ValidateGameServerSpec(gss *agonesv1.GameServerSpec) []meta Message: errSchedulingMustBePacked, }) } + // See SetEviction comment below for why we block EvictionSafeOnUpgrade. + if gss.Eviction.Safe == agonesv1.EvictionSafeOnUpgrade { + causes = append(causes, metav1.StatusCause{ + Type: metav1.CauseTypeFieldValueInvalid, + Field: "eviction.safe", + Message: errEvictionSafeOnUpgradeInvalid, + }) + } return causes } @@ -149,6 +158,37 @@ func podSpecSeccompUnconfined(podSpec *corev1.PodSpec) { podSpec.SecurityContext.SeccompProfile = &corev1.SeccompProfile{Type: corev1.SeccompProfileTypeUnconfined} } +// SetEviction sets disruption controls based on GameServer.Status.Eviction. For Autopilot: +// - Since the safe-to-evict pod annotation is not supported if "false", we delete it (if it's set +// to anything else, we allow it - Autopilot only rejects "false"). +// - OnUpgrade is not supported and rejected by validation above. Since we can't support +// safe-to-evict=false but can support a restrictive PDB, we can support Never and Always, but +// OnUpgrade doesn't make sense on Autopilot today. - an overly restrictive PDB prevents +// any sort of graceful eviction. +func (*gkeAutopilot) SetEviction(safe agonesv1.EvictionSafe, pod *corev1.Pod) error { + if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) { + return nil + } + if safeAnnotation := pod.ObjectMeta.Annotations[agonesv1.PodSafeToEvictAnnotation]; safeAnnotation == agonesv1.False { + delete(pod.ObjectMeta.Annotations, agonesv1.PodSafeToEvictAnnotation) + } + if _, exists := pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel]; !exists { + switch safe { + case agonesv1.EvictionSafeAlways: + // For EvictionSafeAlways, we use a label value that does not match the + // agones-gameserver-safe-to-evict-false PDB. But we go ahead and label + // it, in case someone wants to adopt custom logic for this group of + // game servers. + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = agonesv1.True + case agonesv1.EvictionSafeNever: + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = agonesv1.False + default: + return errors.Errorf("eviction.safe == %s, which webhook should have rejected on Autopilot", safe) + } + } + return nil +} + type autopilotPortAllocator struct { minPort int32 maxPort int32 diff --git a/pkg/cloudproduct/gke/gke_test.go b/pkg/cloudproduct/gke/gke_test.go index 731645cd0a..540e3f946a 100644 --- a/pkg/cloudproduct/gke/gke_test.go +++ b/pkg/cloudproduct/gke/gke_test.go @@ -18,6 +18,7 @@ import ( "agones.dev/agones/pkg/apis" agonesv1 "agones.dev/agones/pkg/apis/agones/v1" + "agones.dev/agones/pkg/util/runtime" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -76,9 +77,10 @@ func TestSyncPodPortsToGameServer(t *testing.T) { func TestValidateGameServer(t *testing.T) { for name, tc := range map[string]struct { - ports []agonesv1.GameServerPort - scheduling apis.SchedulingStrategy - want []metav1.StatusCause + ports []agonesv1.GameServerPort + scheduling apis.SchedulingStrategy + safeToEvict agonesv1.EvictionSafe + want []metav1.StatusCause }{ "no ports => validated": {scheduling: apis.Packed}, "good ports => validated": { @@ -102,7 +104,8 @@ func TestValidateGameServer(t *testing.T) { Protocol: corev1.ProtocolTCP, }, }, - scheduling: apis.Packed, + safeToEvict: agonesv1.EvictionSafeAlways, + scheduling: apis.Packed, }, "bad policy => fails validation": { ports: []agonesv1.GameServerPort{ @@ -125,23 +128,29 @@ func TestValidateGameServer(t *testing.T) { Protocol: corev1.ProtocolUDP, }, }, - scheduling: apis.Distributed, + safeToEvict: agonesv1.EvictionSafeOnUpgrade, + scheduling: apis.Distributed, want: []metav1.StatusCause{ { Type: "FieldValueInvalid", - Message: "PortPolicy must be Dynamic on GKE Autopilot", + Message: "portPolicy must be Dynamic on GKE Autopilot", Field: "bad-udp.portPolicy", }, { Type: "FieldValueInvalid", - Message: "PortPolicy must be Dynamic on GKE Autopilot", + Message: "portPolicy must be Dynamic on GKE Autopilot", Field: "another-bad-udp.portPolicy", }, { Type: "FieldValueInvalid", - Message: "Scheduling strategy must be Packed on GKE Autopilot", + Message: "scheduling strategy must be Packed on GKE Autopilot", Field: "scheduling", }, + { + Type: "FieldValueInvalid", + Message: "eviction.safe OnUpgrade not supported on GKE Autopilot", + Field: "eviction.safe", + }, }, }, } { @@ -149,6 +158,7 @@ func TestValidateGameServer(t *testing.T) { causes := (&gkeAutopilot{}).ValidateGameServerSpec(&agonesv1.GameServerSpec{ Ports: tc.ports, Scheduling: tc.scheduling, + Eviction: agonesv1.Eviction{Safe: tc.safeToEvict}, }) require.Equal(t, tc.want, causes) }) @@ -197,6 +207,103 @@ func TestPodSeccompUnconfined(t *testing.T) { } } +func TestSetSafeToEvict(t *testing.T) { + runtime.FeatureTestMutex.Lock() + defer runtime.FeatureTestMutex.Unlock() + + emptyPodAnd := func(f func(*corev1.Pod)) *corev1.Pod { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{}, + Labels: map[string]string{}, + }, + } + f(pod) + return pod + } + for desc, tc := range map[string]struct { + featureFlags string + safeToEvict agonesv1.EvictionSafe + pod *corev1.Pod + wantPod *corev1.Pod + wantErr bool + }{ + "SafeToEvict feature gate disabled => no change": { + featureFlags: "SafeToEvict=false", + // intentionally leave pod nil, it'll crash if anything's touched. + }, + "SafeToEvict: Always, no incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: agonesv1.EvictionSafeAlways, + pod: emptyPodAnd(func(*corev1.Pod) {}), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = agonesv1.True + }), + }, + "SafeToEvict: Never, no incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: agonesv1.EvictionSafeNever, + pod: emptyPodAnd(func(*corev1.Pod) {}), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = agonesv1.False + }), + }, + "SafeToEvict: OnUpgrade => error": { + featureFlags: "SafeToEvict=true", + safeToEvict: agonesv1.EvictionSafeOnUpgrade, + pod: emptyPodAnd(func(*corev1.Pod) {}), + wantErr: true, + }, + "SafeToEvict: Always, incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: agonesv1.EvictionSafeAlways, + pod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[agonesv1.PodSafeToEvictAnnotation] = "just don't touch, ok?" + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = "seriously, leave it" + }), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[agonesv1.PodSafeToEvictAnnotation] = "just don't touch, ok?" + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = "seriously, leave it" + }), + }, + "SafeToEvict: Never, incoming labels/annotations": { + featureFlags: "SafeToEvict=true", + safeToEvict: agonesv1.EvictionSafeNever, + pod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[agonesv1.PodSafeToEvictAnnotation] = "a passthrough" + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = "or is it passthru?" + }), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[agonesv1.PodSafeToEvictAnnotation] = "a passthrough" + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = "or is it passthru?" + }), + }, + "SafeToEvict: Never, but safe-to-evict pod annotation set to false": { + featureFlags: "SafeToEvict=true", + safeToEvict: agonesv1.EvictionSafeNever, + pod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Annotations[agonesv1.PodSafeToEvictAnnotation] = agonesv1.False + }), + wantPod: emptyPodAnd(func(pod *corev1.Pod) { + pod.ObjectMeta.Labels[agonesv1.SafeToEvictLabel] = agonesv1.False + }), + }, + } { + t.Run(desc, func(t *testing.T) { + err := runtime.ParseFeatures(tc.featureFlags) + assert.NoError(t, err) + + err = (&gkeAutopilot{}).SetEviction(tc.safeToEvict, tc.pod) + if tc.wantErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + assert.Equal(t, tc.wantPod, tc.pod) + }) + } +} + func TestAutopilotPortAllocator(t *testing.T) { for name, tc := range map[string]struct { ports []agonesv1.GameServerPort diff --git a/site/content/en/docs/Reference/agones_crd_api_reference.html b/site/content/en/docs/Reference/agones_crd_api_reference.html index 5b877adcee..014603abbe 100644 --- a/site/content/en/docs/Reference/agones_crd_api_reference.html +++ b/site/content/en/docs/Reference/agones_crd_api_reference.html @@ -3029,6 +3029,9 @@

SdkServerLogLevel

Packages:

-

agones.dev/v1

+

multicluster.agones.dev/v1

Package v1 is the v1 version of the API.

Resource Types: -

Fleet +

GameServerAllocationPolicy

-

Fleet is the data structure for a Fleet resource

+

GameServerAllocationPolicy is the Schema for the gameserverallocationpolicies API

@@ -3072,7 +3068,7 @@

Fleet string

@@ -3081,7 +3077,7 @@

Fleet kind
string -

+ @@ -3112,77 +3108,49 @@

Fleet

-agones.dev/v1 +multicluster.agones.dev/v1
FleetGameServerAllocationPolicy
@@ -3101,8 +3097,8 @@

Fleet

spec
- -FleetSpec + +GameServerAllocationPolicySpec
- - - -
-replicas
+priority
int32
-

Replicas are the number of GameServers that should be in this set. Defaults to 0.

-
-strategy
- - -Kubernetes apps/v1.DeploymentStrategy - - -
-

Deployment strategy

-scheduling
+weight
-agones.dev/agones/pkg/apis.SchedulingStrategy +int
-

Scheduling strategy. Defaults to “Packed”.

-template
+connectionInfo
- -GameServerTemplateSpec + +ClusterConnectionInfo
-

Template the GameServer template to apply for this Fleet

- - -status
- - -FleetStatus - - - - - - -

GameServer +

ClusterConnectionInfo

-

GameServer is the data structure for a GameServer resource. -It is worth noting that while there is a GameServerStatus Status entry for the GameServer, it is not -defined as a subresource - unlike Fleet and other Agones resources. -This is so that we can retain the ability to change multiple aspects of a GameServer in a single atomic operation, -which is particularly useful for operations such as allocation.

+(Appears on: +GameServerAllocationPolicySpec) +

+

+

ClusterConnectionInfo defines the connection information for a cluster

@@ -3194,146 +3162,165 @@

GameServer

- - - - + + @@ -3342,12 +3329,23 @@

GameServer

-apiVersion
-string
- -agones.dev/v1 - +clusterName
+ +string +
-kind
-string +

Optional: the name of the targeted cluster

GameServer
-metadata
+allocationEndpoints
- -Kubernetes meta/v1.ObjectMeta - +[]string
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +

The endpoints for the allocator service in the targeted cluster. +If the AllocationEndpoints is not set, the allocation happens on local cluster. +If there are multiple endpoints any of the endpoints that can handle allocation request should suffice

-spec
+secretName
- -GameServerSpec - +string
-
-
- +

The name of the secret that contains TLS client certificates to connect the allocator server in the targeted cluster

+ + + +
-container
+namespace
string
-

Container specifies which Pod container is the game server. Only required if there is more than one -container defined

+

The cluster namespace from which to allocate gameservers

-ports
+serverCa
- -[]GameServerPort - +[]byte
-

Ports are the array of ports that can be exposed via the game server

+

The PEM encoded server CA, used by the allocator client to authenticate the remote server.

+

ConnectionInfoIterator +

+

+

ConnectionInfoIterator an iterator on ClusterConnectionInfo

+

+ + + + + + + + + +
FieldDescription
-health
+currPriority
- -Health - +int
-

Health configures health checking

+

currPriority Current priority index from the orderedPriorities

-scheduling
+orderedPriorities
-agones.dev/agones/pkg/apis.SchedulingStrategy +[]int32
-

Scheduling strategy. Defaults to “Packed”

+

orderedPriorities list of ordered priorities

-sdkServer
+priorityToCluster
- -SdkServer - +map[int32]map[string][]*agones.dev/agones/pkg/apis/multicluster/v1.GameServerAllocationPolicy
-

SdkServer specifies parameters for the Agones SDK Server sidecar container

+

priorityToCluster Map of priority to cluster-policies map

-template
+clusterBlackList
- -Kubernetes core/v1.PodTemplateSpec - +map[string]bool
-

Template describes the Pod that will be created for the GameServer

+

clusterBlackList the cluster blacklist for the clusters that has already returned

+

GameServerAllocationPolicySpec +

+

+(Appears on: +GameServerAllocationPolicy) +

+

+

GameServerAllocationPolicySpec defines the desired state of GameServerAllocationPolicy

+

+ + + + + + + + -
FieldDescription
-players
+priority
- -PlayersSpec - +int32
-(Optional) -

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

+
+weight
+ +int + +
-status
+connectionInfo
- -GameServerStatus + +ClusterConnectionInfo
-

GameServerSet +
+

agones.dev/v1

+

+

Package v1 is the v1 version of the API.

+

+Resource Types: + +

Fleet

-

GameServerSet is the data structure for a set of GameServers. -This matches philosophically with the relationship between -Deployments and ReplicaSets

+

Fleet is the data structure for a Fleet resource

@@ -3372,7 +3370,7 @@

GameServerSet kind
string -

+ @@ -3409,31 +3407,44 @@

GameServerSet

+ + + +
GameServerSetFleet
@@ -3392,8 +3390,8 @@

GameServerSet

spec
- -GameServerSetSpec + +FleetSpec
-

Replicas are the number of GameServers that should be in this set

+

Replicas are the number of GameServers that should be in this set. Defaults to 0.

-scheduling
+strategy
-agones.dev/agones/pkg/apis.SchedulingStrategy + +Kubernetes apps/v1.DeploymentStrategy +
-

Scheduling strategy. Defaults to “Packed”.

+

Deployment strategy

-template
+scheduling
- -GameServerTemplateSpec +agones.dev/agones/pkg/apis.SchedulingStrategy + +
+

Scheduling strategy. Defaults to “Packed”.

+
+template
+ + +GameServerTemplateSpec
-

Template the GameServer template to apply for this GameServerSet

+

Template the GameServer template to apply for this Fleet

@@ -3443,8 +3454,8 @@

GameServerSet status
- -GameServerSetStatus + +FleetStatus @@ -3453,15 +3464,14 @@

GameServerSet -

AggregatedPlayerStatus +

GameServer

-(Appears on: -FleetStatus, -GameServerSetStatus) -

-

-

AggregatedPlayerStatus stores total player tracking values

+

GameServer is the data structure for a GameServer resource. +It is worth noting that while there is a GameServerStatus Status entry for the GameServer, it is not +defined as a subresource - unlike Fleet and other Agones resources. +This is so that we can retain the ability to change multiple aspects of a GameServer in a single atomic operation, +which is particularly useful for operations such as allocation.

@@ -3473,183 +3483,174 @@

AggregatedPlayerStatus

+ + + + - -
-count
- -int64 - +apiVersion
+string
+ +agones.dev/v1 +
+kind
+string
GameServer
-capacity
+metadata
-int64 + +Kubernetes meta/v1.ObjectMeta +
+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-

FleetSpec -

-

-(Appears on: -Fleet) -

-

-

FleetSpec is the spec for a Fleet

-

- - - - - - - + +
FieldDescription
+spec
+ + +GameServerSpec + + +
+
+
+ - -
-replicas
+container
-int32 +string
-

Replicas are the number of GameServers that should be in this set. Defaults to 0.

+

Container specifies which Pod container is the game server. Only required if there is more than one +container defined

-strategy
+ports
- -Kubernetes apps/v1.DeploymentStrategy + +[]GameServerPort
-

Deployment strategy

+

Ports are the array of ports that can be exposed via the game server

-scheduling
+health
-agones.dev/agones/pkg/apis.SchedulingStrategy + +Health +
-

Scheduling strategy. Defaults to “Packed”.

+

Health configures health checking

-template
+scheduling
- -GameServerTemplateSpec - +agones.dev/agones/pkg/apis.SchedulingStrategy
-

Template the GameServer template to apply for this Fleet

+

Scheduling strategy. Defaults to “Packed”

-

FleetStatus -

-

-(Appears on: -Fleet, -FleetAutoscaleRequest) -

-

-

FleetStatus is the status of a Fleet

-

- - - - - - - - + +
FieldDescription
-replicas
+sdkServer
-int32 + +SdkServer +
-

Replicas the total number of current GameServer replicas

+

SdkServer specifies parameters for the Agones SDK Server sidecar container

-readyReplicas
+template
-int32 + +Kubernetes core/v1.PodTemplateSpec +
-

ReadyReplicas are the number of Ready GameServer replicas

+

Template describes the Pod that will be created for the GameServer

-reservedReplicas
+players
-int32 + +PlayersSpec +
-

ReservedReplicas are the total number of Reserved GameServer replicas in this fleet. -Reserved instances won’t be deleted on scale down, but won’t cause an autoscaler to scale up.

+(Optional) +

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

-allocatedReplicas
+eviction
-int32 + +Eviction +
-

AllocatedReplicas are the number of Allocated GameServer replicas

+(Optional) +

(Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

+
-players
+status
- -AggregatedPlayerStatus + +GameServerStatus
-(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerTracking] -Players are the current total player capacity and count for this Fleet

-

GameServerPort +

GameServerSet

-(Appears on: -GameServerSpec) -

-

-

GameServerPort defines a set of Ports that -are to be exposed via the GameServer

+

GameServerSet is the data structure for a set of GameServers. +This matches philosophically with the relationship between +Deployments and ReplicaSets

@@ -3661,89 +3662,194 @@

GameServerPort

+ + + + - +
+
+
-name
- -string - +apiVersion
+string
+ +agones.dev/v1 +
-

Name is the descriptive name of the port

+kind
+string
GameServerSet
-portPolicy
+metadata
- -PortPolicy + +Kubernetes meta/v1.ObjectMeta
-

PortPolicy defines the policy for how the HostPort is populated. -Dynamic port will allocate a HostPort within the selected MIN_PORT and MAX_PORT range passed to the controller -at installation time. -When Static portPolicy is specified, HostPort is required, to specify the port that game clients will -connect to

+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-container
+spec
-string + +GameServerSetSpec +
-(Optional) -

Container is the name of the container on which to open the port. Defaults to the game server container.

-
-
-containerPort
+replicas
int32
-

ContainerPort is the port that is being opened on the specified container’s process

+

Replicas are the number of GameServers that should be in this set

-hostPort
+scheduling
-int32 +agones.dev/agones/pkg/apis.SchedulingStrategy
-

HostPort the port exposed on the host for clients to connect to

+

Scheduling strategy. Defaults to “Packed”.

-protocol
+template
- -Kubernetes core/v1.Protocol + +GameServerTemplateSpec
-

Protocol is the network protocol being used. Defaults to UDP. TCP and TCPUDP are other options.

+

Template the GameServer template to apply for this GameServerSet

-

GameServerSetSpec -

-

-(Appears on: -GameServerSet) + + + + +status
+ + +GameServerSetStatus + + + + + + + + +

AggregatedPlayerStatus +

+

+(Appears on: +FleetStatus, +GameServerSetStatus)

-

GameServerSetSpec the specification for GameServerSet

+

AggregatedPlayerStatus stores total player tracking values

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+count
+ +int64 + +
+
+capacity
+ +int64 + +
+
+

Eviction +

+

+(Appears on: +GameServerSpec, +GameServerStatus) +

+

+

Eviction specifies the eviction tolerance of the GameServer

+

+ + + + + + + + + + + + + +
FieldDescription
+safe
+ + +EvictionSafe + + +
+

(Alpha, SafeToEvict feature flag) +Game server supports termination via SIGTERM: +- Always: Allow eviction for both Cluster Autoscaler and node drain for upgrades +- OnUpgrade: Allow eviction for upgrades alone +- Never (default): Pod should run to completion

+
+

EvictionSafe +(string alias)

+

+(Appears on: +Eviction) +

+

+

EvictionSafe specified whether the game server supports termination via SIGTERM

+

+

FleetSpec +

+

+(Appears on: +Fleet) +

+

+

FleetSpec is the spec for a Fleet

@@ -3761,7 +3867,20 @@

GameServerSetSpec

+ + + + @@ -3785,19 +3904,20 @@

GameServerSetSpec

-

Replicas are the number of GameServers that should be in this set

+

Replicas are the number of GameServers that should be in this set. Defaults to 0.

+
+strategy
+ + +Kubernetes apps/v1.DeploymentStrategy + + +
+

Deployment strategy

-

Template the GameServer template to apply for this GameServerSet

+

Template the GameServer template to apply for this Fleet

-

GameServerSetStatus +

FleetStatus

(Appears on: -GameServerSet) +Fleet, +FleetAutoscaleRequest)

-

GameServerSetStatus is the status of a GameServerSet

+

FleetStatus is the status of a Fleet

@@ -3815,7 +3935,7 @@

GameServerSetStatus

@@ -3826,7 +3946,7 @@

GameServerSetStatus

@@ -3837,7 +3957,8 @@

GameServerSetStatus

@@ -3848,18 +3969,7 @@

GameServerSetStatus

- - - - @@ -3875,20 +3985,20 @@

GameServerSetStatus (Optional)

[Stage:Alpha] [FeatureFlag:PlayerTracking] -Players is the current total player capacity and count for this GameServerSet

+Players are the current total player capacity and count for this Fleet

-

Replicas is the total number of current GameServer replicas

+

Replicas the total number of current GameServer replicas

-

ReadyReplicas is the number of Ready GameServer replicas

+

ReadyReplicas are the number of Ready GameServer replicas

-

ReservedReplicas is the number of Reserved GameServer replicas

+

ReservedReplicas are the total number of Reserved GameServer replicas in this fleet. +Reserved instances won’t be deleted on scale down, but won’t cause an autoscaler to scale up.

-

AllocatedReplicas is the number of Allocated GameServer replicas

-
-shutdownReplicas
- -int32 - -
-

ShutdownReplicas is the number of Shutdown GameServers replicas

+

AllocatedReplicas are the number of Allocated GameServer replicas

-

GameServerSpec +

GameServerPort

(Appears on: -GameServer, -GameServerTemplateSpec) +GameServerSpec)

-

GameServerSpec is the spec for a GameServer resource

+

GameServerPort defines a set of Ports that +are to be exposed via the GameServer

@@ -3900,113 +4010,89 @@

GameServerSpec

- - - -
-container
+name
string
-

Container specifies which Pod container is the game server. Only required if there is more than one -container defined

-
-ports
- - -[]GameServerPort - - -
-

Ports are the array of ports that can be exposed via the game server

+

Name is the descriptive name of the port

-health
+portPolicy
- -Health + +PortPolicy
-

Health configures health checking

+

PortPolicy defines the policy for how the HostPort is populated. +Dynamic port will allocate a HostPort within the selected MIN_PORT and MAX_PORT range passed to the controller +at installation time. +When Static portPolicy is specified, HostPort is required, to specify the port that game clients will +connect to

-scheduling
+container
-agones.dev/agones/pkg/apis.SchedulingStrategy +string
-

Scheduling strategy. Defaults to “Packed”

+(Optional) +

Container is the name of the container on which to open the port. Defaults to the game server container.

-sdkServer
+containerPort
- -SdkServer - +int32
-

SdkServer specifies parameters for the Agones SDK Server sidecar container

+

ContainerPort is the port that is being opened on the specified container’s process

-template
+hostPort
- -Kubernetes core/v1.PodTemplateSpec - +int32
-

Template describes the Pod that will be created for the GameServer

+

HostPort the port exposed on the host for clients to connect to

-players
+protocol
- -PlayersSpec + +Kubernetes core/v1.Protocol
-(Optional) -

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

+

Protocol is the network protocol being used. Defaults to UDP. TCP and TCPUDP are other options.

-

GameServerState -(string alias)

-

-(Appears on: -GameServerSelector, -GameServerStatus) -

-

-

GameServerState is the state for the GameServer

-

-

GameServerStatus +

GameServerSetSpec

(Appears on: -GameServer) +GameServerSet)

-

GameServerStatus is the status for a GameServer resource

+

GameServerSetSpec the specification for GameServerSet

@@ -4018,128 +4104,140 @@

GameServerStatus

- - +
-state
+replicas
- -GameServerState - +int32
-

GameServerState is the current state of a GameServer, e.g. Creating, Starting, Ready, etc

+

Replicas are the number of GameServers that should be in this set

-ports
+scheduling
- -[]GameServerStatusPort - +agones.dev/agones/pkg/apis.SchedulingStrategy
+

Scheduling strategy. Defaults to “Packed”.

-address
+template
-string + +GameServerTemplateSpec +
+

Template the GameServer template to apply for this GameServerSet

-nodeName
- -string - +
+

GameServerSetStatus +

+

+(Appears on: +GameServerSet) +

+

+

GameServerSetStatus is the status of a GameServerSet

+

+ + + + + + + + + + - -
FieldDescription
+replicas
+ +int32 +
+

Replicas is the total number of current GameServer replicas

-reservedUntil
+readyReplicas
- -Kubernetes meta/v1.Time - +int32
+

ReadyReplicas is the number of Ready GameServer replicas

-players
+reservedReplicas
- -PlayerStatus - +int32
-(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerTracking]

+

ReservedReplicas is the number of Reserved GameServer replicas

-

GameServerStatusPort -

-

-(Appears on: -GameServerAllocationStatus, -GameServerStatus) -

-

-

GameServerStatusPort shows the port that was allocated to a -GameServer.

-

- - - - + + - -
FieldDescription +allocatedReplicas
+ +int32 + +
+

AllocatedReplicas is the number of Allocated GameServer replicas

+
-name
+shutdownReplicas
-string +int32
+

ShutdownReplicas is the number of Shutdown GameServers replicas

-port
+players
-int32 + +AggregatedPlayerStatus +
+(Optional) +

[Stage:Alpha] +[FeatureFlag:PlayerTracking] +Players is the current total player capacity and count for this GameServerSet

-

GameServerTemplateSpec +

GameServerSpec

(Appears on: -FleetSpec, -GameServerSetSpec) +GameServer, +GameServerTemplateSpec)

-

GameServerTemplateSpec is a template for GameServers

+

GameServerSpec is the spec for a GameServer resource

@@ -4151,33 +4249,6 @@

GameServerTemplateSpec

- - - - - + +
-metadata
- - -Kubernetes meta/v1.ObjectMeta - - -
-Refer to the Kubernetes API documentation for the fields of the -metadata field. -
-spec
- - -GameServerSpec - - -
-
-
- - - -
container
string @@ -4265,19 +4336,40 @@

GameServerTemplateSpec

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

+
+eviction
+ + +Eviction + + +
+(Optional) +

(Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

-

Health +

GameServerState +(string alias)

+

+(Appears on: +GameServerSelector, +GameServerStatus) +

+

+

GameServerState is the state for the GameServer

+

+

GameServerStatus

(Appears on: -GameServerSpec) +GameServer)

-

Health configures health checking on the GameServer

+

GameServerStatus is the status for a GameServer resource

@@ -4289,72 +4381,56 @@

Health

- -
-disabled
+state
-bool + +GameServerState +
-

Disabled is whether health checking is disabled or not

+

GameServerState is the current state of a GameServer, e.g. Creating, Starting, Ready, etc

-periodSeconds
+ports
-int32 + +[]GameServerStatusPort +
-

PeriodSeconds is the number of seconds each health ping has to occur in

-failureThreshold
+address
-int32 +string
-

FailureThreshold how many failures in a row constitutes unhealthy

-initialDelaySeconds
+nodeName
-int32 +string
-

InitialDelaySeconds initial delay before checking health

-

PlayerStatus -

-

-(Appears on: -GameServerStatus) -

-

-

PlayerStatus stores the current player capacity values

-

- - - - - - - -
FieldDescription
-count
+reservedUntil
-int64 + +Kubernetes meta/v1.Time +
@@ -4362,34 +4438,44 @@

PlayerStatus

-capacity
+players
-int64 + +PlayerStatus +
+(Optional) +

[Stage:Alpha] +[FeatureFlag:PlayerTracking]

-ids
+eviction
-[]string + +Eviction +
+

(Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer.

-

PlayersSpec +

GameServerStatusPort

(Appears on: -GameServerSpec) +GameServerAllocationStatus, +GameServerStatus)

-

PlayersSpec tracks the initial player capacity

+

GameServerStatusPort shows the port that was allocated to a +GameServer.

@@ -4401,9 +4487,19 @@

PlayersSpec

+ + + +
-initialCapacity
+name
-int64 +string + +
+
+port
+ +int32
@@ -4411,23 +4507,15 @@

PlayersSpec

-

PortPolicy -(string alias)

-

-(Appears on: -GameServerPort) -

-

-

PortPolicy is the port policy for the GameServer

-

-

SdkServer +

GameServerTemplateSpec

(Appears on: -GameServerSpec) +FleetSpec, +GameServerSetSpec)

-

SdkServer specifies parameters for the Agones SDK Server sidecar container

+

GameServerTemplateSpec is a template for GameServers

@@ -4439,230 +4527,147 @@

SdkServer

- +
+
+
-logLevel
+metadata
- -SdkServerLogLevel + +Kubernetes meta/v1.ObjectMeta
-

LogLevel for SDK server (sidecar) logs. Defaults to “Info”

+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-grpcPort
+spec
-int32 + +GameServerSpec +
-

GRPCPort is the port on which the SDK Server binds the gRPC server to accept incoming connections

-
- - -
-httpPort
+container
-int32 +string
-

HTTPPort is the port on which the SDK Server binds the HTTP gRPC gateway server to accept incoming connections

-
-

SdkServerLogLevel -(string alias)

-

-(Appears on: -SdkServer) -

-

-

SdkServerLogLevel is the log level for SDK server (sidecar) logs

-

-
-

allocation.agones.dev/v1

-

-

Package v1 is the v1 version of the API.

-

-Resource Types: - -

GameServerAllocation -

-

-

GameServerAllocation is the data structure for allocating against a set of -GameServers, defined selectors selectors

-

- - - - - - - - - - - - - - - - - - - -
FieldDescription
-apiVersion
-string
- -allocation.agones.dev/v1 - -
-kind
-string +

Container specifies which Pod container is the game server. Only required if there is more than one +container defined

GameServerAllocation
-metadata
+ports
- -Kubernetes meta/v1.ObjectMeta + +[]GameServerPort
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +

Ports are the array of ports that can be exposed via the game server

-spec
- - -GameServerAllocationSpec - - -
-
-
- - -
-multiClusterSetting
+health
- -MultiClusterSetting + +Health
-

MultiClusterPolicySelector if specified, multi-cluster policies are applied. -Otherwise, allocation will happen locally.

+

Health configures health checking

-required
+scheduling
- -GameServerSelector - +agones.dev/agones/pkg/apis.SchedulingStrategy
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Required is the GameServer selector from which to choose GameServers from. -Defaults to all GameServers.

+

Scheduling strategy. Defaults to “Packed”

-preferred
+sdkServer
- -[]GameServerSelector + +SdkServer
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Preferred is an ordered list of preferred GameServer selectors -that are optional to be fulfilled, but will be searched before the required selector. -If the first selector is not matched, the selection attempts the second selector, and so on. -If any of the preferred selectors are matched, the required selector is not considered. -This is useful for things like smoke testing of new game servers.

+

SdkServer specifies parameters for the Agones SDK Server sidecar container

-selectors
+template
- -[]GameServerSelector + +Kubernetes core/v1.PodTemplateSpec
-

Ordered list of GameServer label selectors. -If the first selector is not matched, the selection attempts the second selector, and so on. -This is useful for things like smoke testing of new game servers. -Note: This field can only be set if neither Required or Preferred is set.

+

Template describes the Pod that will be created for the GameServer

-scheduling
+players
-agones.dev/agones/pkg/apis.SchedulingStrategy + +PlayersSpec +
-

Scheduling strategy. Defaults to “Packed”.

+(Optional) +

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

-metadata
+eviction
- -MetaPatch + +Eviction
-

MetaPatch is optional custom metadata that is added to the game server at allocation -You can use this to tell the server necessary session data

+(Optional) +

(Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

-status
- - -GameServerAllocationStatus - - -
-
-

GameServerAllocationSpec +

Health

(Appears on: -GameServerAllocation) +GameServerSpec)

-

GameServerAllocationSpec is the spec for a GameServerAllocation

+

Health configures health checking on the GameServer

@@ -4674,111 +4679,58 @@

GameServerAllocationS

- - - - - - - -
-multiClusterSetting
- - -MultiClusterSetting - - -
-

MultiClusterPolicySelector if specified, multi-cluster policies are applied. -Otherwise, allocation will happen locally.

-
-required
- - -GameServerSelector - - -
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Required is the GameServer selector from which to choose GameServers from. -Defaults to all GameServers.

-
-preferred
+disabled
- -[]GameServerSelector - +bool
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Preferred is an ordered list of preferred GameServer selectors -that are optional to be fulfilled, but will be searched before the required selector. -If the first selector is not matched, the selection attempts the second selector, and so on. -If any of the preferred selectors are matched, the required selector is not considered. -This is useful for things like smoke testing of new game servers.

+

Disabled is whether health checking is disabled or not

-selectors
+periodSeconds
- -[]GameServerSelector - +int32
-

Ordered list of GameServer label selectors. -If the first selector is not matched, the selection attempts the second selector, and so on. -This is useful for things like smoke testing of new game servers. -Note: This field can only be set if neither Required or Preferred is set.

+

PeriodSeconds is the number of seconds each health ping has to occur in

-scheduling
+failureThreshold
-agones.dev/agones/pkg/apis.SchedulingStrategy +int32
-

Scheduling strategy. Defaults to “Packed”.

+

FailureThreshold how many failures in a row constitutes unhealthy

-metadata
+initialDelaySeconds
- -MetaPatch - +int32
-

MetaPatch is optional custom metadata that is added to the game server at allocation -You can use this to tell the server necessary session data

+

InitialDelaySeconds initial delay before checking health

-

GameServerAllocationState -(string alias)

-

-(Appears on: -GameServerAllocationStatus) -

-

-

GameServerAllocationState is the Allocation state

-

-

GameServerAllocationStatus +

PlayerStatus

(Appears on: -GameServerAllocation) +GameServerStatus)

-

GameServerAllocationStatus is the status for an GameServerAllocation resource

+

PlayerStatus stores the current player capacity values

@@ -4790,34 +4742,19 @@

GameServerAllocatio

- - - - + +
-state
+count
- -GameServerAllocationState - +int64
-

GameServerState is the current state of an GameServerAllocation, e.g. Allocated, or UnAllocated

-gameServerName
- -string - -
-
-ports
+capacity
- -[]GameServerStatusPort - +int64
@@ -4825,47 +4762,62 @@

GameServerAllocatio

-address
+ids
-string +[]string
+

PlayersSpec +

+

+(Appears on: +GameServerSpec) +

+

+

PlayersSpec tracks the initial player capacity

+

+ + - - + + + +
-nodeName
- -string - -
-FieldDescription
-source
+initialCapacity
-string +int64
-

If the allocation is from a remote cluster, Source is the endpoint of the remote agones-allocator. -Otherwise, Source is “local”

-

GameServerSelector +

PortPolicy +(string alias)

+

+(Appears on: +GameServerPort) +

+

+

PortPolicy is the port policy for the GameServer

+

+

SdkServer

(Appears on: -GameServerAllocationSpec) +GameServerSpec)

-

GameServerSelector contains all the filter options for selecting -a GameServer for allocation.

+

SdkServer specifies parameters for the Agones SDK Server sidecar container

@@ -4877,65 +4829,64 @@

GameServerSelector

-LabelSelector
+logLevel
- -Kubernetes meta/v1.LabelSelector + +SdkServerLogLevel
-

-(Members of LabelSelector are embedded into this type.) -

-

See: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/

+

LogLevel for SDK server (sidecar) logs. Defaults to “Info”

-gameServerState
+grpcPort
- -GameServerState - +int32
-(Optional) -

[Stage:Beta] -[FeatureFlag:StateAllocationFilter] -GameServerState specifies which State is the filter to be used when attempting to retrieve a GameServer -via Allocation. Defaults to “Ready”. The only other option is “Allocated”, which can be used in conjunction with -label/annotation/player selectors to retrieve an already Allocated GameServer.

+

GRPCPort is the port on which the SDK Server binds the gRPC server to accept incoming connections

-players
+httpPort
- -PlayerSelector - +int32
-(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerAllocationFilter] -Players provides a filter on minimum and maximum values for player capacity when retrieving a GameServer -through Allocation. Defaults to no limits.

+

HTTPPort is the port on which the SDK Server binds the HTTP gRPC gateway server to accept incoming connections

-

MetaPatch -

+

SdkServerLogLevel +(string alias)

(Appears on: -GameServerAllocationSpec) +SdkServer)

-

MetaPatch is the metadata used to patch the GameServer metadata on allocation

+

SdkServerLogLevel is the log level for SDK server (sidecar) logs

+

+
+

allocation.agones.dev/v1

+

+

Package v1 is the v1 version of the API.

+

+Resource Types: + +

GameServerAllocation +

+

+

GameServerAllocation is the data structure for allocating against a set of +GameServers, defined selectors selectors

@@ -4947,59 +4898,145 @@

MetaPatch

+ + + + + + + + + + + @@ -5008,14 +5045,14 @@

MultiClusterSetting

-labels
+apiVersion
+string
+ +allocation.agones.dev/v1 + +
+kind
+string +
GameServerAllocation
+metadata
-map[string]string + +Kubernetes meta/v1.ObjectMeta +
+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-annotations
+spec
-map[string]string + +GameServerAllocationSpec +
+
+
+ + + + - -
+multiClusterSetting
+ + +MultiClusterSetting + + +
+

MultiClusterPolicySelector if specified, multi-cluster policies are applied. +Otherwise, allocation will happen locally.

-

MultiClusterSetting -

-

-(Appears on: -GameServerAllocationSpec) -

-

-

MultiClusterSetting specifies settings for multi-cluster allocation.

-

- - - - + + - - + + + + + + + + + + +
FieldDescription +required
+ + +GameServerSelector + + +
+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Required is the GameServer selector from which to choose GameServers from. +Defaults to all GameServers.

+
-enabled
+preferred
-bool + +[]GameServerSelector +
+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Preferred is an ordered list of preferred GameServer selectors +that are optional to be fulfilled, but will be searched before the required selector. +If the first selector is not matched, the selection attempts the second selector, and so on. +If any of the preferred selectors are matched, the required selector is not considered. +This is useful for things like smoke testing of new game servers.

-policySelector
+selectors
- -Kubernetes meta/v1.LabelSelector + +[]GameServerSelector + + +
+

Ordered list of GameServer label selectors. +If the first selector is not matched, the selection attempts the second selector, and so on. +This is useful for things like smoke testing of new game servers. +Note: This field can only be set if neither Required or Preferred is set.

+
+scheduling
+ +agones.dev/agones/pkg/apis.SchedulingStrategy + +
+

Scheduling strategy. Defaults to “Packed”.

+
+metadata
+ + +MetaPatch + + +
+

MetaPatch is optional custom metadata that is added to the game server at allocation +You can use this to tell the server necessary session data

+
+
+status
+ + +GameServerAllocationStatus
-

PlayerSelector +

GameServerAllocationSpec

(Appears on: -GameServerSelector) +GameServerAllocation)

-

PlayerSelector is the filter options for a GameServer based on player counts

+

GameServerAllocationSpec is the spec for a GameServerAllocation

@@ -5027,95 +5064,136 @@

PlayerSelector

- -
-minAvailable
+multiClusterSetting
-int64 + +MultiClusterSetting +
+

MultiClusterPolicySelector if specified, multi-cluster policies are applied. +Otherwise, allocation will happen locally.

-maxAvailable
+required
-int64 + +GameServerSelector +
+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Required is the GameServer selector from which to choose GameServers from. +Defaults to all GameServers.

-
-

autoscaling.agones.dev/v1

-

-

Package v1 is the v1 version of the API.

-

-Resource Types: - -

FleetAutoscaler -

-

-

FleetAutoscaler is the data structure for a FleetAutoscaler resource

-

- - - - + + - - +selectors
+ + +[]GameServerSelector + + + + - + +
FieldDescription +preferred
+ + +[]GameServerSelector + + +
+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Preferred is an ordered list of preferred GameServer selectors +that are optional to be fulfilled, but will be searched before the required selector. +If the first selector is not matched, the selection attempts the second selector, and so on. +If any of the preferred selectors are matched, the required selector is not considered. +This is useful for things like smoke testing of new game servers.

+
-apiVersion
-string
- -autoscaling.agones.dev/v1 - +

Ordered list of GameServer label selectors. +If the first selector is not matched, the selection attempts the second selector, and so on. +This is useful for things like smoke testing of new game servers. +Note: This field can only be set if neither Required or Preferred is set.

-kind
-string +scheduling
+ +agones.dev/agones/pkg/apis.SchedulingStrategy + +
+

Scheduling strategy. Defaults to “Packed”.

FleetAutoscaler
metadata
- -Kubernetes meta/v1.ObjectMeta + +MetaPatch
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +

MetaPatch is optional custom metadata that is added to the game server at allocation +You can use this to tell the server necessary session data

+

GameServerAllocationState +(string alias)

+

+(Appears on: +GameServerAllocationStatus) +

+

+

GameServerAllocationState is the Allocation state

+

+

GameServerAllocationStatus +

+

+(Appears on: +GameServerAllocation) +

+

+

GameServerAllocationStatus is the status for an GameServerAllocation resource

+

+ + + + + + + + + +
FieldDescription
-spec
+state
- -FleetAutoscalerSpec + +GameServerAllocationState
-
-
- +

GameServerState is the current state of an GameServerAllocation, e.g. Allocated, or UnAllocated

+ + -
-fleetName
+gameServerName
string @@ -5125,58 +5203,59 @@

FleetAutoscaler

-policy
+ports
- -FleetAutoscalerPolicy + +[]GameServerStatusPort
-

Autoscaling policy

-sync
+address
- -FleetAutoscalerSync - +string
-(Optional) -

[Stage:Beta] -[FeatureFlag:CustomFasSyncInterval] -Sync defines when FleetAutoscalers runs autoscaling

+
+nodeName
+ +string + +
-status
+source
- -FleetAutoscalerStatus - +string
+

If the allocation is from a remote cluster, Source is the endpoint of the remote agones-allocator. +Otherwise, Source is “local”

-

BufferPolicy +

GameServerSelector

(Appears on: -FleetAutoscalerPolicy) +GameServerAllocationSpec)

-

BufferPolicy controls the desired behavior of the buffer policy.

+

GameServerSelector contains all the filter options for selecting +a GameServer for allocation.

@@ -5188,59 +5267,65 @@

BufferPolicy

-maxReplicas
+LabelSelector
-int32 + +Kubernetes meta/v1.LabelSelector +
-

MaxReplicas is the maximum amount of replicas that the fleet may have. -It must be bigger than both MinReplicas and BufferSize

+

+(Members of LabelSelector are embedded into this type.) +

+

See: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/

-minReplicas
+gameServerState
-int32 + +GameServerState +
-

MinReplicas is the minimum amount of replicas that the fleet must have -If zero, it is ignored. -If non zero, it must be smaller than MaxReplicas and bigger than BufferSize

+(Optional) +

[Stage:Beta] +[FeatureFlag:StateAllocationFilter] +GameServerState specifies which State is the filter to be used when attempting to retrieve a GameServer +via Allocation. Defaults to “Ready”. The only other option is “Allocated”, which can be used in conjunction with +label/annotation/player selectors to retrieve an already Allocated GameServer.

-bufferSize
+players
-k8s.io/apimachinery/pkg/util/intstr.IntOrString + +PlayerSelector +
-

BufferSize defines how many replicas the autoscaler tries to have ready all the time -Value can be an absolute number (ex: 5) or a percentage of desired gs instances (ex: 15%) -Absolute number is calculated from percentage by rounding up. -Example: when this is set to 20%, the autoscaler will make sure that 20% -of the fleet’s game server replicas are ready. When this is set to 20, -the autoscaler will make sure that there are 20 available game servers -Must be bigger than 0 -Note: by “ready” we understand in this case “non-allocated”; this is done to ensure robustness -and computation stability in different edge case (fleet just created, not enough -capacity in the cluster etc)

+(Optional) +

[Stage:Alpha] +[FeatureFlag:PlayerAllocationFilter] +Players provides a filter on minimum and maximum values for player capacity when retrieving a GameServer +through Allocation. Defaults to no limits.

-

FixedIntervalSync +

MetaPatch

(Appears on: -FleetAutoscalerSync) +GameServerAllocationSpec)

-

FixedIntervalSync controls the desired behavior of the fixed interval based sync.

+

MetaPatch is the metadata used to patch the GameServer metadata on allocation

@@ -5252,25 +5337,34 @@

FixedIntervalSync

+ + + +
-seconds
+labels
-int32 +map[string]string + +
+
+annotations
+ +map[string]string
-

Seconds defines how often we run fleet autoscaling in seconds

-

FleetAutoscaleRequest +

MultiClusterSetting

(Appears on: -FleetAutoscaleReview) +GameServerAllocationSpec)

-

FleetAutoscaleRequest defines the request to webhook autoscaler endpoint

+

MultiClusterSetting specifies settings for multi-cluster allocation.

@@ -5282,63 +5376,36 @@

FleetAutoscaleRequest

- - - - - - - -
-uid
- -k8s.io/apimachinery/pkg/types.UID - -
-

UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are -otherwise identical (parallel requests, requests when earlier requests did not modify etc) -The UID is meant to track the round trip (request/response) between the Autoscaler and the WebHook, not the user request. -It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.

-
-name
- -string - -
-

Name is the name of the Fleet being scaled

-
-namespace
+enabled
-string +bool
-

Namespace is the namespace associated with the request (if any).

-status
+policySelector
- -FleetStatus + +Kubernetes meta/v1.LabelSelector
-

The Fleet’s status values

-

FleetAutoscaleResponse +

PlayerSelector

(Appears on: -FleetAutoscaleReview) +GameServerSelector)

-

FleetAutoscaleResponse defines the response of webhook autoscaler endpoint

+

PlayerSelector is the filter options for a GameServer based on player counts

@@ -5350,45 +5417,39 @@

FleetAutoscaleResponse

- - - -
-uid
- -k8s.io/apimachinery/pkg/types.UID - -
-

UID is an identifier for the individual request/response. -This should be copied over from the corresponding FleetAutoscaleRequest.

-
-scale
+minAvailable
-bool +int64
-

Set to false if no scaling should occur to the Fleet

-replicas
+maxAvailable
-int32 +int64
-

The targeted replica count

-

FleetAutoscaleReview +
+

autoscaling.agones.dev/v1

+

+

Package v1 is the v1 version of the API.

+

+Resource Types: + +

FleetAutoscaler

-

FleetAutoscaleReview is passed to the webhook with a populated Request value, -and then returned with a populated Response.

+

FleetAutoscaler is the data structure for a FleetAutoscaler resource

@@ -5400,108 +5461,112 @@

FleetAutoscaleReview

+ + + + + + + + - - -
-request
+apiVersion
+string
+ +autoscaling.agones.dev/v1 + +
+kind
+string +
FleetAutoscaler
+metadata
- -FleetAutoscaleRequest + +Kubernetes meta/v1.ObjectMeta
+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-response
+spec
- -FleetAutoscaleResponse + +FleetAutoscalerSpec
-
-

FleetAutoscalerPolicy -

-

-(Appears on: -FleetAutoscalerSpec) -

-

-

FleetAutoscalerPolicy describes how to scale a fleet

-

+
+
- - - + + - - + +
FieldDescription +fleetName
+ +string + +
+
-type
+policy
- -FleetAutoscalerPolicyType + +FleetAutoscalerPolicy
-

Type of autoscaling policy.

+

Autoscaling policy

-buffer
+sync
- -BufferPolicy + +FleetAutoscalerSync
(Optional) -

Buffer policy config params. Present only if FleetAutoscalerPolicyType = Buffer.

+

[Stage:Beta] +[FeatureFlag:CustomFasSyncInterval] +Sync defines when FleetAutoscalers runs autoscaling

+
-webhook
+status
- -WebhookPolicy + +FleetAutoscalerStatus -(Optional) -

Webhook policy config params. Present only if FleetAutoscalerPolicyType = Webhook.

-

FleetAutoscalerPolicyType -(string alias)

-

-(Appears on: -FleetAutoscalerPolicy) -

-

-

FleetAutoscalerPolicyType is the policy for autoscaling -for a given Fleet

-

-

FleetAutoscalerSpec +

BufferPolicy

(Appears on: -FleetAutoscaler) +FleetAutoscalerPolicy)

-

FleetAutoscalerSpec is the spec for a Fleet Scaler

+

BufferPolicy controls the desired behavior of the buffer policy.

@@ -5513,53 +5578,59 @@

FleetAutoscalerSpec

-fleetName
+maxReplicas
-string +int32
+

MaxReplicas is the maximum amount of replicas that the fleet may have. +It must be bigger than both MinReplicas and BufferSize

-policy
+minReplicas
- -FleetAutoscalerPolicy - +int32
-

Autoscaling policy

+

MinReplicas is the minimum amount of replicas that the fleet must have +If zero, it is ignored. +If non zero, it must be smaller than MaxReplicas and bigger than BufferSize

-sync
+bufferSize
- -FleetAutoscalerSync - +k8s.io/apimachinery/pkg/util/intstr.IntOrString
-(Optional) -

[Stage:Beta] -[FeatureFlag:CustomFasSyncInterval] -Sync defines when FleetAutoscalers runs autoscaling

+

BufferSize defines how many replicas the autoscaler tries to have ready all the time +Value can be an absolute number (ex: 5) or a percentage of desired gs instances (ex: 15%) +Absolute number is calculated from percentage by rounding up. +Example: when this is set to 20%, the autoscaler will make sure that 20% +of the fleet’s game server replicas are ready. When this is set to 20, +the autoscaler will make sure that there are 20 available game servers +Must be bigger than 0 +Note: by “ready” we understand in this case “non-allocated”; this is done to ensure robustness +and computation stability in different edge case (fleet just created, not enough +capacity in the cluster etc)

-

FleetAutoscalerStatus +

FixedIntervalSync

(Appears on: -FleetAutoscaler) +FleetAutoscalerSync)

-

FleetAutoscalerStatus defines the current status of a FleetAutoscaler

+

FixedIntervalSync controls the desired behavior of the fixed interval based sync.

@@ -5571,75 +5642,93 @@

FleetAutoscalerStatus

+ +
-currentReplicas
+seconds
int32
-

CurrentReplicas is the current number of gameserver replicas -of the fleet managed by this autoscaler, as last seen by the autoscaler

+

Seconds defines how often we run fleet autoscaling in seconds

+

FleetAutoscaleRequest +

+

+(Appears on: +FleetAutoscaleReview) +

+

+

FleetAutoscaleRequest defines the request to webhook autoscaler endpoint

+

+ + + + + + + +
FieldDescription
-desiredReplicas
+uid
-int32 +k8s.io/apimachinery/pkg/types.UID
-

DesiredReplicas is the desired number of gameserver replicas -of the fleet managed by this autoscaler, as last calculated by the autoscaler

+

UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are +otherwise identical (parallel requests, requests when earlier requests did not modify etc) +The UID is meant to track the round trip (request/response) between the Autoscaler and the WebHook, not the user request. +It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.

-lastScaleTime
+name
- -Kubernetes meta/v1.Time - +string
-(Optional) -

lastScaleTime is the last time the FleetAutoscaler scaled the attached fleet,

+

Name is the name of the Fleet being scaled

-ableToScale
+namespace
-bool +string
-

AbleToScale indicates that we can access the target fleet

+

Namespace is the namespace associated with the request (if any).

-scalingLimited
+status
-bool + +FleetStatus +
-

ScalingLimited indicates that the calculated scale would be above or below the range -defined by MinReplicas and MaxReplicas, and has thus been capped.

+

The Fleet’s status values

-

FleetAutoscalerSync +

FleetAutoscaleResponse

(Appears on: -FleetAutoscalerSpec) +FleetAutoscaleReview)

-

FleetAutoscalerSync describes when to sync a fleet

+

FleetAutoscaleResponse defines the response of webhook autoscaler endpoint

@@ -5651,52 +5740,45 @@

FleetAutoscalerSync

+ + + +
-type
+uid
- -FleetAutoscalerSyncType - +k8s.io/apimachinery/pkg/types.UID
-

Type of autoscaling sync.

+

UID is an identifier for the individual request/response. +This should be copied over from the corresponding FleetAutoscaleRequest.

-fixedInterval
+scale
- -FixedIntervalSync - +bool
-(Optional) -

FixedInterval config params. Present only if FleetAutoscalerSyncType = FixedInterval.

+

Set to false if no scaling should occur to the Fleet

+
+replicas
+ +int32 + +
+

The targeted replica count

-

FleetAutoscalerSyncType -(string alias)

-

-(Appears on: -FleetAutoscalerSync) -

-

-

FleetAutoscalerSyncType is the sync strategy for a given Fleet

-

-

WebhookPolicy +

FleetAutoscaleReview

-(Appears on: -FleetAutoscalerPolicy) -

-

-

WebhookPolicy controls the desired behavior of the webhook policy. -It contains the description of the webhook autoscaler service -used to form url which is accessible inside the cluster

+

FleetAutoscaleReview is passed to the webhook with a populated Request value, +and then returned with a populated Response.

@@ -5708,79 +5790,38 @@

WebhookPolicy

- - - -
-url
- -string - -
-(Optional) -

url gives the location of the webhook, in standard URL form -(scheme://host:port/path). Exactly one of url or service -must be specified.

-

The host should not refer to a service running in the cluster; use -the service field instead. The host might be resolved via external -DNS in some apiservers (e.g., kube-apiserver cannot resolve -in-cluster DNS as that would be a layering violation). host may -also be an IP address.

-

Please note that using localhost or 127.0.0.1 as a host is -risky unless you take great care to run this webhook on all hosts -which run an apiserver which might need to make calls to this -webhook. Such installs are likely to be non-portable, i.e., not easy -to turn up in a new cluster.

-

The scheme must be “https”; the URL must begin with “https://”.

-

A path is optional, and if present may be any string permissible in -a URL. You may use the path to pass an arbitrary string to the -webhook, for example, a cluster identifier.

-

Attempting to use a user or basic auth e.g. “user:password@” is not -allowed. Fragments (“#…”) and query parameters (“?…”) are not -allowed, either.

-
-service
+request
- -Kubernetes admissionregistration/v1.ServiceReference + +FleetAutoscaleRequest
-(Optional) -

service is a reference to the service for this webhook. Either -service or url must be specified.

-

If the webhook is running within the cluster, then you should use service.

-caBundle
+response
-[]byte + +FleetAutoscaleResponse +
-(Optional) -

caBundle is a PEM encoded CA bundle which will be used to validate the webhook’s server certificate. -If unspecified, system trust roots on the apiserver are used.

-
-

multicluster.agones.dev/v1

+

FleetAutoscalerPolicy +

-

Package v1 is the v1 version of the API.

+(Appears on: +FleetAutoscalerSpec)

-Resource Types: - -

GameServerAllocationPolicy -

-

GameServerAllocationPolicy is the Schema for the gameserverallocationpolicies API

+

FleetAutoscalerPolicy describes how to scale a fleet

@@ -5792,53 +5833,79 @@

GameServerAllocat

- - - - + + +
-apiVersion
-string
- -multicluster.agones.dev/v1 - +type
+ + +FleetAutoscalerPolicyType + +
-kind
-string +

Type of autoscaling policy.

GameServerAllocationPolicy
-metadata
+buffer
- -Kubernetes meta/v1.ObjectMeta + +BufferPolicy
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +(Optional) +

Buffer policy config params. Present only if FleetAutoscalerPolicyType = Buffer.

-spec
+webhook
- -GameServerAllocationPolicySpec + +WebhookPolicy
-
-
+(Optional) +

Webhook policy config params. Present only if FleetAutoscalerPolicyType = Webhook.

+
+

FleetAutoscalerPolicyType +(string alias)

+

+(Appears on: +FleetAutoscalerPolicy) +

+

+

FleetAutoscalerPolicyType is the policy for autoscaling +for a given Fleet

+

+

FleetAutoscalerSpec +

+

+(Appears on: +FleetAutoscaler) +

+

+

FleetAutoscalerSpec is the spec for a Fleet Scaler

+

+ + + + + + + - -
FieldDescription
-priority
+fleetName
-int32 +string
@@ -5846,39 +5913,43 @@

GameServerAllocat

-weight
+policy
-int + +FleetAutoscalerPolicy +
+

Autoscaling policy

-connectionInfo
+sync
- -ClusterConnectionInfo + +FleetAutoscalerSync
-
+(Optional) +

[Stage:Beta] +[FeatureFlag:CustomFasSyncInterval] +Sync defines when FleetAutoscalers runs autoscaling

-

ClusterConnectionInfo +

FleetAutoscalerStatus

(Appears on: -GameServerAllocationPolicySpec) +FleetAutoscaler)

-

ClusterConnectionInfo defines the connection information for a cluster

+

FleetAutoscalerStatus defines the current status of a FleetAutoscaler

@@ -5890,67 +5961,75 @@

ClusterConnectionInfo

-clusterName
+currentReplicas
-string +int32
-

Optional: the name of the targeted cluster

+

CurrentReplicas is the current number of gameserver replicas +of the fleet managed by this autoscaler, as last seen by the autoscaler

-allocationEndpoints
+desiredReplicas
-[]string +int32
-

The endpoints for the allocator service in the targeted cluster. -If the AllocationEndpoints is not set, the allocation happens on local cluster. -If there are multiple endpoints any of the endpoints that can handle allocation request should suffice

+

DesiredReplicas is the desired number of gameserver replicas +of the fleet managed by this autoscaler, as last calculated by the autoscaler

-secretName
+lastScaleTime
-string + +Kubernetes meta/v1.Time +
-

The name of the secret that contains TLS client certificates to connect the allocator server in the targeted cluster

+(Optional) +

lastScaleTime is the last time the FleetAutoscaler scaled the attached fleet,

-namespace
+ableToScale
-string +bool
-

The cluster namespace from which to allocate gameservers

+

AbleToScale indicates that we can access the target fleet

-serverCa
+scalingLimited
-[]byte +bool
-

The PEM encoded server CA, used by the allocator client to authenticate the remote server.

+

ScalingLimited indicates that the calculated scale would be above or below the range +defined by MinReplicas and MaxReplicas, and has thus been capped.

-

ConnectionInfoIterator +

FleetAutoscalerSync

-

ConnectionInfoIterator an iterator on ClusterConnectionInfo

+(Appears on: +FleetAutoscalerSpec) +

+

+

FleetAutoscalerSync describes when to sync a fleet

@@ -5962,58 +6041,52 @@

ConnectionInfoIterato

- - - - - - - -
-currPriority
- -int - -
-

currPriority Current priority index from the orderedPriorities

-
-orderedPriorities
- -[]int32 - -
-

orderedPriorities list of ordered priorities

-
-priorityToCluster
+type
-map[int32]map[string][]*agones.dev/agones/pkg/apis/multicluster/v1.GameServerAllocationPolicy + +FleetAutoscalerSyncType +
-

priorityToCluster Map of priority to cluster-policies map

+

Type of autoscaling sync.

-clusterBlackList
+fixedInterval
-map[string]bool + +FixedIntervalSync +
-

clusterBlackList the cluster blacklist for the clusters that has already returned

+(Optional) +

FixedInterval config params. Present only if FleetAutoscalerSyncType = FixedInterval.

-

GameServerAllocationPolicySpec +

FleetAutoscalerSyncType +(string alias)

+

+(Appears on: +FleetAutoscalerSync) +

+

+

FleetAutoscalerSyncType is the sync strategy for a given Fleet

+

+

WebhookPolicy

(Appears on: -GameServerAllocationPolicy) +FleetAutoscalerPolicy)

-

GameServerAllocationPolicySpec defines the desired state of GameServerAllocationPolicy

+

WebhookPolicy controls the desired behavior of the webhook policy. +It contains the description of the webhook autoscaler service +used to form url which is accessible inside the cluster

@@ -6025,34 +6098,62 @@

GameServerAll

-priority
+url
-int32 +string
+(Optional) +

url gives the location of the webhook, in standard URL form +(scheme://host:port/path). Exactly one of url or service +must be specified.

+

The host should not refer to a service running in the cluster; use +the service field instead. The host might be resolved via external +DNS in some apiservers (e.g., kube-apiserver cannot resolve +in-cluster DNS as that would be a layering violation). host may +also be an IP address.

+

Please note that using localhost or 127.0.0.1 as a host is +risky unless you take great care to run this webhook on all hosts +which run an apiserver which might need to make calls to this +webhook. Such installs are likely to be non-portable, i.e., not easy +to turn up in a new cluster.

+

The scheme must be “https”; the URL must begin with “https://”.

+

A path is optional, and if present may be any string permissible in +a URL. You may use the path to pass an arbitrary string to the +webhook, for example, a cluster identifier.

+

Attempting to use a user or basic auth e.g. “user:password@” is not +allowed. Fragments (“#…”) and query parameters (“?…”) are not +allowed, either.

-weight
+service
-int + +Kubernetes admissionregistration/v1.ServiceReference +
+(Optional) +

service is a reference to the service for this webhook. Either +service or url must be specified.

+

If the webhook is running within the cluster, then you should use service.

-connectionInfo
+caBundle
- -ClusterConnectionInfo - +[]byte
+(Optional) +

caBundle is a PEM encoded CA bundle which will be used to validate the webhook’s server certificate. +If unspecified, system trust roots on the apiserver are used.