Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: differentiated updates to GameServers #120

Merged
merged 1 commit into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions apis/v1alpha1/gameserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ type GameServerSpec struct {
UpdatePriority *intstr.IntOrString `json:"updatePriority,omitempty"`
DeletionPriority *intstr.IntOrString `json:"deletionPriority,omitempty"`
NetworkDisabled bool `json:"networkDisabled,omitempty"`
// Containers can be used to make the corresponding GameServer container fields
// different from the fields defined by GameServerTemplate in GameServerSetSpec.
Containers []GameServerContainer `json:"containers,omitempty"`
}

type GameServerContainer struct {
// Name indicates the name of the container to update.
Name string `json:"name"`
// Image indicates the image of the container to update.
// When Image updated, pod.spec.containers[*].image will be updated immediately.
Image string `json:"image,omitempty"`
// Resources indicates the resources of the container to update.
// When Resources updated, pod.spec.containers[*].Resources will be not updated immediately,
// which will be updated when pod recreate.
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
}

type GameServerState string
Expand Down
23 changes: 23 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions config/crd/bases/game.kruise.io_gameservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,54 @@ spec:
spec:
description: GameServerSpec defines the desired state of GameServer
properties:
containers:
description: Containers can be used to make the corresponding GameServer
container fields different from the fields defined by GameServerTemplate
in GameServerSetSpec.
items:
properties:
image:
description: Image indicates the image of the container to update.
When Image updated, pod.spec.containers[*].image will be updated
immediately.
type: string
name:
description: Name indicates the name of the container to update.
type: string
resources:
description: Resources indicates the resources of the container
to update. When Resources updated, pod.spec.containers[*].Resources
will be not updated immediately, which will be updated when
pod recreate.
properties:
limits:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount of compute
resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
requests:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum amount of compute
resources required. If Requests is omitted for a container,
it defaults to Limits if that is explicitly specified,
otherwise to an implementation-defined value. More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
required:
- name
type: object
type: array
deletionPriority:
anyOf:
- type: integer
Expand Down
50 changes: 50 additions & 0 deletions config/crd/bases/game.kruise.io_gameserversets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,56 @@ spec:
serviceQualityAction:
items:
properties:
containers:
description: Containers can be used to make the corresponding
GameServer container fields different from the fields
defined by GameServerTemplate in GameServerSetSpec.
items:
properties:
image:
description: Image indicates the image of the container
to update. When Image updated, pod.spec.containers[*].image
will be updated immediately.
type: string
name:
description: Name indicates the name of the container
to update.
type: string
resources:
description: Resources indicates the resources of
the container to update. When Resources updated,
pod.spec.containers[*].Resources will be not updated
immediately, which will be updated when pod recreate.
properties:
limits:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount
of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
requests:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum
amount of compute resources required. If Requests
is omitted for a container, it defaults to
Limits if that is explicitly specified, otherwise
to an implementation-defined value. More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
required:
- name
type: object
type: array
deletionPriority:
anyOf:
- type: integer
Expand Down
18 changes: 18 additions & 0 deletions docs/en/user_manuals/CRD_field_description.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,24 @@ type GameServerSpec struct {
// Whether to perform network isolation and cut off the access layer network
// Default is false
NetworkDisabled bool `json:"networkDisabled,omitempty"`

// Containers can be used to make the corresponding GameServer container fields
// different from the fields defined by GameServerTemplate in GameServerSetSpec.
Containers []GameServerContainer `json:"containers,omitempty"`
}

type GameServerContainer struct {
// Name indicates the name of the container to update.
Name string `json:"name"`

// Image indicates the image of the container to update.
// When Image updated, pod.spec.containers[*].image will be updated immediately.
Image string `json:"image,omitempty"`

// Resources indicates the resources of the container to update.
// When Resources updated, pod.spec.containers[*].Resources will be not updated immediately,
// which will be updated when pod recreate.
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
}
```

Expand Down
18 changes: 18 additions & 0 deletions docs/中文/用户手册/CRD字段说明.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,25 @@ type GameServerSpec struct {

// 是否进行网络隔离、切断接入层网络,默认为false
NetworkDisabled bool `json:"networkDisabled,omitempty"`

// 使对应的GameServer Containers字段与GameServerSetSpec中GameServerTemplate定义的字段不同,意味着该GameServer可以拥有独立的参数配置。
// 当前支持更改 Image 与 Resources
Containers []GameServerContainer `json:"containers,omitempty"`
}

type GameServerContainer struct {
// Name 表示要更新的容器的名称。
Name string `json:"name"`

// Image 表示要更新的容器的镜像。
// 当Image更新时,pod.spec.containers[*].image会立即更新。
Image string `json:"image,omitempty"`

// Resources 表示要更新的容器的资源。
// 当Resources更新时,pod.spec.containers[*].Resources不会立即更新,它会在pod重建时更新。
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
}

```

### GameServerStatus
Expand Down
36 changes: 34 additions & 2 deletions pkg/controllers/gameserver/gameserver_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,17 @@
}
}

if len(newLabels) != 0 || len(newAnnotations) != 0 {
patchPod := map[string]interface{}{"metadata": map[string]map[string]string{"labels": newLabels, "annotations": newAnnotations}}
// sync pod containers when the containers(images) in GameServer are different from that in pod.
containers := manager.syncPodContainers(gs.Spec.Containers, pod.DeepCopy().Spec.Containers)

if len(newLabels) != 0 || len(newAnnotations) != 0 || containers != nil {
patchPod := make(map[string]interface{})
if len(newLabels) != 0 || len(newAnnotations) != 0 {
patchPod["metadata"] = map[string]map[string]string{"labels": newLabels, "annotations": newAnnotations}
}
if containers != nil {
patchPod["spec"] = map[string]interface{}{"containers": containers}
}

Check warning on line 186 in pkg/controllers/gameserver/gameserver_manager.go

View check run for this annotation

Codecov / codecov/patch

pkg/controllers/gameserver/gameserver_manager.go#L185-L186

Added lines #L185 - L186 were not covered by tests
patchPodBytes, err := json.Marshal(patchPod)
if err != nil {
return err
Expand Down Expand Up @@ -348,6 +357,29 @@
return spec, newGsConditions
}

func (manager GameServerManager) syncPodContainers(gsContainers []gameKruiseV1alpha1.GameServerContainer, podContainers []corev1.Container) []corev1.Container {
var newContainers []corev1.Container
for _, podContainer := range podContainers {
for _, gsContainer := range gsContainers {
if gsContainer.Name == podContainer.Name {
var newContainer corev1.Container
newContainer.Name = podContainer.Name
changed := false
if gsContainer.Image != "" && gsContainer.Image != podContainer.Image {
newContainer.Image = gsContainer.Image
changed = true
}

if changed {
newContainers = append(newContainers, newContainer)
}
}
}
}

return newContainers
}

func NewGameServerManager(gs *gameKruiseV1alpha1.GameServer, pod *corev1.Pod, c client.Client, recorder record.EventRecorder) Control {
return &GameServerManager{
gameServer: gs,
Expand Down
55 changes: 55 additions & 0 deletions pkg/controllers/gameserver/gameserver_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,3 +569,58 @@ func TestSyncNetworkStatus(t *testing.T) {
}
}
}

func TestSyncPodContainers(t *testing.T) {
tests := []struct {
gsContainers []gameKruiseV1alpha1.GameServerContainer
podContainers []corev1.Container
newContainers []corev1.Container
}{
// case 0
{
gsContainers: nil,
podContainers: []corev1.Container{
{
Name: "A",
Image: "A-v1",
},
},
newContainers: nil,
},

// case 1
{
gsContainers: []gameKruiseV1alpha1.GameServerContainer{
{
Name: "A",
Image: "A-v2",
},
},
podContainers: []corev1.Container{
{
Name: "A",
Image: "A-v1",
},
{
Name: "B",
Image: "B-v1",
},
},
newContainers: []corev1.Container{
{
Name: "A",
Image: "A-v2",
},
},
},
}

for i, test := range tests {
expect := test.newContainers
manager := &GameServerManager{}
actual := manager.syncPodContainers(test.gsContainers, test.podContainers)
if !reflect.DeepEqual(expect, actual) {
t.Errorf("case %d: expect newContainers %v, but actually got %v", i, expect, actual)
}
}
}
Loading
Loading