googleforgames / agones

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

Support using the same port for both TCP/UDP forwarding #1523

Closed stevefan1999-personal closed 3 years ago

stevefan1999-personal commented 4 years ago

Is your feature request related to a problem? Please describe.

SRCDS uses both TCP/UDP on the same port where the TCP is for RCON access, but the dynamic port policy will also assign a random port for both TCP RCON port and main game communication UDP port. This is really infuriating that I have to resort to using static allocation policy.

Describe the solution you'd like

Introduce a new protocol "Any" for GameServer, that will allocate one port that listen on both TCP and UDP. If that semantically doesn't sound, because maybe in the future there will be more protocol supports, then make it an array:

      ports:
        - name: srcds
          containerPort: {{ $.Values.srcds.port }}
          protocol:
            - UDP
            - TCP
          portPolicy: Static
          hostPort: {{ $.Values.srcds.port }}
markmandel commented 4 years ago

Unfortunately, Kubenetes cannot support both UDP and TCP on the same hostPort.

I would suggest writing your own iptables rule to route appropriately.

markmandel commented 4 years ago

Oh, actually, looks like I might be wrong: https://github.com/kubernetes/kubernetes/pull/8490

Sounds like it's worth investigation.

stevefan1999-personal commented 4 years ago

@markmandel I can set it using static policy and it works

markmandel commented 4 years ago

One workaround you could use, is if you have no way to expose what the ports that are exposed to the outside system, is write some code that integrates into the Agones SDK to create a local iptables rules on the container that routes the traffic from one/both of the exposed port back to the appropriate ports on your required process.

markmandel commented 4 years ago

This came up again. Rather than "Any" - maybe a "Both" or "UDP+TCP" or something like that?

In retrospect, it would have been good to have this as a sequence, but to maintain backward compatibility, probably best not to change this at this point.

I figure we can bank on no new protocol other than TCP or UDP to become standard in the near future :smile:

Bmandk commented 4 years ago

One workaround you could use, is if you have no way to expose what the ports that are exposed to the outside system, is write some code that integrates into the Agones SDK to create a local iptables rules on the container that routes the traffic from one/both of the exposed port back to the appropriate ports on your required process.

Unfortunately, that does not work for my setup, as my server registers itself on an external masterserver (which I have no control over). It just sends the port number, and expects both TCP and UDP to be exposed to the same number.

I get that this is probably pretty niche, and mostly happens in instances where you don't have control over the server architecture yourself. But it's currently what blocking me from continuing with Agones.

Bmandk commented 4 years ago

After digging through the code for port allocation a bit, here is my proposal for a feature that implements TCP and UDP on the same hostPort.

The protocol would be expanded with a TCPUDP type, which will ensure that the hostPort will have both UDP and TCP for the node, as well as pointing to the same specified container.

The actual implementation will happen during the allocation loop as follows:

  1. To not break the loop, a separate list of GameServerPorts will be initialized before the loop.
  2. When the allocation loop encounters a TCPUDP protocol, change the protocol for the port to TCP, and add an identical GameServerPort to the previously mentioned list.
  3. Immediately after the initial allocation-loop, loop through the new list. Here we first change the protocol to UDP, and then add the identical port to the GameServer.

This should in theory allocate both ports to the GameServer, and they will be part of any other port. One caveat is that this is a naive approach, as the allocator will only check for the port number, but not look at the protocol. This could cause issues in setups where the nodepools are shared with other kinds of servers or services. However, to really get around such a problem, the work is a more extensive, having to also track the protocol with the port allocations.

markmandel commented 4 years ago

Random thought: "TCP&UDP"? Not strong opinion, just throwing it out there to see if it sticks.

As per implementation design -- at first glance, seems reasonable :+1: Will likely review more when we can see it in the PR!

You will likely also need to update the CRD validation spec: https://github.com/googleforgames/agones/blob/master/install/helm/agones/templates/crds/_gameserverspecvalidation.yaml#L78-L83

Which you likely would have encountered quickly when you went to write e2e tests :smile: