I am learning kubernetes and wondering if it is suitable for the following usecase:
I have a server (server as in daemon, not computer) for a multiplayer game. The game runs continuously and clients can join and leave at any time. But each server has a limit for maximum amount of clients. When it gets full, new server should be started. Servers should be shut down when empty, but leaving at least one running at any time. Each server chooses an arbitrary UDP port on which it listens. The individual servers report themselves to a master-server. The clients first connect to the master-server to get list of running servers including their addresses and ports, then connect directly to one of them.
To handle this with Kubernetes, each game server could be a single Pod. I could use autoscaling with custom metric to handle the starting and shutting down based on the amount of connected clients.
But I am not sure how to expose each Pod to the outside world under unique UDP port. If I create a Service for these Pods, then I get just a single port assigned to all of them and packets arriving to it get send to different Pod each time, which obviously doesn't work.
Is there a reasonable way to handle this with kubernetes?
Edit: While the game server has the ability to find free port automatically, it can be given configured to listen on specific port as well, so that part isn't an issue if kubernetes can handle the assignment of a free port on the internet-facing address.
Ideally the end result could look like this:
Public-facing IP +------- NodeA --------------+
| +------ Pod1 ------------+ |
UDP/10001 ............> | | GameServer @ UDP/10000 | |
| +------------------------+ |
UDP/10002 ...... | +------ Pod2 ------------+ |
......> | | GameServer @ UDP/10000 | |
UDP/10003 ... | +------------------------+ |
.. +----------------------------+
UDP/10004 . ..
. .. +------- NodeB --------------+
. .. | +------ Pod3 ------------+ |
. .> | | GameServer @ UDP/10000 | |
. | +------------------------+ |
.. | +------ Pod4 ------------+ |
.....> | | GameServer @ UDP/10000 | |
| +------------------------+ |
+----------------------------+
This is quite unusual case. K8s was not designed to work with applications that open random ports. The only thing that comes up to my mind to solve it is the use of hostNetwork: true
, but you need to aware of what it does and what are the drawbacks. K8s docs:
HostNetwork - Controls whether the pod may use the node network namespace. Doing so gives the pod access to the loopback device, services listening on localhost, and could be used to snoop on network activity of other pods on the same node.
Now let's think for a moment why would it (the use of hostNetwork: true) be a solution.
Pods with hostNetwork: true
running on nodes will have node's ip, and will automatically be exposed externally as long as the node is exposed.
There should be no issues with udp, you wouldn't need to configure any services, and know any ports beforehand. Pod starts with host ip, application opens any port it wants, advertises it to master-server and it is ready to go.
But since it requires exposing nodes to the internet, be aware that nodes will be prone to attacks, and that may be considered a security issue.