Skip to content

Commit

Permalink
simple-game-server: Adds a graceful termination delay (#3436)
Browse files Browse the repository at this point in the history
* simple-game-server: Adds a graceful termination delay

* Adds `gracefulTerminationDelaySec` to imitate a gameserver delaying
after SIGTERM (eviction).

* Adds test/eviction/evictpod.go, which I used to test the above.

This should allow easier testing in autoscaling scenarios (including
eventually possibly e2e tests with eviction: safe: Always).
  • Loading branch information
zmerlynn authored Oct 18, 2023
1 parent 91b24cb commit f3ed290
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 8 deletions.
4 changes: 2 additions & 2 deletions examples/simple-game-server/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ WITH_ARM64 ?= 1
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
project_path := $(dir $(mkfile_path))
ifeq ($(REPOSITORY),)
server_tag := simple-game-server:0.18
server_tag := simple-game-server:0.19
else
server_tag := $(REPOSITORY)/simple-game-server:0.18
server_tag := $(REPOSITORY)/simple-game-server:0.19
endif

ifeq ($(WITH_WINDOWS), 1)
Expand Down
4 changes: 2 additions & 2 deletions examples/simple-game-server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
Expand Down
8 changes: 4 additions & 4 deletions examples/simple-game-server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
3 changes: 3 additions & 0 deletions examples/simple-game-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func main() {
shutdownDelaySec := flag.Int("automaticShutdownDelaySec", 0, "If greater than zero, automatically shut down the server this many seconds after the server becomes allocated (cannot be used if automaticShutdownDelayMin is set)")
readyDelaySec := flag.Int("readyDelaySec", 0, "If greater than zero, wait this many seconds each time before marking the game server as ready")
readyIterations := flag.Int("readyIterations", 0, "If greater than zero, return to a ready state this number of times before shutting down")
gracefulTerminationDelaySec := flag.Int("gracefulTerminationDelaySec", 0, "Delay after we've been asked to terminate (by SIGKILL or automaticShutdownDelaySec)")
udp := flag.Bool("udp", true, "Server will listen on UDP")
tcp := flag.Bool("tcp", false, "Server will listen on TCP")

Expand Down Expand Up @@ -122,6 +123,8 @@ func main() {
}

<-sigCtx.Done()
log.Printf("Waiting %d seconds before exiting", *gracefulTerminationDelaySec)
time.Sleep(time.Duration(*gracefulTerminationDelaySec) * time.Second)
os.Exit(0)
}

Expand Down
66 changes: 66 additions & 0 deletions test/eviction/evictpod.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2023 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

// evictpod.go --pod <pod> --namespace <namespace> initiates a pod eviction
// using the k8s eviction API.
package main

import (
"context"
"flag"
"log"
"path/filepath"

policy "k8s.io/api/policy/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
)

// Borrowed from https://stackoverflow.com/questions/62803041/how-to-evict-or-delete-pods-from-kubernetes-using-golang-client
func evictPod(ctx context.Context, client *kubernetes.Clientset, name, namespace string) error {
return client.PolicyV1().Evictions(namespace).Evict(ctx, &policy.Eviction{
ObjectMeta: meta_v1.ObjectMeta{
Name: name,
Namespace: namespace,
}})
}

func main() {
ctx := context.Background()

kubeconfig := flag.String("kubeconfig", filepath.Join(homedir.HomeDir(), ".kube", "config"), "(optional) absolute path to the kubeconfig file")
namespace := flag.String("namespace", "default", "Namespace (defaults to `default`)")
pod := flag.String("pod", "", "Pod name (required)")
flag.Parse()

if *pod == "" {
log.Fatal("--pod must be non-empty")
}

config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
log.Fatalf("Could not build config: %v", err)
}

kubeClient, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalf("Could not create the kubernetes clientset: %v", err)
}

if err := evictPod(ctx, kubeClient, *pod, *namespace); err != nil {
log.Fatalf("Pod eviction failed: %v", err)
}
}

0 comments on commit f3ed290

Please sign in to comment.