在 GKE 中动态部署有状态应用程序

Dynamic deployment of stateful applications in GKE

我正在尝试找出我应该将 GKE 堆栈中的哪些工具应用于我的用例,该用例是使用动态 HTTP 端点动态部署有状态应用程序。

在我的例子中,有状态意味着我不需要任何副本和负载平衡(因为该应用程序根本无法水平扩展)。我知道在 k8s/gke 命名法中我仍然会使用 'load-balancer' 即使它会充当反向代理并且实际上不会平衡任何负载。

用例如下。我有一些网络应用程序,我可以在其中请求 'new instance',在 return 中,我得到一个动态生成的 url(例如 http://random-uuid-1.acme.io). This domain should point to a newly spawned, single instance of a container (Pod) hosting some web application. Again, if I request another 'new instance', I'll get a http://random-uuid-2.acme.io,它将指向另一个(单独的),新同一应用程序的衍生实例。

到目前为止,我想出了以下设置。每次我请求 'new instance' 时,我都会执行以下操作:

上面提到的Ingress使用了一个LoadBalancer作为它的控制器,它是GKE中的自动化进程。

我已经遇到的一些问题,您或许可以帮助我解决:

  1. 虽然 Pod 和 NodePort 是每个应用程序的独立资源,但 Ingress 是共享的。因此,我不能只 create/delete 一个资源,但我也被迫跟踪添加到 Ingress 的内容,然后才能从 yaml append/delete 中获取,这绝对不是这种方式这样做(即编辑 yaml)。相反,我可能想要像 Ingress 这样的东西来监视特定的命名空间并根据 Pod 标签自动创建规则。假设我有 3 个带有标签 app-1app-2app-3 的 pods,我希望 Ingress 自动监控我的命名空间中的所有 Pods 并根据以下内容创建规则这些 pods 的标签(即 app-1.acme.io -> 反向代理到 Pod app-1)。
  2. 使用新的 HTTP 规则更新 Ingress 需要大约一分钟的时间来允许流量进入 Pod,直到那时我一直收到 404,即使 Ingress 和 LoadBalancer 看起来都像 'ready'。我不知道我应该 watch/wait 得到一个明确的消息,即 Ingress Controller 已准备好接受新生成的应用程序的流量。
  3. 如果您无法严格定义 Pods/Services 清单,那么管理此类集群的最佳做法是什么,因为您正在动态创建它们(使用不同的名称、端点或规则)。您肯定不想为您生成的每个应用程序创建一堆 yaml-s 来维护。我会想象在 Consul 的情况下类似于 consul templates 但对于 k8s?

我参与了一个类似的项目,我们决定使用 Kubernetes Client Library 生成实例。这些实例由一个简单的 Web 应用程序管理,该应用程序采用一些自定义参数,将它们保存到数据库中,然后创建一个实例。由于数据库的存在,跟踪到目前为止已创建的内容没有问题。通过查询数据库,我们能够判断此类部署是否已创建或 update/delete 任何关联资源。

每个实例包括:

  • 一个部署(单个或多个副本,取决于实例);
  • 一个ClusterIp服务(没有理由用NodePort预留机器端口);
  • 共享入口控制器的入口对象;
  • 和一些共享的 configMap。

并且我们还使用了 external DNS and cert manager,一个用于管理 DNS 记录,另一个用于为入口颁发 SSL 证书。使用此设置,部署一个新实例大约需要 10 分钟。 pod 和入口控制器在几秒钟内准备就绪,但我们必须等待证书,它是否准备就绪取决于颁发者的 DNS 是否获得了我们的新记录。使用通配符域可能会避免此问题,但我们必须使用许多不同的域,因此在我们的案例中这不是一个选项。

除此之外,您可以考虑编写 Helm chart and make use of helm list command 来查找现有实例并管理它们。不过,这是一个相当 'manual' 的解决方案。如果您希望此功能成为您应用程序的一部分 - 最好使用 Kubernetes 的客户端库。