このチュートリアルは、「Microservices March 2022: Kubernetes Networking」の概念を実践する4つのチュートリアルのうちの1つです:
- 自動スケーリングでKubernetesのレイテンシを短縮(本記事)
- レート制限によるKubernetes APIの保護
- KubernetesアプリをSQLインジェクションから保護
- カナリアデプロイで稼働時間とレジリエンスを向上
NGINXをさらに多くのKubernetesネットワーキングのユースケースで活用するための詳しいガイダンスをお探しですか?無料のeBook「Managing Kubernetes Traffic with NGINX: 実践ガイド」をダウンロードしてください。
組織でKubernetes上に構築したアプリが、今や人気を集めています。1日あたりの訪問者数は、わずか数人から数百人(時には数千人)にまで増えました。しかし、問題があります……増加したトラフィックがボトルネックに達し、ユーザー側で遅延やタイムアウトが発生しています。ユーザー体験を改善できなければ、アプリは使われなくなってしまいます。
皆さんには、勇敢なKubernetesエンジニアとして解決策があります。Ingress controllerをデプロイしてトラフィックをルーティングし、トラフィックの変動に応じてIngress controllerのPod数が即座に増減するよう、オートスケーリングポリシーを設定します。これで、Ingress controllerのPodはトラフィックの急増にもスムーズに対応でき、「レイテンシーにさようなら!」。トラフィックが減少すればスケールダウンしてリソースを節約でき、「コスト削減にこんにちは!」。お見事です。
ラボとチュートリアルの概要
このブログは、Microservices March 2022のユニット1のラボ「高トラフィックWebサイト向けKubernetesクラスターの設計」に対応しています。NGINX Ingress Controllerを使用してアプリを公開し、高トラフィックに応じてIngress Controller Podを自動スケーリングする方法を紹介します。
このチュートリアルを実行するには、以下を備えたマシンが必要です。
- 2 CPU以上
- 2 GBの空きメモリ
- 20 GBの空きディスク容量
- インターネット接続
- Docker、Hyperkit、Hyper‑V、KVM、Parallels、Podman、VirtualBox、VMware Fusion/Workstationなどのコンテナまたは仮想マシンマネージャー
- minikubeがインストールされていること
- Helmがインストール済み
- ブラウザーウィンドウを起動できる構成。起動できない場合は、ブラウザーから該当するサービスにアクセスする方法を確認する必要があります。
ラボとチュートリアルを最大限に活用するため、開始前に以下の準備を行うことを推奨します。
- 視聴する:ライブ配信されたコンセプト概要の録画
- 確認する:背景情報を紹介するブログ
- ラボの内容を20分にまとめた動画をご覧ください: 
このチュートリアルでは、以下のテクノロジーを使用します。
- NGINX Ingress Controller(NGINX Open Sourceをベースとしています)
- Helm
- KEDA
- Locust
- minikube
- Podinfo
- Prometheus
各チャレンジの手順には、アプリの設定に使用するYAMLファイルの全文が含まれています。また、F5のGitHubリポジトリからテキストをコピーすることもできます。各YAMLファイルのテキストには、GitHubへのリンクも併記されています。
このチュートリアルには、4つの課題が含まれています。
- Kubernetesクラスター上でシンプルなアプリを構成する
- NGINX Ingress Controllerを使用してアプリにトラフィックをルーティングする
- トラフィックの生成と監視
- NGINX Ingress Controllerを自動スケーリング
チャレンジ1:Kubernetesクラスターにシンプルなアプリを構成する
このチャレンジでは、minikubeクラスターを作成し、サンプルアプリとしてPodinfoをインストールします。
Minikubeクラスターの作成
Create a minikubeクラスターを作成します。数秒後、デプロイが成功したことを示すメッセージが表示されます。
$ minikube start 🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default Podinfoアプリのインストール
Podinfoは、「Kubernetesでマイクロサービスを実行するためのベストプラクティスを紹介する、Goで作成されたWebアプリケーション」です。フットプリントが小さいため、サンプルアプリとして使用します。
- 任意のテキストエディターを使用して、以下の内容で「1-deployment.yaml」というYAMLファイルを作成します(または、GitHubからコピーします)。このファイルでは、レプリカが1つのDeploymentとServiceを定義します。
apiVersion: apps/v1 kind: Deployment
metadata:
name: podinfo
spec:
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: podinfo
image: stefanprodan/podinfo
ports:
- containerPort: 9898
---
apiVersion: v1
kind: Service
metadata:
name: podinfo
spec:
ports:
- port: 80
targetPort: 9898
nodePort: 30001
selector:
app: podinfo
type: LoadBalancer - アプリをデプロイします:
$ kubectl apply -f 1-deployment.yaml deployment.apps/podinfo created
service/podinfo created- Podinfo Podがデプロイされ、
Running列の値がSTATUSになっていることを確認します。
$ kubectl get podsNAME READY STATUS RESTARTS AGE
podinfo-5d76864686-rd2s5 1/1 Running 0 3m38s- ブラウザーでPodinfoを開きます。「greetings from podinfo」ページが表示されれば、Podinfoは稼働しています。
$ minikube service podinfo課題2:NGINX Ingress Controllerを使用してトラフィックをアプリにルーティングする
この課題では、NGINX Ingress Controllerをデプロイし、Podinfoアプリにトラフィックをルーティングするように設定します。
NGINX Ingress Controllerをデプロイ
NGINX Ingress Controllerを最も迅速にインストールするには、Helmを使用します。
- NGINXリポジトリをHelmに追加します:
$ helm repo add nginx-stable https://helm.nginx.com/stable - NGINX Open SourceベースのNGINX Ingress Controller(F5 NGINXが保守)をダウンロードしてインストールします。出力の最終行で、インストールが正常に完了したことを確認できます。
$ helm install main nginx-stable/nginx-ingress \ --set controller.watchIngressWithoutClass=true \ --set controller.service.type=NodePort \ --set controller.service.httpPort.nodePort=30005
NAME: main
LAST DEPLOYED: Tue Mar 15 09:49:17 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES: The NGINX Ingress Controller has been installed.- NGINX Ingress Controllerポッドがデプロイされたことを、
RunningがSTATUS列に表示されていることで確認します(読みやすくするため、出力は2行に分けています)。
$ kubectl get podsNAME READY STATUS ...
main-nginx-ingress-779b74bb8b-mtdkr 1/1 Running ...
podinfo-5d76864686-fjncl 1/1 Running ...
... RESTARTS AGE
... 0 18s
... 0 2m36sトラフィックをアプリにルーティング
- 任意のテキストエディターを使用して、以下の内容で「2-ingress.yaml」というYAMLファイルを作成します(または、GitHubからコピーします)。このファイルでは、Podinfoにトラフィックをルーティングするために必要なIngressマニフェストを定義します。
apiVersion: networking.k8s.io/v1 kind: Ingress
metadata:
name: podinfo
spec:
ingressClassName: nginx
rules:
- host: "example.com"
http:
paths:
- backend:
service:
name: podinfo
port:
number: 80
path: /
pathType: Prefix - Ingressリソースをデプロイします:
$ kubectl apply -f 2-ingress.yaml ingress.networking.k8s.io/podinfo created 課題3:トラフィックの生成と監視
この課題では、さまざまなトラフィック負荷におけるNGINX Ingress Controllerのパフォーマンスを観察します。準備として、NGINX Ingress Controllerで利用可能なメトリクスを一覧表示し、Prometheusをデプロイし、Locustをインストールします。次に、Locustを使用してトラフィックの急増をシミュレートし、パフォーマンスへの影響を追跡します。その結果はPrometheusで確認します。
すでに確認したとおり、Ingressコントローラーは、リバースプロキシ(ここではNGINX)とKubernetesとの統合用コードを組み合わせた通常のKubernetes Podです。アプリが大量のトラフィックを受信する場合は、NGINX Ingress Controllerの過負荷によるレイテンシーを回避するため、Podレプリカ数を増やす必要があると考えられます。
利用可能なメトリクスの一覧表示
スケーリングのタイミングと規模を判断するには、NGINX Ingress Controllerのパフォーマンスに関する正確な情報が必要です。このチュートリアルでは、スケーリングのタイミングを判断するためのNGINXメトリクスとして、アクティブな接続数(nginx_connections_active)を使用します。ここでは、NGINX Ingress Controllerがこのメトリクスを追跡していることを確認します。
NGINX Ingress Controllerは複数のメトリクスを公開します。このチュートリアルで使用するNGINX Open Sourceベースのモデルでは8個、NGINX Plusベースのモデルでは80個以上のメトリクスを公開します。
- メトリクスの一覧を照会するため、NGINX Ingress ControllerポッドのIPアドレスを取得します。アドレスは
IPフィールドに表示されます。ここでは172.17.0.4です。(読みやすくするため、RESTARTS列とAGE列を省略し、出力を2行に分けています。)
$ kubectl get pods -o wide NAME READY STATUS ...
main-nginx-ingress-779b74bb8b-6hdwx 1/1 Running ...
podinfo-5d76864686-nl8ws 1/1 Running ...
... IP NODE NOMINATED NODE READINESS GATES
... 172.17.0.4 minikube <none> <none>
... 172.17.0.3 minikube <none> <none>- Kubernetesクラスター内のホスト上に、シェルを備えた一時的なBusyBox Podを作成します:
$ kubectl run -ti --rm=true busybox --image=busyboxIf you don't see a command prompt, try pressing enter.
/ # - NGINX Ingress Controllerによって生成されたメトリクスを一覧表示し、次のメトリクスが含まれていることを確認します:
nginx_connections_active。<IP_address>には、手順1で取得した値を指定します。
/# wget -qO- <IP_address>:9113/metrics- シェルを終了して、Kubernetesサーバーに戻ります。
/# exit Prometheusをデプロイ
NGINX Ingress Controllerがnginx_connections_activeメトリクスを追跡していることを確認できたので、次にメトリクスを収集(「スクレイプ」)するツールが必要です。このチュートリアルでは、Prometheusを使用します。
NGINX Ingress Controllerと同様に、Helmを使用するのがPrometheusをインストールする最も速い方法です。
- PrometheusリポジトリをHelmに追加します:
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts- Prometheusをダウンロードしてインストールします:
$ helm install prometheus prometheus-community/prometheus \ --set server.service.type=NodePort --set server.service.nodePort=30010- インストールを確認します。通常、完了までに最大60秒かかります。次の出力例では、確認コマンドを実行したのが
helminstallコマンドの実行からわずか数秒後だったため、インストールはまだ進行中で、一部のPrometheus PodのSTATUSフィールドにContainerCreatingと表示されています。すべてのPodのステータスがRunningになると、インストールは完了です。(読みやすいように、出力を2行に分けています。)
$ kubectl get podsNAME READY ...
main-nginx-ingress-779b74bb8b-mtdkr 1/1 ...
podinfo-5d76864686-fjncl 1/1 ...
prometheus-alertmanager-d6d94cf4b-85ww5 0/2 ...
prometheus-kube-state-metrics-7cd8f95cb-86hhs 0/1 ...
prometheus-node-exporter-gqxfz 1/1 ...
prometheus-pushgateway-56745d8d8b-qnwcb 0/1 ...
prometheus-server-b78c9449f-kwhzp 0/2 ...
... STATUS RESTARTS AGE
... Running 0 3m23s
... Running 0 5m41s
... ContainerCreating 0 7s
... Running 0 7s
... Running 0 7s
... ContainerCreating 0 7s
... ContainerCreating 0 7s- Prometheusを開きます。minikube環境では、次のコマンドを実行すると、デフォルトのブラウザーでPrometheusダッシュボードが開きます。
$ minikube service prometheus-server- 次のようなページが表示されれば、サーバーが動作していることを確認できます。

- 検索バーに「
nginx_ingress_nginx_connections_active」と入力して、アクティブ接続メトリクスの現在値を確認します。NGINX Ingress Controllerポッドを1つデプロイしているため、アクティブ接続が1つと表示されます。
Locustのインストール
次のセクションでは、オープンソースの負荷テストツールであるLocustを使用してトラフィックの急増をシミュレートし、PrometheusでNGINX Ingress Controllerのパフォーマンスを確認します。ここでは、Locustをデプロイします。
- 任意のテキストエディターを使用して、以下の内容で「3-locust.yaml」という名前のYAMLファイルを作成します(または、GitHubからコピーします)。DeploymentオブジェクトとServiceオブジェクトでLocustポッドを定義します。ConfigMapオブジェクトでは、正しいヘッダーを含むリクエストを生成してポッドに送信する「locustfile.py」というスクリプトを定義します。
apiVersion: v1
kind: ConfigMap
metadata:
name: locust-script
data:
locustfile.py: |-
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
wait_time = between(0.7, 1.3)
@task
def hello_world(self):
self.client.get("/", headers={"Host": "example.com"})
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: locust
spec:
selector:
matchLabels:
app: locust
template:
metadata:
labels:
app: locust
spec:
containers:
- name: locust
image: locustio/locust
ports:
- containerPort: 8089
volumeMounts:
- mountPath: /home/locust
name: locust-script
volumes:
- name: locust-script
configMap:
name: locust-script
---
apiVersion: v1
kind: Service
metadata:
name: locust
spec:
ports:
- port: 8089
targetPort: 8089
nodePort: 30015
selector:
app: locust
type: LoadBalancer - Locustをデプロイします:
$ kubectl apply -f 3-locust.yaml configmap/locust-script created
deployment.apps/locust created
service/locust created トラフィックの急増をシミュレートし、パフォーマンスへの影響を確認する
- ブラウザーでLocustを開きます。
$ minikube service locust-

- 各フィールドに次の値を入力します:
- ユーザー数 – 1000
- 生成レート – 10
- ホスト – http://main-nginx-ingress
- [Start swarming]ボタンをクリックして、Podinfoアプリにトラフィックを送信します。
- Prometheusダッシュボードに戻り、NGINX Ingress Controllerの応答を確認します。変化を確認するには、
nginx_ingress_nginx_connections_activeに対して新たにクエリを実行する必要がある場合があります。次の画面出力に示すように、多数の接続が確立されると、単一のNGINX Ingress Controller Podでは、レイテンシーを増加させずに増大したトラフィックを処理することが困難になります。Prometheusのグラフから、NGINX Ingress Controller Podあたりのアクティブな接続数が約100に達すると、レイテンシーが急増することがわかります。この情報を使用して、レイテンシーの増加を回避するためにNGINX Ingress Controller Podの数をスケールアップするタイミングを判断できます。
課題4:NGINX Ingress Controllerを自動スケーリングする
最後の課題では、トラフィック量の増加に応じてリソースを自動スケーリングする構成を作成します。このチュートリアルでは自動スケーリングにKEDAを使用するため、まずKEDAをインストールし、スケーリングを実行するタイミングと方法を定義するポリシーを作成します。次に、課題3と同様にLocustを使用してトラフィックの急増をシミュレートし、自動スケーリングが有効な場合のNGINX Ingress ControllerのパフォーマンスをPrometheusで確認します。
KEDAをインストール
KEDAは、Kubernetesのイベント駆動型オートスケーラーです。メトリクスサーバー(Kubernetes向けのメトリクスを保存、変換するコンポーネント)を統合し、Prometheusをはじめとするツールからメトリクスを直接取得できます。これらのメトリクスを使用してHorizontal Pod Autoscaler(HPA)を作成し、Prometheusが収集したメトリクスを橋渡ししてKubernetesに渡します。

NGINX Ingress ControllerやPrometheusと同様に、このチュートリアルではHelmを使用してKEDAをインストールします。
- KEDAをHelmリポジトリに追加します:
$ helm repo add kedacore https://kedacore.github.io/charts
"kedacore" has been added to your repositories - KEDAをインストールします:
$ helm install keda kedacore/keda NAME: keda
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None- KEDAが2つのPodとして実行されていることを確認します。(読みやすくするため、
NAME列の一部の値は短縮されています。また、RESTARTS列は省略されています。すべてのPodで値は0です。)
$ kubectl get pods NAME READY STATUS AGE
keda-operator-8644dcdb79-492x5 1/1 Running 59s keda-operator-metrics-apiserver-66d... 1/1 Running 59s
locust-77c699c94d-dvb5n 1/1 Running 8m59s
main-nginx-ingress-779b74bb8b-v7ggw 1/1 Running 48m
podinfo-5d76864686-c98rb 1/1 Running 50m
prometheus-alertmanager-d6d94cf4b-8... 2/2 Running 37m
prometheus-kube-state-metrics-7cd8f... 1/1 Running 37m
prometheus-node-exporter-j4qf4 1/1 Running 37m
prometheus-pushgateway-56745d8d8b-9n4nl 1/1 Running 37m
prometheus-server-b78c9449f-6ktn9 2/2 Running 37m自動スケーリングポリシーの作成
次に、KEDAの「ScaledObject」カスタムリソース定義(CRD)を使用して、NGINX Ingress Controllerのスケーリング方法を決定するパラメーターを定義します。以下の設定では、
- Prometheusが収集した
nginx_connections_activeメトリクスの値に基づいて自動スケーリングをトリガーします - 既存の各podのアクティブ接続数が100に達すると、新しいpodをデプロイします
- NGINX Ingress ControllerのPodを1個から最大20個まで自動スケーリング
以下の手順を実行します。
- 任意のテキストエディターを使用して、以下の内容を含むYAMLファイル「4-scaled-object.yaml」を作成します(または、GitHubからコピーします)。このファイルでは、KEDAの「
ScaledObject」を定義します。
apiVersion: keda.sh/v1alpha1 kind: ScaledObject
metadata:
name: nginx-scale
spec:
scaleTargetRef:
kind: Deployment
name: main-nginx-ingress
minReplicaCount: 1
maxReplicaCount: 20
cooldownPeriod: 30
pollingInterval: 1
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus-server
metricName: nginx_connections_active_keda
query: |
sum(avg_over_time(nginx_ingress_nginx_connections_active{app="main-nginx-ingress"}[1m]))
threshold: "100" - デプロイします:
ScaledObject:
$ kubectl apply -f 4-scaled-object.yaml scaledobject.keda.sh/nginx-scale created トラフィックの急増をシミュレートし、オートスケーリングがパフォーマンスに与える影響を確認
オートスケーリングの効果を本格的に検証するため、接続数をチャレンジ3の2倍に増やします。
- ブラウザーでLocustサーバーに戻ります。各フィールドに次の値を入力し、[Start swarming]ボタンをクリックします。
- ユーザー数 – 2000
- 生成レート – 10
- ホスト – http://main-nginx-ingress
- PrometheusとLocustのダッシュボードに戻ります。Prometheusグラフの下にあるピンク色のボックスは、NGINX Ingress ControllerのPod数がスケールアップおよびスケールダウンする様子を示しています。

- ターミナルに戻り、KEDA HPAを手動で確認します。出力の「
REPLICAS」フィールドには、現在デプロイされているPodレプリカの数が表示されます。(読みやすいように、出力は2行に分けて表示しています。)
$ kubectl get hpa
NAME REFERENCE ...
keda-hpa-nginx-scale Deployment/main-nginx-ingress ...
... TARGETS MINPODS MAXPODS REPLICAS AGE
... 101500m/100 (avg) 1 20 10 2m45s次のステップ
アクティブ接続数だけに基づいてオートスケーリングを行う場合、潜在的な制約があります。スケーリングを行ってもNGINX Ingress Controllerの負荷が高まり、接続を切断せざるを得なくなると、オートスケーラーはアクティブ接続数の減少をリクエスト数の減少と解釈し、レプリカ数を減らします。その結果、パフォーマンスがさらに低下する可能性がありますが、複数のメトリクスを組み合わせて利用することで、この事態を防止できます。たとえば、nginxplus_connections_dropped(NGINX PlusベースのNGINX Ingress Controllerで利用可能)では、切断されたクライアント接続を追跡できます。
NGINX PlusおよびNGINX App Protectを搭載したNGINX Ingress Controllerをお試しいただくには、今すぐ30日間の無料トライアルを開始するか、ユースケースについてF5にお問い合わせください。
NGINX Open SourceでNGINX Ingress Controllerをお試しいただくには、リリース版のソースコードを入手するか、DockerHubからビルド済みコンテナをダウンロードできます。
関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります
