在 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' 时,我都会执行以下操作:
- 使用公开 HTTP 端口
的动态名称 app-${uuid}
创建一个新 Pod
- 使用 NodePort 创建一个新服务,将 Pod 的 HTTP 端口“暴露”给集群
- 通过添加新的 http 规则来创建或更新(如果存在)Ingress,我在其中指定域 X 应指向 NodePort X
上面提到的Ingress使用了一个LoadBalancer作为它的控制器,它是GKE中的自动化进程。
我已经遇到的一些问题,您或许可以帮助我解决:
- 虽然 Pod 和 NodePort 是每个应用程序的独立资源,但 Ingress 是共享的。因此,我不能只 create/delete 一个资源,但我也被迫跟踪添加到 Ingress 的内容,然后才能从 yaml append/delete 中获取,这绝对不是这种方式这样做(即编辑 yaml)。相反,我可能想要像 Ingress 这样的东西来监视特定的命名空间并根据 Pod 标签自动创建规则。假设我有 3 个带有标签
app-1
、app-2
和 app-3
的 pods,我希望 Ingress 自动监控我的命名空间中的所有 Pods 并根据以下内容创建规则这些 pods 的标签(即 app-1.acme.io -> 反向代理到 Pod app-1
)。
- 使用新的 HTTP 规则更新 Ingress 需要大约一分钟的时间来允许流量进入 Pod,直到那时我一直收到 404,即使 Ingress 和 LoadBalancer 看起来都像 'ready'。我不知道我应该 watch/wait 得到一个明确的消息,即 Ingress Controller 已准备好接受新生成的应用程序的流量。
- 如果您无法严格定义 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 的客户端库。
我正在尝试找出我应该将 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' 时,我都会执行以下操作:
- 使用公开 HTTP 端口 的动态名称
- 使用 NodePort 创建一个新服务,将 Pod 的 HTTP 端口“暴露”给集群
- 通过添加新的 http 规则来创建或更新(如果存在)Ingress,我在其中指定域 X 应指向 NodePort X
app-${uuid}
创建一个新 Pod
上面提到的Ingress使用了一个LoadBalancer作为它的控制器,它是GKE中的自动化进程。
我已经遇到的一些问题,您或许可以帮助我解决:
- 虽然 Pod 和 NodePort 是每个应用程序的独立资源,但 Ingress 是共享的。因此,我不能只 create/delete 一个资源,但我也被迫跟踪添加到 Ingress 的内容,然后才能从 yaml append/delete 中获取,这绝对不是这种方式这样做(即编辑 yaml)。相反,我可能想要像 Ingress 这样的东西来监视特定的命名空间并根据 Pod 标签自动创建规则。假设我有 3 个带有标签
app-1
、app-2
和app-3
的 pods,我希望 Ingress 自动监控我的命名空间中的所有 Pods 并根据以下内容创建规则这些 pods 的标签(即 app-1.acme.io -> 反向代理到 Podapp-1
)。 - 使用新的 HTTP 规则更新 Ingress 需要大约一分钟的时间来允许流量进入 Pod,直到那时我一直收到 404,即使 Ingress 和 LoadBalancer 看起来都像 'ready'。我不知道我应该 watch/wait 得到一个明确的消息,即 Ingress Controller 已准备好接受新生成的应用程序的流量。
- 如果您无法严格定义 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 的客户端库。