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

Game operation and maintenance API #166

Open
chrisliu1995 opened this issue Jul 30, 2024 · 5 comments
Open

Game operation and maintenance API #166

chrisliu1995 opened this issue Jul 30, 2024 · 5 comments

Comments

@chrisliu1995
Copy link
Member

kruise-game contains two CRDs GameServer and GameServerSet. Game servers can be managed by deploying or changing the corresponding CR. However, in actual production use, a release or operation and maintenance action is often a combination of a series of operations on CR. For example, set the GameServer image tag with ids 1, 7, and 10 to v0.3; adjust the update priority of GameServer with ids 5, 9, and 11 before updating the game server, etc.

Therefore, a set of APIs with operation and maintenance semantics is needed, which users can directly use or integrate into their own operation and maintenance platform to facilitate operation and maintenance operations.

@kairveeehh
Copy link

Heyy @chrisliu1995 i am kairvee and would like to take up this issue under LFX mentorship programme as it aligns with my interests and skills , please inform me over the further things ,
thanks.

@kunal-511
Copy link

Hello @chrisliu1995
I'm excited to work on the Kruise-game project, focusing on GameServer and GameServerSet CRDs. I'm currently learning and developing relevant skills to contribute to designing and implementing APIs with operation and maintenance semantics. I understand the need to simplify complex production operations and am eager to help. With my passion for this project and commitment to learning, I'm confident in my ability to make a meaningful contribution. I look forward to discussing this opportunity further.

@kairveeehh
Copy link

kruise-game contains two CRDs GameServer and GameServerSet. Game servers can be managed by deploying or changing the corresponding CR. However, in actual production use, a release or operation and maintenance action is often a combination of a series of operations on CR. For example, set the GameServer image tag with ids 1, 7, and 10 to v0.3; adjust the update priority of GameServer with ids 5, 9, and 11 before updating the game server, etc.

Therefore, a set of APIs with operation and maintenance semantics is needed, which users can directly use or integrate into their own operation and maintenance platform to facilitate operation and maintenance operations.

@chrisliu1995 can you please update me over any pretests/ issues to work on before applying?

@Nihit25
Copy link

Nihit25 commented Aug 20, 2024

Hey everyone!

I'm Nihit, a pre-final year student from the Indian Institute of Information Technology, Gwalior, majoring in Information Technology. I'm a tech enthusiast with a strong passion for open-source. I've applied for this project and have been working on this issue for some time now. I would greatly appreciate any guidance or clarity on how best to approach this issue. I'm really looking forward to solving this problem and contributing to the project as much as possible.

@ScottL97
Copy link

Based on the above requirements, I have the following initial thoughts:

Features

  • A library provides filter and updater for OKG GS. It can be used by Golang packages, command line tools, RESTful API and so on.For example:
    • It can be the container image to filter GS list or patch spec.opsState/annotations/labels of filtered GS list for Argo workflow steps.
    • It can be the container image to choose a GS for match maker or gateway pod.
    • It can be the GS sidecar container image to patch its owner GS.
    • It can be used to achieve A/B test by filter and updater.

Architecture

image

Query Layer

  • Query/Update GS list filtered by parsed filter provided by Filter Layer.

Filter Layer

Strategy

  • We need the Filter Layer since the same functionality provided in mutiple facades needs to be abstracted.
  • Logic syntax is needed since the filter condition may be a combination of multiple conditions.
  • Regular expressions need to be supported for flexible filtering.

Filter syntax

  • Learn from MongoDB query syntax to provide a simplified Filter syntax.
  • There are predefined operators starting with $ (such as comparison operators, logical operators, function operators) and matching strings that do not start with $.
  • To standardize semantics, an object can only contain one key-value pair, for example:
// legal:
{
    "$and": [
        {
            "metadata.annotations.version": "java21"
        },
        {
            "spec.opsState": "Maintaining"
        }
    ]
}
// Illegal:
{
    "$and": [
        {
            "metadata.annotations.version": "java21",
            "spec.opsState": "Maintaining"
        }
    ]
}
  • In the following content, the value represents a number or string, and the object and array are JSON objects and arrays.

Comparison Operators

  • $gt/$lt/$ne/$eq/$in:greater than/less than/not equal/equal/included,where $in acts on an array of values (such as strings, numbers), and the rest act on a value.

Logical Operators

  • $and/$or/$not: $and/$or act on an array of values, $not acts on an object.

Examples

This is a simplified GS example:

apiVersion: game.kruise.io/v1alpha1
kind: GameServer
metadata:
  annotations:
    server: minecraft-pvp-0
    version: java21
  generation: 1
  labels:
    app.kubernetes.io/name: minecraft-pvp
    game.kruise.io/owner-gss: minecraft-pvp
  name: minecraft-pvp-0
  namespace: minecraft
  ownerReferences:
  - apiVersion: v1
    blockOwnerDeletion: true
    controller: true
    kind: Pod
    name: minecraft-pvp-0
    uid: c1610944-1fb1-44c7-8ec0-9d24b4aae09c
spec:
  deletionPriority: 0
  opsState: None
  updatePriority: 0
status:
  currentState: Ready
  deletionPriority: "0"
  desiredState: Ready
  lastTransitionTime: "2024-09-09T04:33:18Z"
  networkStatus:
    createTime: "2024-09-02T06:58:59Z"
    currentNetworkState: Ready
    desiredNetworkState: Ready
    externalAddresses:
    - endPoint: nlb-xxx.cn-hangzhou.nlb.aliyuncs.com
      ip: ""
      ports:
      - name: "3000"
        port: 1273
        protocol: UDP
    internalAddresses:
    - ip: 172.20.4.77
      ports:
      - name: "3000"
        port: 3000
        protocol: UDP
    networkType: AlibabaCloud-NLB
  podStatus:
    containerStatuses:
    - image: itzg/minecraft-server:java21
      name: minecraft
      ready: true
      restartCount: 0
      started: true
      state:
        running:
          startedAt: "2024-09-02T06:58:58Z"
  updatePriority: "0"

Query GS list with "version": "java21" annatation and opsState not None:

{
    "$and": [
        {
            "metadata.annotations.version": "java21"
        },
        {
            "spec.opsState": {
                "$ne": "None"
            }
        }
    ]
}

Query GS list with opsState Maintaining or Draining:

{
    "$or": [
        {
            "spec.opsState": "Maintaining"
        },
        {
            "spec.opsState": "Draining"
        }
    ]
}

Adaptor Layer

Golang Package

Functions

func NewFilter() *Filter
func NewUpdater() *Updater
func GetGsList(filter *FilterDocument)
func UpdateGsList(filter *FilterDocument, updater *UpdaterDocument)

Class

Filter:

type Filter struct {
}

func (f *Filter) Build() *FilterDocument
func (f *Filter) BuildFromString(filterString string) *FilterDocument

Updater:

type Updater struct {
}

func (u *Updater) Build() *UpdaterDocument
func (u *Updater) BuildFromString(updaterString string) *UpdaterDocument

RESTful API

  • Query GS list with opsState Maintaining or Draining:

GET http://localhost/gs?filter={"$or":[{"spec.opsState":"Maintaining"},{"spec.opsState":"Draining"}]}

After URL escape:

GET http://localhost/gs?filter=%7B%22%24or%22%3A%5B%7B%22spec.opsState%22%3A%22Maintaining%22%7D%2C%7B%22spec.opsState%22%3A%22Draining%22%7D%5D%7D

200 response:

[
    {
        "name": "minecraft-pvp-0",
        "namespace": "minecraft",
        ...
    },
    {
        "name": "minecraft-pvp-1",
        "namespace": "minecraft",
        ...
    }
]

4XX/5XX error response:

{
    "code": 1,
    "message": "internal error"
}
  • Update GS with opsState Maintaining or Draining to None:

POST http://localhost/gs

body:

{
    "query": {
        "$or": [
            {
                "spec.opsState": "Maintaining"
            },
            {
                "spec.opsState": "Draining"
            }
        ]
    },
    "update": {
        "spec.opsState": "None"
    }
}

200 response(successfully updated GS list):

[
    {
        "name": "minecraft-pvp-0",
        "namespace": "minecraft",
        ...
    },
    {
        "name": "minecraft-pvp-1",
        "namespace": "minecraft",
        ...
    }
]

4XX/5XX response(there is more than one GS that failed to update):

{
    "updated": [
        {
            "name": "minecraft-pvp-0",
            "namespace": "minecraft",
            ...
        }
    ],
    "failed": [
        {
            "error": {
                "code": 1,
                "message": "internal error"
            },
            "gs": {
                "name": "minecraft-pvp-1",
                "namespace": "minecraft",
                ...
            }
        }
    ]
}
  • Since writing filter and URL escaping are complicated, for developers who do not understand filter syntax, RESTful API client SDK is provided and called in the following chain method.
func GetActiveOpsGsList() {
    // Create HttpClient and configure connection pool
    sdkClient := sdk_client.Connect("http://localhost")

    // Do HTTP request
    gsList, err := sdkClient.GetGsList("namespace_name", NewFilter().Or().Kv("spec.opsState", "Maintaining").Kv("spec.opsState", "Draining").Build())
    // Or use the encapsulated simpler way
    gsList, err = sdkClient.GetGsList("namespace_name", NewFilter().Or().OpsState("Maintaining").OpsState("Draining").Build())

    gsList, err = sdkClient.GetGsList("namespace_name", NewFilter().And().Kv("metadata.annotations.version", "java21").Ko("spec.opsState", Not().StrEq("None")).Build())
    // Or use the encapsulated simpler way
    gsList, err = sdkClient.GetGsList("namespace_name", NewFilter().And().Annotation("version", "java21").OpsStateNot("None").Build())

    // patch GS
    gsList, err = sdkClient.UpdateGsList("namespace_name", NewFilter().Or().OpsState("Maintaining").OpsState("Draining").Build(), NewUpdater().OpsState("None").Build())
}

Command Line Tool

# Query the GS whose GSS name is minecraft-pvp and opsState is None
gsops -namespace minecraft -filter -owner_gss minecraft-pvp -ops_state None
# Another form: gsops --namespace=minecraft --filter --owner_gss=minecraft-pvp --ops_state=None
# Update GS with opsState Maintaining or Draining to None
gsops -namespace minecraft -filter -or -ops_state Maintaining -ops_state Draining -updater -ops_state None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants