Kubernetes 和 Gunicorn 上的 Flask 应用程序扩展

Posted

技术标签:

【中文标题】Kubernetes 和 Gunicorn 上的 Flask 应用程序扩展【英文标题】:Flask application scaling on Kubernetes and Gunicorn 【发布时间】:2019-11-06 23:33:16 【问题描述】:

我们有一个通过 gunicorn 提供服务的 Flask 应用程序,使用 eventlet worker。我们将应用程序部署在 kubernetes pod 中,其想法是根据工作负载扩展 pod 的数量。

gunicorn 中工人数量的推荐设置为2 - 4 x $NUM_CPUS。见docs。我之前在专用物理硬件上部署了服务,这样的计算是有意义的。在 4 核机器上,有 16 个工人听起来不错,但我们最终将其增加到 32 个工人。

这个计算是否仍然适用于使用异步工作器的 kubernetes pod,尤其是:

    单个节点上可能有多个 pod。 同一服务将在多个 pod 中运行。

我应该如何设置 gunicorn 工人的数量?

    将其设置为 -w 1 并让 kubernetes 通过 pod 处理扩展? 在 kubernetes 节点上将其设置为 2-4 x $NUM_CPU。一个吊舱还是多个吊舱? 完全不同的东西?

更新

我们决定采用第一个选项,这是我们目前的方法。将 gunicorn 作品的数量设置为 1,并通过增加 pod 的数量进行水平缩放。否则将会有太多的移动部件,而且我们将无法充分利用 Kubernetes。

【问题讨论】:

您还可以使用调度器拓扑功能设置每个节点的工作 Pod 数量以避免资源过度使用:kubernetes.io/docs/concepts/workloads/pods/… 【参考方案1】:

为了更好地了解该问题的原作者在 2019 年选择的最终解决方案

设置gunicorn作品的数量为1(-w 1),水平缩放 通过增加 pod 的数量(使用 Kubernetes HPA)。

考虑到 Kubernetes 平台中工作负载相关功能的快速增长,它可能在不久的将来不适用,例如除了 HPA、Vertical Pod Autoscaling (VPA) 和 Multidimensional Pod autoscaling (MPA) 之外,Kubernetes 的一些发行版也提出了建议,因此我建议以社区 wiki 帖子的形式继续此线程。

【讨论】:

【参考方案2】:

我不是开发人员,这似乎不是一个简单的任务,但出于您的考虑,请关注bests practices for Better performance by optimizing Gunicorn config

此外,由于CPU utilization 和 (How is Python scaling with Gunicorn and Kubernetes?),kubernetes 中还有不同的机制可以像 HPA 一样扩展您的部署

你也可以使用Resource requests and limits of Pod and Container.

根据Gunicorn documentation

不要将工作人员的数量扩展到您期望拥有的客户数量。 Gunicorn 应该只需要 4-12 个工作进程来处理每秒数百或数千个请求。 Gunicorn 在处理请求时依靠操作系统来提供所有的负载平衡。 通常我们建议 (2 x $num_cores) + 1 作为开始时的工人数量。虽然不是太科学,但该公式是基于这样的假设:对于给定的核心,一个工作人员将在另一个工作人员处理请求时从套接字读取或写入。

#更新

根据您的方法,您可以选择不同的解决方案(部署、守护进程)所有上述语句都可以通过根据Assigning CPU Resources to Containers and Pods 处理在 kubernetes 中实现

    将部署与资源(限制、请求)结合使用,您可以根据硬件限制将应用的大小调整为单个节点上的多个 pod,但取决于您的“应用负载”,它可能不是足够好的解决方案。

CPU 请求和限制与容器相关联,但将 Pod 视为具有 CPU 请求和限制是很有用的。 Pod 的 CPU 请求是 Pod 中所有 Container 的 CPU 请求的总和。同样,Pod 的 CPU 限制是 Pod 中所有容器的 CPU 限制的总和。

注意:

CPU 资源以 CPU 单位衡量。在 Kubernetes 中,一个 CPU 相当于: f.e. 1 个 GCP 核心。

    正如文章中提到的第二种方法(将您的应用程序扩展到多个节点)也是不错的选择。在这种情况下,您可以使用 f.e. cosnider。使用“cluster austoscaler”在 GKE 上添加 Statefulset 或部署,当您尝试创建没有足够容量在集群内运行的新 Pod 时,您可以获得更具可扩展性的解决方案。在这种情况下,集群自动扩缩器会自动添加额外的资源。

另一方面,您可以考虑使用其他不同的解决方案,例如 Cerebral,它使您可以创建用户定义的策略,以增加或减少集群内节点池的大小。

GKE 的集群自动扩缩器会根据您要运行的工作负载的需求自动调整集群的大小。启用自动扩展后,如果您创建了没有足够容量运行的新 Pod,GKE 会自动将新节点添加到您的集群;相反,如果集群中的某个节点未充分利用,并且其 Pod 可以在其他节点上运行,则 GKE 可以删除该节点。

请记住,这个问题非常笼统,对于这个主题没有一个好的答案。您应该根据您的要求、负载、活动、容量、成本考虑所有利弊......

希望对您有所帮助。

【讨论】:

我熟悉 Gunicorn 缩放和 Kubernetes 水平自动缩放。问题是当这两种技术相交时会发生什么,这不是这些文档中的任何内容所涉及的。 根据帖子中的考虑,更新了关于 kuberenets 解决方案的答案。请分享您的发现

以上是关于Kubernetes 和 Gunicorn 上的 Flask 应用程序扩展的主要内容,如果未能解决你的问题,请参考以下文章

gunicorn 访问日志格式

了解 Docker/Docker-Compose 上的 Gunicorn 和 Flask

数字海洋 NGINX 和 gunicorn 上的 CORS 标头访问控制缺少 django

Heroku 上的 Gunicorn 'ImportError: No module named app.wsgiapp'

Docker + Gunicorn + Nginx + Django:将非 www 重定向到 AWS Route 53 上的 www

heroku上的gunicorn:绑定到本地主机