我正在尝试设置一个可以自动启动和关闭视频游戏服务器的系统,作为 docker 镜像。在这种情况下,factoriotools/factorio-docker。每个游戏都是该容器的不同、独特的单 pod 部署,因此(在简化的情况下)需要自己的 IP 地址来监听特定的 UDP 端口。负载平衡器是多余的和不相关的,而且 Cloud NAT 似乎不容易允许入口流量。
我知道有几种方法可以实现这一点,但都需要做出相当大的妥协:
- 我可以使用 NodePort 服务,但无法控制客户端需要连接到哪个端口。这是一个问题,因为服务器会将自己注册到服务器列表中。
- 我可以使用主机网络。如果我的信息正确的话,这需要特权容器,这绝对不好。
- 我或许可以使用 UDP 负载平衡器,但即使它存在并且可以工作,成本也很昂贵。
可能有办法解决这两种方法的局限性(对于第二种方法,让主机保持短暂的寿命并保持严格的防火墙,这应该基本上没问题?),但我不禁想到有一个更好的选择,我在官方 kubernetes 文档中找不到描述。traefik 是否有一些我不知道的技巧?有没有办法获得 MetalLB 的变体,可以根据需要动态分配公共 IP 地址?
如何让每个服务器容器使用特定的 UDP 端口监听不同的公共 IP 地址,同时又不导致安全性问题?
编辑:
- 端口是可以配置的,只要我知道在 pod 启动之前服务器需要在哪个端口上运行即可。
- 除非我误解了服务器文档,否则客户端需要能够连接到服务器正在监听的同一端口。k8s 在应用程序监听端口和客户端连接端口之间划定的差异对我来说毫无帮助。
- 寻址这个问题,我不需要负载平衡器,因为它对我来说实际上什么都做不了。更改 IP 地址无关紧要,系统设计用于处理这个问题。如果服务器停机 15 秒,每个人都必须重新连接,然后他们会找到新的 IP 地址。服务器无法处理同一游戏上的多个 pod,因此永远不会有多个副本。
- 我刚刚尝试了一项
NodePort
具有随机公共端口的服务(我还没有看到我可以选择外部端口),我可以直接连接,但不能列出服务器连接。服务器列出过程首先通过让服务器将出站 UDP 流量发送到给定端点来自动检测如何连接到服务器。因此,我不仅需要控制入站流量连接到哪个端口,还需要控制出站流量的路由方式,包括可能使用的任何 NAT。
答案1
发布这个社区维基答案是为了为这个问题设置更多的基本方法,而不是提供明确的解决方案。
请随意编辑和扩展。
您可以使用 公开您的应用程序Services
。有几个选项,每个选项都有所不同:
ClusterIP
:在集群内部 IP 上公开服务。选择此值会使服务只能从集群内部访问。这是默认值ServiceType
。- 节点端口:通过静态端口( )在每个节点的 IP 上公开服务
NodePort
。服务路由ClusterIP
到的服务NodePort
会自动创建。您可以NodePort
通过请求 ,从集群外部联系服务<NodeIP>:<NodePort>
。- 负载均衡器:使用云提供商的负载均衡器向外部公开服务。
NodePort
并且ClusterIP
会自动创建外部负载均衡器路由到的服务。- 外部名称:通过返回带有其值的记录,将服务映射到字段的内容
externalName
(例如foo.bar.example.com
)CNAME
。不设置任何类型的代理。
关于公开应用程序的具体文档Google Kubernetes Engine
可以在这里找到:
特别关注问题中包含的一些要点:
我可以使用 NodePort 服务,但无法控制客户端需要连接到哪个端口。这是一个问题,因为服务器会将自己注册到服务器列表中。
您可以NodePort
在Service
YAML 中指定端口(如nodePort: 32137
或nodePort: 30911
)。
您可以将应用程序配置为侦听相同的端口nodePort
:
- 应用程序正在监听端口
30000
- 服务正在使用
nodePort
:port
(30000
客户端/用户应连接到此端口) 和 targetPort:30000
。在这种情况下,端口不会发生变化。
附注!
默认情况下,防火墙
nodePort
会阻止该端口范围GCP
。您需要创建一个规则(或一组规则)来允许它。
我可以使用主机网络。如果我的信息正确的话,这需要特权容器,这绝对不好。
我建议不要使用特权容器,除非有充分的理由。引用官方文档:
特权策略是故意开放的,完全不受限制。此类策略通常针对由特权、受信任用户管理的系统级和基础设施级工作负载。
端口是可以配置的,只要我知道在 pod 启动之前服务器需要在哪个端口上运行即可。
由于您将拥有多个单个Pods
(每个都有一个单独的Deployment
),因此您可以对每个单个进行参数化。我的意思是,您可以创建一个模板并仅修改清单的一部分(例如端口、环境变量等)。
您可以将环境变量传递给您,Pod
以便将其用作命令中的参数。您还可以修改Pod
以