这是我之前问过的一个问题,但问题/方法不同。如果重要的话,我使用的是 GKE,但我希望有一个与云无关的答案。
我正在尝试运行容器factoriotools/factorio
,但由于使用特定于应用程序的公共服务器列表功能,该应用程序有一些特殊要求,就像在许多使用用户托管服务器的视频游戏中所见的那样。
到目前为止,我已经能够使用主机网络和直接连接来与 NodePort 服务配合使用。但是,对于非特权容器来说,应用程序的公共服务器列表功能仍然是一个问题。
以下是 Factorio 管理公共服务器列表的方法:
- 容器在一个套接字上监听,比如 UDP 端口 34197。
- NodePort 服务将该流量公开路由到 20635。
- 容器通过其监听端口 (34197) 向 ping-pong 服务器发送 ping,ping-pong 服务器使用收到 ping 的 IP 地址和端口进行回复。在 k8s 之外,这仍然是端口 34197。
- 然后容器使用这些信息向服务器列表注册。IP 地址、端口、服务器名称和一些其他信息。
- 在 GKE 中,乒乓球会被路由到任意未使用的端口(例如 40792)。
- 容器认为它正在监听我设置的端口(20534)以外的端口,然后使用错误的端口(40792,因为乒乓服务器是这么说的)向公共服务器列表进行注册。
- 任何从公共服务器列表进行的连接的尝试都会失败;客户端认为服务器正在监听乒乓服务器见证的端口(40792),但容器一直在与其监听端口(34197)进行交互。
(我听说这个过程是 ICE/STUN 工作方式的变体)
因此,这意味着如果容器在 34197 上监听,但 Kubernetes 将其外部路由到 20635,则入站和出站流量都需要通过公共端的 20635,应用程序的内置服务器列表功能才能正常工作。
如果我绕过公共服务器列表,直接连接到容器节点的公共 IP 地址(端口 20635),它就可以完美运行。但对于我正在做的事情来说,这是一个相当大的妥协。
主机网络通过允许容器直接打开主机上的任何端口来绕过整个问题。对于已经公开的主机,这意味着主机上的任何内容(尤其是 k8s)都无法通过额外的层重新路由容器流量并更改端口号。因此,当容器打开端口 34197 时,它会获得端口 34197。当它在端口 34197 上发送时,该流量将在端口 34197 上发送。乒乓服务器会看到它应该看到的端口。而且因为它是一个公共 UDP 端口,所以谁先发送流量并不重要;流量就是流量,端口就是端口。
但是,如果我正确理解了文档,在主机的网络堆栈上运行容器需要特权容器,这实际上是主机上的 root 访问权限,这在生产中非常糟糕。因此,对于非特权容器,除了依赖主机网络之外,还需要其他解决方案。我找不到那个“其他解决方案”。我找不到任何关于如何做到这一点的文档,甚至找不到任何人正在考虑它的证据。我该如何做到这一点?
答案1
我建议你使用 GCP游戏服务器功能。它是一个专用的游戏服务器,可让您免去管理全球游戏服务器基础设施的麻烦,因此您可以专注于更快地创建出色的游戏,而不会增加复杂性或影响性能。
它使用 Kubernetes 进行容器编排,从而管理游戏服务器集群,并阿戈内斯用于游戏服务器队列编排和生命周期管理。Agones 是一个开源专用游戏服务器托管和扩展项目,建立在 Kubernetes 之上,具有您所需的灵活性,可以根据多人游戏的需求进行定制。
在使用 Agones 创建游戏服务器时,您必须添加一些防火墙规则来打开连接集群所需的 UDP 端口。
要使用 Agones 创建游戏服务器,您可以执行以下操作:快速开始 它将指导您使用 Agones 自定义资源在 Kubernetes 中创建游戏服务器。
要获取 GameServer 状态,请使用以下命令。它将为您提供 GameServer 的各种生命周期事件。
watch kubectl describe gameserver
要使用 Agones 在 GCP 中设置 GameServer,你可以查看官方的 Google文档。