googleforgames / agones

Dedicated Game Server Hosting and Scaling for Multiplayer Games on Kubernetes
https://agones.dev
Apache License 2.0
6.09k stars 810 forks source link

Expose dynamic ports to game server as environmental variable #1524

Closed stevefan1999-personal closed 4 years ago

stevefan1999-personal commented 4 years ago

Is your feature request related to a problem? Please describe. Some traditional game server, like CSGO, doesn't support proxied port because in order to connect it through the master server you need both your IP and ports to be the same, or the game lobby ticket will not be created properly. e.g.

<Your Agones CSGO server> -> tells the master server I'm listening on 27015
<Your Agones controller> -> Allocated port 7777 -> forwarded it to proxy <Your Agones CSGO server> on 27015
<Client> -> only sees <Your Agones CSGO server IP>:27015 -> tried connecting through <Your Agones CSGO server IP>:7777 -> fails

Describe the solution you'd like Expose the ports as an environmental variables for the game server in the format of AGONES_MANAGED_PORT_${strings.ToUpper(name)} (e.g. AGONES_MANAGED_PORT_SRCDS etc.), then the game server will have a variable redirection to listen on these port, and report the right address/port to the master server. This is the most appropriate solution and is the least intrusive.

Additional context Add any other context or screenshots about the feature request here.

markmandel commented 4 years ago

Any reason why the port information exposed via the SDK.GameServer() or SDK.WatchGameServer() aren't sufficient?

stevefan1999-personal commented 4 years ago

@markmandel I mean sure I can write a SDK client and expose the ports as an environmental variables but isn't that overkill...

markmandel commented 4 years ago

While I appreciate your enthusiasm, I don't think this is something we will consider on this project, so I'm going to say no to this ticket.

Once we go down this path, then almost every configuration variable should become an environment variable., and that's a lot of work and ongoing testing for little payoff.

The SDK provides the greatest flexibility for the largest variety of use cases, and therefore if you need an environment variable, it's possible to write your own specific game server wrapper / tooling to implement this for your specific use case.

stevefan1999-personal commented 7 months ago

After 4 years I'm going to do a necromancy: I was attempting to do the following:

apiVersion: agones.dev/v1
kind: Fleet
metadata:
  # generateName: "gds-example" # generate a unique name, with the given prefix
  name: "svencoop-example2" # set a fixed name
  namespace: game
spec:
  replicas: 1
  template:
    spec:
      container: svencoop
      ports:
      - name: default
        portPolicy: Passthrough
        container: svencoop
        protocol: TCPUDP
      # Health checking for the running game server
      health:
        # Disable health checking. defaults to false, but can be set to true
        disabled: false
        # Number of seconds after the container has started before health check is initiated. Defaults to 5 seconds
        initialDelaySeconds: 120
        periodSeconds: 10
        failureThreshold: 30
      sdkServer:
        logLevel: Info
        grpcPort: 9357
        httpPort: 9358

      template:
        metadata:
          labels:
            game: svencoop
        # Pod Specification
        spec:
          containers:
            - name: svencoop
              image: lacledeslan/gamesvr-svencoop
              imagePullPolicy: Always
              command:
                - ./svends_run
              args:
                - '-num_edicts 8192'
                - +map hl_c03
                - '-pingboost 3'
                - '-reuse'
                - '-sys_ticrate 1000'
                - '-netthread'
                - '-port $(PORT)'
              env:
                - name: PORT
                  valueFrom:
                    fieldRef:
                      fieldPath: spec.ports['default'].hostPort

I was attempting to use the Downward API to do what I wanted to. Didn't work out as expected:

Pod "svencoop-example2-q7xbr-7b9db" is invalid: spec.containers[1].env[0].valueFrom.fieldRef.fieldPath: Invalid value: "spec.ports['default'].hostPort": error converting fieldPath: field label not supported: spec.ports['default'].hostPort

Being able to use the downward API is very close to what I wanted to do already. However, it seems like we can expose those port information to metadata.annotations['<KEY>'] to get a workaround. Not sure how much hack is needed, given there can be multiple ports needed.