Skip to content

Commit

Permalink
Passthrough autopilot - Adds an AutopilotPassthroughPort Feature Gate…
Browse files Browse the repository at this point in the history
… and new pod label (#3809)

Towards supporting Passthrough on Autopilot
  • Loading branch information
vicentefb authored May 1, 2024
1 parent 2877209 commit ef2d0b5
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions install/helm/agones/defaultfeaturegates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ PlayerAllocationFilter: false
PlayerTracking: false

# Dev features
FeatureAutopilotPassthroughPort: true

# Example feature
Example: false
3 changes: 3 additions & 0 deletions pkg/apis/agones/v1/gameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ const (
// GameServerPodLabel is the label that the name of the GameServer
// is set on the Pod the GameServer controls
GameServerPodLabel = agones.GroupName + "/gameserver"
// GameServerPortPolicyPodLabel is the label to identify the port policy
// of the pod
GameServerPortPolicyPodLabel = agones.GroupName + "/port"
// GameServerContainerAnnotation is the annotation that stores
// which container is the container that runs the dedicated game server
GameServerContainerAnnotation = agones.GroupName + "/container"
Expand Down
19 changes: 19 additions & 0 deletions pkg/cloudproduct/gke/gke.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,21 @@ func (*gkeAutopilot) ValidateScheduling(ss apis.SchedulingStrategy, fldPath *fie
}

func (*gkeAutopilot) MutateGameServerPod(gss *agonesv1.GameServerSpec, pod *corev1.Pod) error {
setPassthroughLabel(gss, pod)
setPrimaryContainer(pod, gss.Container)
podSpecSeccompUnconfined(&pod.Spec)
return nil
}

// setPassthroughLabel sets the agones.dev/port: "autopilot-passthrough" label to the game server container.
// This will help to back the container port from the allocated port using an objectSelector of this label
// in GameServers that are using Passthrough Port Policy
func setPassthroughLabel(gs *agonesv1.GameServerSpec, pod *corev1.Pod) {
if runtime.FeatureEnabled(runtime.FeatureAutopilotPassthroughPort) && hasPortPolicy(gs, agonesv1.Passthrough) {
pod.ObjectMeta.Labels[agonesv1.GameServerPortPolicyPodLabel] = "autopilot-passthrough"
}
}

// setPrimaryContainer sets the autopilot.gke.io/primary-container annotation to the game server container.
// This acts as a hint to Autopilot for which container to add resources to during resource adjustment.
// See https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-resource-requests#autopilot-resource-management
Expand Down Expand Up @@ -223,6 +233,15 @@ func setEvictionNoExtended(ev *agonesv1.Eviction, pod *corev1.Pod) error {
return nil
}

func hasPortPolicy(gs *agonesv1.GameServerSpec, portPolicy agonesv1.PortPolicy) bool {
for _, p := range gs.Ports {
if p.PortPolicy == portPolicy {
return true
}
}
return false
}

type autopilotPortAllocator struct {
minPort int32
maxPort int32
Expand Down
96 changes: 96 additions & 0 deletions pkg/cloudproduct/gke/gke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
package gke

import (
"fmt"
"testing"

"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"
Expand Down Expand Up @@ -222,6 +224,100 @@ func TestPodSeccompUnconfined(t *testing.T) {
}
}

func TestSetPassthroughLabel(t *testing.T) {
for name, tc := range map[string]struct {
pod *corev1.Pod
wantPod *corev1.Pod
ports []agonesv1.GameServerPort
features string
}{
"gameserver with with Passthrough port policy adds label to pod": {
features: fmt.Sprintf("%s=true", runtime.FeatureAutopilotPassthroughPort),

pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
ports: []agonesv1.GameServerPort{
{
Name: "awesome-udp",
PortPolicy: agonesv1.Passthrough,
ContainerPort: 1234,
Protocol: corev1.ProtocolUDP,
},
},
wantPod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{
agonesv1.GameServerPortPolicyPodLabel: "autopilot-passthrough",
},
},
},
},
"gameserver with Static port policy does not add label to pod": {
features: fmt.Sprintf("%s=true", runtime.FeatureAutopilotPassthroughPort),

pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
ports: []agonesv1.GameServerPort{
{
Name: "awesome-udp",
PortPolicy: agonesv1.Static,
ContainerPort: 1234,
Protocol: corev1.ProtocolUDP,
},
},
wantPod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
},
"gameserver, no feature gate, with Passthrough port policy does not add label to pod": {
features: fmt.Sprintf("%s=false", runtime.FeatureAutopilotPassthroughPort),

pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
ports: []agonesv1.GameServerPort{
{
Name: "awesome-udp",
PortPolicy: agonesv1.Passthrough,
ContainerPort: 1234,
Protocol: corev1.ProtocolUDP,
},
},
wantPod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
},
} {
t.Run(name, func(t *testing.T) {
runtime.FeatureTestMutex.Lock()
defer runtime.FeatureTestMutex.Unlock()
require.NoError(t, runtime.ParseFeatures(tc.features))
gs := (&autopilotPortAllocator{minPort: 7000, maxPort: 8000}).Allocate(&agonesv1.GameServer{Spec: agonesv1.GameServerSpec{Ports: tc.ports}})
pod := tc.pod.DeepCopy()
setPassthroughLabel(&gs.Spec, pod)
assert.Equal(t, tc.wantPod, pod)
})
}
}

func TestSetEvictionNoExtended(t *testing.T) {
emptyPodAnd := func(f func(*corev1.Pod)) *corev1.Pod {
pod := &corev1.Pod{
Expand Down
4 changes: 4 additions & 0 deletions pkg/util/runtime/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ const (
////////////////
// Dev features

// FeatureAutopilotPassthroughPort is a feature flag that enables/disables Passthrough Port Policy.
FeatureAutopilotPassthroughPort Feature = "PassthroughPortPolicy"

////////////////
// Example feature

Expand Down Expand Up @@ -109,6 +112,7 @@ var (
FeaturePlayerTracking: false,

// Dev features
FeatureAutopilotPassthroughPort: true,

// Example feature
FeatureExample: false,
Expand Down

0 comments on commit ef2d0b5

Please sign in to comment.