ブログ | NGINX

動的 Kubernetes クラウド環境での NGINX Ingress コントローラーのパフォーマンス テスト

NGINX-F5 水平黒タイプ RGB の一部
アミール・ラウダットのサムネイル
アミール・ラウダット
2020年9月22日公開

編集者– この投稿は10 部構成のシリーズの一部です。

  1. プロダクショングレードのKubernetesで複雑さを軽減
  2. 高度なトラフィック管理で Kubernetes の回復力を向上させる方法
  3. Kubernetes の可視性を向上させる方法
  4. トラフィック管理ツールを使用して Kubernetes を保護する 6 つの方法
  5. Ingress コントローラーの選択ガイド、パート 1: 要件を特定する
  6. Ingress コントローラーの選択ガイド、パート 2: リスクと将来への備え
  7. Ingress コントローラーの選択ガイド、パート 3: オープンソース vs. デフォルト vs. コマーシャル
  8. Ingress コントローラーの選択ガイド、パート 4: NGINX Ingress コントローラー オプション
  9. サービスメッシュの選択方法
  10. 動的 Kubernetes クラウド環境での NGINX Ingress コントローラーのパフォーマンス テスト (この投稿)

また、ブログの完全セットを無料の電子書籍「 Taking Kubernetes from Test to Production」としてダウンロードすることもできます。

コンテナ化されたアプリケーションを本番環境で実行する企業が増えるにつれて、Kubernetes はコンテナ オーケストレーションの標準ツールとしての地位を固め続けています。 同時に、COVID-19パンデミックによる在宅勤務の取り組みによりインターネットトラフィックの増加が加速したため、クラウドコンピューティングの需要は数年早まっています。 顧客が大規模なネットワーク障害や過負荷を経験しているため、企業はインフラストラクチャのアップグレードに急いで取り組んでいます。

クラウドベースのマイクロサービス環境で必要なレベルのパフォーマンスを達成するには、次世代のハイパースケール データ センターの拡張性とパフォーマンスを活用する、高速で完全に動的なソフトウェアが必要です。 Kubernetes を使用してコンテナを管理する多くの組織は、NGINX ベースの Ingress コントローラーを使用してユーザーにアプリを配信しています。

このブログでは、現実的なマルチクラウド環境における 3 つの NGINX Ingress コントローラーのパフォーマンス テストの結果を報告し、インターネット経由のクライアント接続のレイテンシを測定します。

テストプロトコルと収集されたメトリクス

負荷生成プログラムwrk2 を使用してクライアントをエミュレートし、定義された期間に HTTPS 経由で継続的にリクエストを送信しました。 テスト対象の Ingress コントローラー (コミュニティ Ingress コントローラー、NGINX Open Source に基づく NGINX Ingress コントローラー、または NGINX Plus に基づく NGINX Ingress コントローラー) は、Kubernetes Pod にデプロイされたバックエンド アプリケーションにリクエストを転送し、アプリケーションによって生成された応答をクライアントに返しました。 Ingress コントローラのストレステストを行うために、クライアント トラフィックの安定したフローを生成し、次のパフォーマンス メトリックを収集しました。

  • レイテンシ – クライアントがリクエストを生成してから応答を受信するまでの時間。 レイテンシはパーセンタイル分布で報告します。 たとえば、レイテンシ テストからのサンプルが 100 個ある場合、99 パーセンタイルの値は、100 回のテスト実行全体で応答の2 番目に遅いレイテンシになります。
  • 接続タイムアウト – Ingress コントローラーが一定時間内にリクエストに応答できなかったために、暗黙的にドロップまたは破棄される TCP 接続。
  • 読み取りエラー – Ingress コントローラーからのソケットが閉じられているために失敗した接続での読み取り試行。
  • 接続エラー – クライアントと Ingress コントローラー間の TCP 接続が確立されていません。

トポロジー

すべてのテストでは、AWS のクライアントマシンで実行されているwrk2ユーティリティを使用してリクエストを生成しました。 AWS クライアントは、Google Kubernetes Engine (GKE) 環境のGKE-node-1に Kubernetes DaemonSetとしてデプロイされた Ingress コントローラの外部 IP アドレスに接続しました。 Ingress コントローラーは、SSL ターミネーション (Kubernetes Secretを参照) とレイヤー 7 ルーティング用に設定され、タイプLoadBalancerの Kubernetesサービスを介して公開されました。 バックエンド アプリケーションは、GKE-node-2上の Kubernetes Deploymentとして実行されました。

クラウド マシンの種類とソフトウェア構成の詳細については、付録を参照してください。

テスト方法

クライアントの展開

AWS クライアントマシンで次のwrk2 (バージョン 4.0.0) スクリプトを実行しました。 2 つのwrkスレッドが生成され、それらが一緒に GKE にデプロイされた Ingress コントローラへの 1000 の接続を確立します。 3 分間のテスト実行ごとに、スクリプトは 1 秒あたり 30,000 件のリクエスト (RPS) を生成します。これは、実稼働環境の Ingress コントローラーにかかる負荷を適切にシミュレートしていると考えられます。

wrk -t2 -c1000 -d180s -L -R30000 https://app.example.com:443/

どこ:

  • -t – スレッド数を設定する (2)
  • -c – TCP接続数を設定します(1000)
  • -d – テスト実行の継続時間を秒単位で設定します(180、つまり3分)
  • -L – 分析ツールにエクスポートするための詳細なレイテンシパーセンタイル情報を生成します
  • -R – RPSの数を設定します(30,000)

TLS 暗号化には、 2048 ビットのキー サイズと Perfect Forward Secrecy を備えた RSA を使用しました。

バックエンドアプリケーション( https://app.example.com:443でアクセス)からの各応答は、約1KBの基本的なサーバーメタデータと、 200OK HTTP ステータス コード。

バックエンドアプリケーションの展開

バックエンド アプリケーションの静的デプロイメントと動的デプロイメントの両方でテスト実行を実施しました。

静的デプロイメントでは、5 つの Pod レプリカがあり、Kubernetes API を使用して変更は適用されませんでした。

動的デプロイメントでは、次のスクリプトを使用して、バックエンドのnginxデプロイメントを 5 つの Pod レプリカから 7 つに定期的にスケールし、その後 5 つに戻しました。 これは動的な Kubernetes 環境をエミュレートし、Ingress コントローラーがエンドポイントの変更にどれだけ効果的に適応するかをテストします。

while [ 1 -eq 1 ]
do
kubectl scale deploy nginx --replicas=5
sleep 12
kubectl scale deploy nginx --replicas=7
sleep 10
done

パフォーマンス結果

静的デプロイメントのレイテンシ結果

グラフに示されているように、3 つの Ingress コントローラはすべて、バックエンド アプリケーションの静的デプロイメントで同様のパフォーマンスを達成しました。 これらはすべて NGINX オープンソースに基づいており、静的デプロイメントでは Ingress コントローラーから再構成する必要がないことを考えると、これは理にかなっています。

動的展開のレイテンシ結果

このグラフは、バックエンド アプリケーションを 5 つのレプリカ ポッドから 7 つまで定期的にスケーリングした動的デプロイメントで、各 Ingress コントローラによって発生したレイテンシを示しています (詳細については、 「バックエンド アプリケーションのデプロイメント」を参照してください)。

この環境では、 NGINX Plus ベースのIngress コントローラーだけが優れたパフォーマンスを発揮し、99.99 パーセンタイルまで実質的に遅延が発生しないことは明らかです。 コミュニティと NGINX オープンソース ベースの Ingress コントローラーはどちらも、かなり低いパーセンタイルで顕著な遅延が発生しますが、パターンはかなり異なります。 コミュニティ Ingress コントローラーの場合、レイテンシは緩やかに、しかし着実に 99 パーセンタイルまで上昇し、そこで約 5000 ミリ秒 (5 秒) で安定します。 NGINX オープンソースベースの Ingress コントローラの場合、レイテンシは 99 パーセンタイルで約 32 秒に急上昇し、99.99 パーセンタイルでは再び60 秒に上昇します

「動的デプロイメントのタイムアウトとエラー結果」でさらに説明するように、コミュニティと NGINX オープンソースベースの Ingress コントローラーで発生する遅延は、バックエンド アプリケーションのエンドポイントの変更に応じて NGINX 構成が更新および再ロードされた後に発生するエラーとタイムアウトによって発生します。

以下は、前のグラフと同じテスト条件でのコミュニティ Ingress コントローラーとNGINX Plus ベースのIngress コントローラーの結果の詳細なビューです。 NGINX Plus ベースのIngress コントローラーは、99.99 パーセンタイルまでは実質的に遅延が発生しませんが、99.9999 パーセンタイルでは 254 ミリ秒に向かって上昇し始めます。 コミュニティ Ingress コントローラーのレイテンシ パターンは、99 パーセンタイルで 5000 ミリ秒のレイテンシまで着実に増加し、その時点でレイテンシは安定します。

動的デプロイメントのタイムアウトとエラー結果

この表には、遅延結果の原因がより詳しく示されています。

  NGINX オープンソース コミュニティ NGINX プラス
接続エラー 33365 0 0
接続タイムアウト 309 8809 0
読み取りエラー 4650 0 0

NGINX オープンソース ベースの Ingress コントローラーでは、バックエンド アプリケーションのエンドポイントが変更されるたびに NGINX 構成を更新して再ロードする必要があるため、多くの接続エラー、接続タイムアウト、読み取りエラーが発生します。 接続/ソケット エラーは、NGINX がリロードするのにかかる短い時間の間に、クライアントが NGINX プロセスに割り当てられなくなったソケットに接続しようとすると発生します。 接続タイムアウトは、クライアントが Ingress コントローラーへの接続を確立したが、バックエンド エンドポイントが利用できなくなった場合に発生します。 エラーとタイムアウトはどちらもレイテンシに重大な影響を及ぼし、99 パーセンタイルでは 32 秒、99.99 パーセンタイルでは再び60 秒に急上昇します。

コミュニティ Ingress コントローラーでは、バックエンド アプリケーションのスケールアップとスケールダウンに伴うエンドポイントの変更により、8,809 回の接続タイムアウトが発生しました。 コミュニティ Ingress コントローラーは、エンドポイントが変更されたときに構成の再読み込みを回避するために Lua コードを使用します。 結果は、NGINX 内で Lua ハンドラーを実行してエンドポイントの変更を検出すると、エンドポイントを変更するたびに構成を再ロードする必要があることから生じる NGINX オープンソース ベース バージョンのパフォーマンス制限の一部に対処できることを示しています。 それでも、接続タイムアウトは依然として発生し、高いパーセンタイルでは大きな遅延が発生します。

NGINX Plus ベースのIngress コントローラーでは、エラーやタイムアウトは発生せず、動的環境はパフォーマンスにほとんど影響を与えませんでした。 これは、エンドポイントが変更されたときに NGINX Plus API を使用して NGINX 構成を動的に更新するためです。 前述のように、最高のレイテンシは 254 ミリ秒で、99.9999 パーセンタイルでのみ発生しました。

結論

パフォーマンス結果から、動的な Kubernetes クラウド環境でタイムアウトとエラーを完全に排除するには、Ingress コントローラーがイベント ハンドラーや構成の再読み込みなしでバックエンド エンドポイントの変更に動的に調整する必要があることがわかります。 結果に基づくと、 NGINX Plus API は、動的な環境で NGINX を動的に再構成するための最適なソリューションであると言えます。 私たちのテストでは、 NGINX Plus ベースのIngress コントローラーのみが、ユーザーの満足を維持するために必要な、高度に動的な Kubernetes 環境で完璧なパフォーマンスを達成しました。

付録

クラウドマシンの仕様

機械 クラウドプロバイダー マシンタイプ
クライアント アマゾン m5a.4xlarge
GKE ノード 1 グーグル e2-標準-32
GKE ノード 2 グーグル e2-標準-32

NGINX オープンソースおよび NGINX Plus Ingress コントローラーの構成

Kubernetes 構成

apiバージョン: apps/v1
種類: DaemonSet
メタデータ:
名前: nginx-ingress
名前空間: nginx-ingress
仕様:
セレクター:
matchLabels:
アプリ: nginx-ingress
テンプレート:
メタデータ:
ラベル:
アプリ: nginx-ingress
#アノテーション:
#prometheus.io/scrape: "true"
#prometheus.io/port: "9113"
仕様:
サービス アカウント名: nginx-ingress
ノード セレクター:
kubernetes.io/ホスト名: gke-rawdata-cluster-default-pool-3ac53622-6nzr
ホスト ネットワーク: true
コンテナ:
-イメージ: gcr.io/nginx-demos/nap-ingress:edge
イメージ プル ポリシー: 常に
名前: nginx-plus-ingress
ポート:
- 名前: http
コンテナポート: 80
ホストポート: 80
- 名前: https
コンテナポート: 443
ホストポート: 443
- 名前: 準備ポート
コンテナポート: 8081
#- 名前: プロメテウス
# コンテナポート: 9113
readinessProbe:
httpGet:
パス: /nginx-ready
ポート: readiness-port
periodSeconds: 1
securityContext:
allowPrivilegeEscalation: true
runAsUser: 101 #nginx
機能:
削除:
- ALL
追加:
- NET_BIND_SERVICE
環境:
- 名前: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- 名前: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args:
- -nginx-plus
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret

注:

  • この構成は NGINX Plus 用です。 NGINX Open Source の構成では、必要に応じてnginx‑plusへの参照が調整されました。
  • NGINX App Protect はイメージ ( gcr.io/nginx-demos/nap-ingress:edge ) に含まれていますが、無効になっています ( -enable-app-protectフラグが省略されています)。

構成マップ

親切: ConfigMap
apiVersion: v1
メタデータ:
名前: nginx-config
名前空間: nginx-ingress
データ:
ワーカー接続: 「10000」
ワーカー制限なしファイル: 「10240」
キープアライブ: 「100」
キープアライブ要求: 「100000000」

コミュニティ NGINX Ingress コントローラーの設定

Kubernetes 構成

apiバージョン: apps/v1
種類: DaemonSet
メタデータ:
ラベル:
helm.sh/chart: ingress-nginx-2.11.1
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.34.1 app.kubernetes.io/maned-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
spec:
nodeSelector: 
kubernetes.io/hostname: gke-rawdata-cluster-default-pool-3ac53622-6nzr
hostNetwork: true
containers:
- name: controller
image: us.gcr.io/k8s-artifacts-prod/ingress-nginx/controller:v0.34.1@sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20
イメージプルポリシー: IfNotPresent
ライフサイクル:
preStop:
exec:
コマンド:
- /wait-shutdown
引数:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
securityContext:
機能:
ドロップ:
- ALL
追加:
- NET_BIND_SERVICE
runAsUser: 101
allowPrivilegeEscalation: true
env:
- 名前: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
readinessProbe:
httpGet:
path: /healthz
port: 10254
スキーム: HTTP
期間秒数: 1
ポート:
- 名前: http
コンテナポート: 80
プロトコル: TCP
- 名前: https
コンテナポート: 443
プロトコル: TCP
- 名前: webhook
コンテナポート: 8443
プロトコル: TCP
ボリュームマウント:
-名前: webhook-cert
マウントパス: /usr/local/certificates/
読み取り専用: true
サービスアカウント名: ingress-nginx
終了GracePeriodSeconds: 300
ボリューム:
- 名前: webhook-cert
シークレット:
シークレット名: ingress-nginx-admission

構成マップ

apiバージョン: v1
種類: ConfigMap
メタデータ:
名前: ingress-nginx-controller
名前空間: ingress-nginx
データ:
max-worker-connections: 「10000」
ワーカーが開くファイルの最大数: 「10204」
アップストリーム キープアライブ接続: 「100」
キープアライブリクエスト: 「100000000」

バックエンドアプリの構成

Kubernetes 構成

apiバージョン: apps/v1
種類: デプロイメント
メタデータ:
名前: nginx
仕様:
セレクター:
matchLabels:
アプリ: nginx 
テンプレート:
メタデータ:
ラベル:
アプリ: nginx
仕様:
ノードセレクター:
kubernetes.io/hostname: gke-rawdata-cluster-default-pool-3ac53622-t2dz 
コンテナ:
- 名前: nginx
イメージ: nginx
ポート:
- コンテナポート: 8080
volumeMounts: 
- 名前: main-config-volume
mountPath: /etc/nginx
- 名前: app-config-volume
mountPath: /etc/nginx/conf.d
readinessProbe:
httpGet:
パス: /healthz
ポート: 8080
期間秒数: 3
ボリューム: 
- 名前: main-config-volume
configMap:
名前: main-conf
- 名前: app-config-volume
configMap: 
名前: app-conf
---

構成マップ

apiバージョン: v1
種類: ConfigMap
メタデータ:
名前: main-conf
名前空間: default
データ:
nginx.conf: |+
user nginx;
worker_processes 16;
worker_rlimit_nofile 102400;
worker_cpu_affinity auto 1111111111111111;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 100000;
}

http {

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

sendfile on;
tcp_nodelay オン;

access_log オフ;

/etc/nginx/conf.d/*.conf をインクルードします;
}

---

apiVersion: v1
kind: ConfigMap
メタデータ:
名前: app-conf
名前空間: default
データ:
app.conf: "server {listen 8080;location / {default_type text/plain;expires -1;return 200 'サーバー アドレス: $server_addr:$server_port\nサーバー名:$hostname\n日付: $time_local\nURI: $request_uri\nリクエスト ID: $request_id\n';}location /healthz {return 200 '私は幸せで健康です :)';}}"
---

サービス

apiバージョン: v1
種類: サービス
メタデータ:
名前: app-svc
仕様:
ポート:
- ポート: 80
ターゲットポート: 8080
プロトコル: TCP
名前: http
セレクタ:
アプリ: nginx
---

「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"