NGINX(エンジンエックス)|日本公式サイト

NGINXはF5ファミリーの一員となりました。新体制の詳細はこちらを御覧ください。

レート制限をNGINXサービスメッシュで実現する方法

悪意のあるリクエスト(ブルートフォースパスワード推測やDDoS攻撃)であるか、正常なリクエストであるか(セールに集まる大量の顧客)に関係なく、大量のHTTPリクエストは、サービスに負荷をかけ、アプリケーションを停止させる可能性があります。この問題を簡単に解決する方法が、レート制限であり、一定時間内に各ユーザーが行えるリクエストの数を制限することなのです。しかし、Kubernetes環境では、サービスに到達する総トラフィック量のかなりの部分が、他のサービスとの通信という形で、Ingressコントローラーの管理対象とするスコープの外になっている可能性があります。このような状況では、サービスメッシュを使用してレート制限ポリシーを設定することが理にかなっていることが多いのです。

NGINXサービスメッシュでレート制限を設定するのは簡単で、10分もかからずに完了することができます。このデモをご覧になり、レート制限ポリシーを定義して適用する方法をご確認ください。

デモ:NGINXサービスメッシュによるレート制限の設定

このデモでは、NGINXサービスメッシュサイドカーを注入した3つのコンテナを利用します。バックエンドサービス、フロントエンドサービス、そしてbashターミナルの3つです。

NGINXサービスメッシュコントロールプレーンもデプロイされています。フロントエンドサービスはバックエンドサービスに1秒ごとにリクエストを送信し、そのレスポンスをフロントエンドサービスのログで確認することができます。

backend v1
backend v1
backend v1
backend v1

レート制限ポリシーの適用(1:00)

バックエンドサービスにあまり多くのリクエストを転送したくない場合を考えてみましょう。 以下のフィールドを持つカスタムリソースとして、レート制限ポリシーを定義することができます。

  • destination – リクエストを受け取るサービスです。ここではバックエンドのサービスです。
  • sources – リクエストが来るクライアントのリストで、それぞれレート制限の対象となります。ここでは、1つのソース、フロントエンドサービスだけを定義しています。
  • rate – レート制限です。ここでは、1 分あたり 10 リクエスト、あるいは 6 秒に 1 リクエストの割合になっています。
apiVersion: specs.smi.nginx.com/v1alpha1
kind: RateLimit
metadata:
  name: backend-rate-limit
  namespace: default
spec:
  destination:
    kind: Service
    name: backend-svc
    namespace: default
  sources:
  - kind: Deployment
    name: frontend
    namespace: default
  name: 10rm
  rate: 10r/m
  burst: 0
  delay: nodelay

以下のコマンドを実行して、ポリシーを有効にします。

$ kubectl create -f rate-limit.yaml

フロントエンドのログを見ると、6つのリクエストのうち5つが以下のメッセージとともに拒否されていることがわかります。

<html>
<head><title>503 Service Temporarily Unavailable</title</head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.19.5</center>
</body>
</html>

すべてのクライアントにレート制限を適用する (2:32)

レート制限は、sourcesフィールドに指定されたクライアント(デモ環境ではフロントエンドサービス)にのみ適用されます。バックエンドサービスは、他のすべてのクライアントからのリクエストを、 リクエストの転送レートに関わらず受け付け、各リクエストは成功を示すbackend v1 レスポンスを受け取ります。

すべてのクライアントにレート制限を適用するには、2つの方法があります。1つ目は、sourcesフィールドに対象の名前を追加する方法です。2つ目は、よりシンプルな方法で、sourcesフィールドを完全に削除することです。以下コマンドを実行して、ポリシーを編集します。

$ kubectl edit ratelimits.specs.smi.nginx.com backend-rate-limit

編集したポリシーを保存した後、再びbashターミナルでリクエストしてみると、レート制限を超えたソースからのリクエストは、上記のようなフォーマットされた503エラーで拒否されることがわかります。

リクエストのバーストを許可する (3:43)

レート制限をカスタマイズするために、その他のいくつかのフィールドがポリシーには存在します。アプリケーションの中には、「バースト的」に連続した複数のリクエストを送信するものがあることが分かっています。これに対応するために、burstフィールドを指定することが可能です。ここでは 3 に設定しています。つまり、バックエンドサービスは 6 秒ごとにその数の追加リクエストを受け付けます。それ以上のリクエストは拒否されます。

delayフィールドは、リクエストが許容するバーストがバックエンドサービスにどのように転送されるかを制御します。これがなければ (つまりデフォルトでは)、バーストリクエストはキューに入れられ、指定したレート制限に従って、リクエストごとの間隔を保ち、新しいリクエストとともに転送されます。バーストしたリクエストをすぐに送るために、delayフィールドを値 nodelayに設定することができます。

また、delayフィールドを整数に設定することもできます。例えば、これを 3 に設定し、burstフィールドを 5 に増やすと、6 秒周期で 5 つ以上のバーストリクエストが到着すると、3 つは直ちに送信され、2 つはキューに入れられ、残りは拒否されます。

burst: 3delay: nodelay と設定した場合の効果をログで観察することができます。リクエストが拒否される前に、3つの余分なリクエストが受け入れられるのがわかります。

backend v1
backend v1
backend v1
backend v1
<html>
<head><title>503 Service Temporarily Unavailable</title</head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.19.5</center>
</body>
</html>
. . .

レート制限の解除 (6:30)

このデモの最後のアクションは、レート制限ポリシーを解除し、すべてのリクエストを受け入れます。そのために、以下のコマンドを実行します。

$ kubectl delete -f rate-limit.yml

NGINXサービスメッシュによるレート制限を試してみる

burstとdelayのパラメータの詳細については、reference documentationを参照してください。その他のトラフィックマネジメントパターンについては、ブログ「高度なトラフィック管理で実現する強靭なKubernetesプラットフォーム」をご覧ください。

また、NGINXサービスメッシュの機能を紹介するビデオデモもご覧ください。

NGINXサービスメッシュは完全に無料で、すぐにダウンロードでき、10分以内にデプロイすることができます! まずはドキュメントを確認し、GitHubで使い方のフィードバックをください。

関連資料

サンプルNGINX Plus 無料トライアル サンプルダウンロード資料 サンプル無料ウェビナー