<p>So in the last few days, I tried to find a way to dynamically attach ingress names (like <code>game-1.myapp.com</code>) to solve TCP &amp; UDP for Steam Dedicated Servers on Kubernetes. I have attached the following diagram on how I planned it, but there are some issues I encountered.</p>
<p>I can dynamically create Namespaces, Pods (controlled by Stateful Sets), PVCs, Services, and Ingresses for each individual game server using the Kubernetes API. Each game server lies in its own namespace, completely separated by the others. I assured that the server runs under the hood, the Pod is also Running and active, the logs are good.</p>
<p>I got locked out when I needed to assign the Stateful Set service to an Ingress that is able to continuously reply to TCP/UDP traffic by using a namespaced DNS, that routes to the cluster's Ingress Controller (in Minikube; for Production an ALB/NLB should be used, AFAIK).</p>
<p>Somehow, I need a way to ingress the <code>game-xxxxx.myapp.com</code> to the specific <code>game-xxxxx</code> namespace's pod. It doesn't really matter if they will have appended ports or not.</p>
<p>For this, I can simply just API-call the DNS solver for <code>myapp.com</code> and add or remove <code>A Records</code> when it's needed. This seems okay, but I have found out that I can use ExternalDNS (<a href="https://github.com/bitnami/charts/tree/master/bitnami/external-dns" rel="nofollow noreferrer">https://github.com/bitnami/charts/tree/master/bitnami/external-dns</a>) to do this automatically for me, based on the existent services.</p>
<p>What I have tried, no luck yet:</p>
<h3>NGINX</h3>
<p>Setting up NGINX, but I had to define the exposed ports for each Service. Based on their documentation (<a href="https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services" rel="nofollow noreferrer">https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services</a>), it is <strong>OVERKILL</strong> to modify that ConfigMap and Recreate the NGINX pods each time, since there might be many changes and this does not seem viable. Plus, I highly doubt that NGINX will be a breeze under heavy load, I find it more suitable for web servers rather than game servers.</p>
<p>Also, I might need a way to make sure that I can have duplicated ports. For example, I cannot assign in NGINX the same <code>28015</code> port to many other servers, even when they are in different namespaces. If I use Agones (<a href="https://github.com/googleforgames/agones/blob/release-1.9.0/examples/gameserver.yaml" rel="nofollow noreferrer">https://github.com/googleforgames/agones/blob/release-1.9.0/examples/gameserver.yaml</a>) to assign random ports, at some point I might run out of them to assign.</p>
<h3>Traefik</h3>
<p>I have tried to use Traefik, but had no luck. The IngressRoute allows the TCP/UDP routing from a Router to and EntryPoint than then routes it to the service assigned. I am not really sure how this works, I tried setting annotations to services &amp; defining entry points, but it still refuses to work: <a href="https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-ingressroutetcp" rel="nofollow noreferrer">https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-ingressroutetcp</a></p>
<h3>Agones</h3>
<p>Agones should be working for game servers and it supports <code>TCPUDP</code> protocol for service ports, but again, no luck with this.</p>
<h3>Flow</h3>
<p>I have posted below the diagram on how things should work. I also have this following YAML file that will create the Stateful Set, a PVC, and the Service. You can clearly see I tried ExternalName setup so maybe I can set the Minikube IP to that name and be able to connect, yet again, no luck:</p>
<p><a href="https://i.stack.imgur.com/VENAy.png" rel="nofollow noreferrer">Steam Dedicated Server workflow</a></p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Service
metadata:
  name: rust-service
  labels:
    game: rust
spec:
  # type: ExternalName
  # externalName: rust-1.rust.coal.app
  # clusterIP: &quot;&quot;
  selector:
    game: rust
  ports:
  - name: rust-server-tcp
    protocol: TCP
    port: 28015
    targetPort: 28015
  - name: rust-server-udp
    protocol: UDP
    port: 28015
    targetPort: 28015
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: rust-server
spec:
  selector:
    matchLabels:
      game: rust
  replicas: 1
  serviceName: rust-service
  template:
    metadata:
      name: rust-server
      labels:
        game: rust
    spec:
      containers:
      - name: rust
        image: didstopia/rust-server:latest
        ports:
          - name: rust-server-tcp
            protocol: TCP
            containerPort: 28015
          - name: rust-server-udp
            protocol: UDP
            containerPort: 28015
  volumeClaimTemplates:
    - metadata:
        name: local-disk
      spec:
        resources:
          requests:
            storage: &quot;10Gi&quot;
        accessModes: [&quot;ReadWriteOnce&quot;]
</code></pre>
<p>Edit: bump</p>

<blockquote>
<p><strong>A side note!</strong></p>
<p>If <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" rel="nofollow noreferrer">Ingress</a> resource is used/mentioned it's referring to <code>HTTP</code>/<code>HTTPS</code> traffic.</p>
</blockquote>
<hr />
<p>The diagram that you've posted is looking like a good opportunity to use <code>Service</code> of type <code>LoadBalancer</code>.</p>
<p>Service of type <code>LoadBalancer</code> is used to handle external <code>TCP</code>/<code>UDP</code> traffic (Layer 4).</p>
<blockquote>
<p>Disclaimer!</p>
<p>This solution <a href="https://github.com/kubernetes/kubernetes/issues/2995" rel="nofollow noreferrer">supports only one</a> at the time protocol, <strong>either</strong> <code>TCP</code> or <code>UDP</code>.</p>
<p>To have both protocol on the same port you will need to fallback to <code>Service</code> of type <code>NodePort</code> (which allocates port on a node from <code>30000</code> to <code>32767</code>).</p>
<p>You can read more about creating cloud agnostic LoadBalancer that is using <code>NodePort</code> type of service by following this link:</p>
<ul>
<li><em><a href="https://medium.com/asl19-developers/build-your-own-cloud-agnostic-tcp-udp-loadbalancer-for-your-kubernetes-apps-3959335f4ec3" rel="nofollow noreferrer">Medium.com: Build your own cloud agnostic tcp udp loadbalancer for Kubernetes apps</a></em></li>
</ul>
</blockquote>
<p>In this setup <code>Ingress</code> controllers like <code>Traefik</code> or <code>Nginx</code> are not needed as they will only be an additional step between your <code>Client</code> and a <code>Pod</code>.</p>
<p>The example of such <code>LoadBalancer</code> you already have in your <code>YAML</code> definition (I slightly modified it):</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: rust-service
  labels:
    game: rust
spec:
  type: LoadBalancer # &lt;-- THE CHANGE
  selector:
    game: rust
  ports:
  - name: rust-server-tcp
    protocol: TCP
    port: 28015
    targetPort: 28015
</code></pre>
<p>If you are intending to use <code>AWS</code> with it's <code>EKS</code> please refer to it's documentation:</p>
<ul>
<li><em><a href="https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html" rel="nofollow noreferrer">Docs.aws.amazon.com: EKS: Userguide: Getting Started</a></em></li>
</ul>
<p>Example of a possible setup (steps):</p>
<ul>
<li>For each &quot;game-X&quot;:
<ul>
<li>Create a <code>namespace</code> &quot;game-X-namespace&quot;</li>
<li>Create a <code>deployment</code> &quot;game-X-deployment&quot;</li>
<li><strong>Create a <code>service</code> of type <code>LoadBalancer</code> &quot;game-X-&quot; that would point to a &quot;game-X-deployment&quot;</strong></li>
<li><strong>Create a <code>DNS</code> record pointing &quot;game-X.com&quot; to IP of <code>LoadBalancer</code> created in previous step.</strong></li>
</ul>
</li>
</ul>
<p>Each <code>LoadBalancer</code> would have it's own IP and the <code>DNS</code> name associated with it like:</p>
<ul>
<li><code>awesome-game.com</code> with IP of <code>123.123.123.123</code> and port to connect to <code>28015/TCP</code></li>
<li><code>magnificent-game.com</code> with IP of <code>234.234.234.234</code> and port to connect to <code>28015/TCP</code></li>
</ul>
<hr />
<p>I reckon this medium guide to create  dedicated Steam server could prove useful:</p>
<ul>
<li><em><a href="https://medium.com/alterway/deploying-a-steam-dedicated-server-on-kubernetes-645099d063e0" rel="nofollow noreferrer">Medium.com: Deploying a steam dedicated server on Kubernetes</a></em></li>
</ul>
<hr />
<p>Additional resources:</p>
<ul>
<li><em><a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="nofollow noreferrer">Kubernetes.io: Docs: Concepts: Services networking: Service</a></em></li>
</ul>
