web-dev-qa-db-ja.com

Docker / Kubernetes + Gunicorn / Celery-複数のワーカーとレプリカ?

コンテナ化されたDjangoアプリをgunicornとセロリを使用してデプロイするための正しいアプローチは何だろうと思っていました。

具体的には、これらの各プロセスには、gunicornにworkersを、セロリにconcurrencyを使用して、垂直方向にスケーリングする組み込みの方法があります。そして、replicasを使用したスケーリングへのKubernetesアプローチがあります。

ワーカーをCPUの一部の機能に等しく設定するという概念もあります。 Gunicornお勧め

コアあたり2〜4人のワーカー

ただし、resoureceQuotasを使用しない限り、CPUが分割可能な共有リソースであるK8でこれが何を意味するか混乱します。

ベストプラクティスとは何かを理解したい。私が考えることができる3つのオプションがあります:

  • Gunicornのシングルワーカーとセロリの同時実行性1を使用し、レプリカを使用してそれらをスケーリングしますか? (水平スケーリング)
  • 内部スケーリング(垂直スケーリング)を使用して、gunicornとセロリを単一のレプリカ展開で実行します。これは、それぞれかなり高い値のワーカーと並行性を設定することを意味します。
  • 1と2の混合アプローチで、ワーカーと同時実行性に小さな値でgunicornとセロリを実行し(2など)、K8s Deploymentレプリカを使用して水平にスケーリングします。

SOについてはいくつかの質問がありますが、詳細/思慮深い答えを提供するものはありません。

注:Gunicornにはデフォルトのworker_class syncを使用します

27
rtindru

これらのテクノロジーは、当初のように似ていません。これらは、アプリケーションスタックのさまざまな部分に対応し、実際には補完的です。

GunicornはWebリクエストの同時実行性をスケーリングするためのものであり、セロリはワーカーキューと考える必要があります。 kubernetesにすぐに行きます。


ユニコーン

Web要求の同時実行性は、主にネットワークI/Oまたは「I/Oバウンド」によって制限されます。これらのタイプのタスクは、スレッドによって提供される協調スケジューリングを使用してスケーリングできます。要求の同時実行がアプリケーションを制限していることがわかった場合は、gunicornワーカースレッドを増やすことから始めてください。


セロリ

重い物を持ち上げる作業イメージを圧縮し、いくつかのMLアルゴを実行します。これは「CPUバウンド」タスクです。より多くのCPUほどスレッド化の恩恵を受けることはできません。これらのタスクは、セロリ労働者によってオフロードおよび並列化される必要があります。


クベルネテス

Kubernetesが便利なのは、すぐに使える水平スケーラビリティとフォールトトレランスを提供することです。

アーキテクチャ的には、2つの個別のk8デプロイメントを使用して、アプリケーションのさまざまなスケーラビリティの問題を表します。 Djangoアプリ用のデプロイとセロリ労働者用のデプロイ。これにより、リクエストのスループットと処理能力を独立してスケーリングできます。

コンテナーごとに単一のコアに固定されたセロリワーカーを実行します(-c 1)これにより、デバッグが大幅に簡素化され、Dockerの「コンテナごとに1プロセス」というマントラが順守されます。また、レプリカ数を増やすことでコアごとに処理能力を拡張できるため、予測可能性の追加の利点も得られます。

Djangoアプリのデプロイは、特定のアプリケーションに最適な設定を見つけるためにDYORする必要がある場所です。再び--workers 1したがって、コンテナごとに1つのプロセスがありますが、--threads最適なソリューションを見つけます。繰り返しますが、レプリカ数を変更するだけで、水平スケーリングをKubernetesに任せます。

HTH同様のプロジェクトに取り組んでいるとき、それは間違いなく頭を包み込まなければならなかったものです。

15
stacksonstacks

DjangoとCeleryを使用してKubernetes klusterを実行し、最初のアプローチを実装しました。このトレードオフと、このアプローチを選択する理由についての私の考えの一部です。

私の意見では、Kubernetesはレプリカの水平スケーリング(デプロイメントと呼ばれる)がすべてです。その点で、展開をできるだけ単一の用途に保ち、需要が増加するにつれて展開(および不足した場合はポッド)を増やすことが最も理にかなっています。したがって、LoadBalancerはGunicorn展開へのトラフィックを管理し、RedisキューはCeleryワーカーへのタスクを管理します。これにより、基礎となるドッカーコンテナーがシンプルで小さくなり、適切と思われるように個別に(および自動的に)スケーリングできます。

展開ごとに必要なworkers/concurrencyの数についての考えは、Kubernetesを実行している基礎となるハードウェアによって異なり、正しく動作するには実験が必要です。

たとえば、Amazon EC2でクラスターを実行し、さまざまなEC2インスタンスタイプとworkersで実験して、パフォーマンスとコストのバランスを取りました。インスタンスあたりのCPUが多いほど、必要なインスタンスが少なくなり、インスタンスごとにデプロイできるworkersが増えます。しかし、我々の場合、より小さなインスタンスをデプロイする方が安価であることがわかりました。展開ごとに3人のワーカーを含む複数のm4.largeインスタンスを展開するようになりました。

興味深い副次的な注意:gunicornのパフォーマンスがAmazonロードバランサーと組み合わせて非常に悪いため、uwsgiに切り替えてパフォーマンスを大幅に向上させました。しかし、原則は同じです。

11
Boris