K8s游戏服务器:通过服务/入口动态转发Pod的TCP和UDP NGINX 特拉菲克痛苦流量

问题描述

因此,在最近的几天里,我试图找到一种方法来动态附加入口名称(例如game-1.myapp.com),以解决Kubernetes上Steam专用服务器的TCP和UDP。我已附上下图,说明了我的计划方式,但是遇到了一些问题。

我可以使用Kubernetes API为每个单独的游戏服务器动态创建命名空间,Pod(由状态集控制),PVC,服务和入口。每个游戏服务器都位于其自己的名称空间中,彼此完全分开。我保证服务器可以在后台运行,Pod也在运行且处于活动状态,日志很好。

当我需要将有状态集服务分配给能够使用命名空间DNS连续答复TCP / UDP流量的Ingress时,我就被锁定在外,该DNS路由到集群的Ingress Controller(在Minikube中;对于生产应该使用ALB / NLB,AFAIK)。

以某种方式,我需要一种方法game-xxxxx.myapp.com引入特定的game-xxxxx名称间的pod。它们是否将附加端口并不重要。

为此,我可以仅通过API调用myapp.com的DNS解析器,并在需要时添加删除A Records。这似乎可以,但是我发现我可以根据现有服务使用ExternalDNS(https://github.com/bitnami/charts/tree/master/bitnami/external-dns)为我自动执行此操作。

我尝试过的,还没有运气:

Nginx

设置Nginx,但是我必须为每个服务定义暴露的端口。根据他们的文档(https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services),每次修改ConfigMap并重新创建Nginx Pod都是 OVERKILL ,因为可能会有很多更改,但这似乎不可行。另外,我非常怀疑Nginx是否会在繁重的负载下轻而易举,我发现它更适合Web服务器而不是游戏服务器。

此外,我可能需要一种方法来确保可以有重复的端口。例如,即使它们在不同的命名空间中,我也无法在Nginx中为许多其他服务器分配相同的28015端口。如果我使用agoneshttps://github.com/googleforgames/agones/blob/release-1.9.0/examples/gameserver.yaml)分配随机端口,则有时可能会用光它们来分配。

特拉菲克

我曾尝试使用Traefik,但没有运气。 IngressRoute允许从路由器到EntryPoint的TCP / UDP路由,然后再将其路由到分配的服务。我不太确定这是如何工作的,我尝试为服务设置注释并定义入口点,但仍然无法正常工作:https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-ingressroutetcp

痛苦

人们应该为游戏服务器工作,并且它为服务端口支持TcpuDP协议,但是同样,运气不好。

流量

我已在图表下方发布了有关工作原理的信息。我还具有下面的YAML文件,该文件将创建状态集,PVC和服务。您可以清楚地看到我尝试了ExternalName设置,因此也许可以将Minikube IP设置为该名称并能够连接,但是再一次,没有运气:

Steam Dedicated Server workflow

apiVersion: v1
kind: Service
Metadata:
  name: rust-service
  labels:
    game: rust
spec:
  # type: ExternalName
  # externalName: rust-1.rust.coal.app
  # clusterIP: ""
  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: "10Gi"
        accessModes: ["ReadWriteOnce"]

编辑:凹凸

解决方法

旁注!

如果使用/提到Ingress资源,则表示HTTP / HTTPS流量。


您发布的图表似乎是使用Service类型的LoadBalancer的好机会。

类型为LoadBalancer的服务用于处理外部TCP / UDP流量(第4层)。

免责声明!

此解决方案根据时间协议supports only one TCPUDP

要在同一端口上同时使用这两个协议,您将需要回退到类型为Service的{​​{1}}(它将节点上的端口从NodePort分配到30000)。

通过以下链接,您可以了解有关使用32767类型的服务创建与云无关的LoadBalancer的更多信息:

在此设置中,无需使用NodePortIngress之类的Traefik控制器,因为它们只是NginxClient之间的一个附加步骤。

您在Pod定义中已经有了这样的LoadBalancer的示例(我对此做了一些修改):

YAML

如果您打算将apiVersion: v1 kind: Service metadata: name: rust-service labels: game: rust spec: type: LoadBalancer # <-- THE CHANGE selector: game: rust ports: - name: rust-server-tcp protocol: TCP port: 28015 targetPort: 28015 AWS一起使用,请参阅其文档:

可能的设置示例(步骤):

  • 对于每个“ X游戏”:
    • 创建一个EKS“游戏X命名空间”
    • 创建一个namespace“游戏X部署”
    • 创建类型为deployment“游戏X-”的service,它指向“游戏X部署”
    • 创建一条LoadBalancer记录,将“ game-X.com”指向上一步中创建的DNS的IP。

每个LoadBalancer都有自己的IP和与其关联的LoadBalancer名称,例如:

  • DNS,IP地址为awesome-game.com,端口号连接到123.123.123.123
  • 28015/TCP,IP地址为magnificent-game.com,端口号连接到234.234.234.234

我认为创建专用的Steam服务器的这份中等指南可能会有用:


其他资源:

,

因此,正如先前的回复所说,入口是针对Web流量的。我没有使用Ingresses实现有效的设置,但我设法将服务与NodePort一起使用,并确保使用将自定义子域名绑定到正确IP的外部DNS创建DNS记录:{{ 3}}

现在,在必须创建部署,等待Pod被分配并确保Pod粘在该节点上或确保节点耗尽的情况下,以某种方式保留同一个节点的想法之后,问题仍然存在IP(非临时性IP),只要不删除部署,该IP就会一直保留在容器中。这样,当我需要现有的Deployment来部署Pod时,应该确保标记节点。