ブログ | NGINX

NGINX チュートリアル: 自動スケーリングでKubernetesのレイテンシを削減

ダニエレ・ポレンチッチ サムネイル
ダニエレ・ポレンチッチ
2022年3月15日公開

このチュートリアルは、2022 年 3 月の Microservices の概念を実践する 4 つのチュートリアルのうちの 1 つです。 Kubernetes ネットワーキング:

さらに多くの Kubernetes ネットワークユースケースで NGINX を使用するための詳細なガイダンスが必要ですか? 無料の電子書籍「NGINX を使用した Kubernetes トラフィックの管理」をダウンロードしてください。 実用ガイド

あなたの組織は Kubernetes でアプリを構築し、それが人気を集めています。 1 日あたりの訪問者数が数人から数百人 (場合によっては数千人) に増加しました。 しかし、問題があります...トラフィックの増加によりボトルネックが発生し、顧客に対して遅延やタイムアウトが発生します。 エクスペリエンスを改善できなければ、人々はアプリの使用をやめてしまいます。

勇敢な Kubernetes エンジニアであるあなたには解決策があります。 トラフィックをルーティングするために Ingress コントローラをデプロイし、トラフィックの変動に合わせて Ingress コントローラ ポッドの数が瞬時に拡大および縮小されるように自動スケーリング ポリシーを設定します。 これで、Ingress コントローラー ポッドはトラフィックの急増をシームレスに処理し (「レイテンシーとはおさらばです!」)、トラフィックが減少するとスケールダウンしてリソースを節約し (「コスト削減」を実現) ます。 よくやった、君。

ラボとチュートリアルの概要

このブログは、マイクロサービス2022 年 3 月のユニット 1 「高トラフィックの Web サイト向けの Kubernetes クラスターの設計」のラボに付随するもので、NGINX Ingress Controller を使用してアプリを公開し、高トラフィックに応じて Ingress コントローラー ポッドを自動スケーリングする方法を示します。

チュートリアルを実行するには、次の条件を満たすマシンが必要です。

  • 2CPU以上
  • 2 GBの空きメモリ
  • 20 GB の空きディスク容量
  • インターネット接続
  • Docker、Hyperkit、Hyper‑V、KVM、Parallels、Podman、VirtualBox、VMware Fusion/Workstation などのコンテナまたは仮想マシン マネージャー
  • minikubeがインストールされている
  • Helmがインストールされました
  • ブラウザ ウィンドウを起動できるようにする構成。 それが不可能な場合は、ブラウザ経由で関連サービスにアクセスする方法を検討する必要があります。

ラボとチュートリアルを最大限に活用するには、開始する前に次のことを実行することをお勧めします。

このチュートリアルでは次のテクノロジを使用します。

各チャレンジの手順には、アプリを構成するために使用される YAML ファイルの完全なテキストが含まれています。 GitHub リポジトリからテキストをコピーすることもできます。 各 YAML ファイルのテキストとともに GitHub へのリンクが提供されます。

このチュートリアルには 4 つの課題が含まれています。

  1. Kubernetes クラスター上でシンプルなアプリを構成する
  2. NGINX Ingress Controller を使用してトラフィックをアプリにルーティングする
  3. トラフィックの生成と監視
  4. NGINX Ingress コントローラーの自動スケール

課題1: Kubernetes クラスター上でシンプルなアプリを構成する

このチャレンジでは、 minikube クラスターを作成し、サンプル アプリとしてPodinfo をインストールします

Minikube クラスターを作成する

minikubeクラスターを作成します。 数秒後、デプロイメントが成功したことを確認するメッセージが表示されます。

$ minikube start 🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 

Podinfoアプリをインストールする

Podinfo は、 「Kubernetes でマイクロサービスを実行するためのベスト プラクティスを紹介する、Go で作成された Web アプリケーション」です。 フットプリントが小さいため、サンプル アプリとして使用しています。

  1. 任意のテキスト エディターを使用して、次の内容を含む1-deployment.yamlという YAML ファイルを作成します (またはGitHub からコピーします)。 単一のレプリカとサービスを持つデプロイメントを定義します。

    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 
    
  2. アプリをデプロイします。

    $ kubectl apply -f 1-deployment.yaml deployment.apps/podinfo created 
    service/podinfo created
    
  3. STATUS列の値が Running であることで示されるように、Podinfo ポッドがデプロイされていることを確認します。

    $ kubectl get podsNAME                       READY   STATUS   RESTARTS   AGE 
    podinfo-5d76864686-rd2s5   1/1     Running  0          3m38s
    
  4. ブラウザで Podinfo を開きます。 podinfo ページからの挨拶は、 Podinfo が実行中であることを示します。

    $ minikube service podinfo
    

チャレンジ2: NGINX Ingress Controller を使用してトラフィックをアプリにルーティングする

このチャレンジでは、 NGINX Ingress Controller をデプロイしトラフィックを Podinfo アプリにルーティングするように設定します。

NGINX Ingress Controller をデプロイする

NGINX Ingress Controller をインストールする最も速い方法は、 Helmを使用することです。

  1. NGINX リポジトリを Helm に追加します。

    $ helm repo add nginx-stable https://helm.nginx.com/stable 
    
  2. F5 NGINX によって管理されている NGINX オープンソースベースのNGINX Ingress Controllerをダウンロードしてインストールします。出力の最後の行でインストールが成功したことが確認できます。

    $ 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.
    
  3. STATUS列の値がRunning であることで示されるように、NGINX Ingress Controller ポッドがデプロイされていることを確認します (読みやすくするために、出力は 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
    

アプリへのトラフィックをルーティングする

  1. 任意のテキスト エディターを使用して、次の内容を含む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 
    
  2. 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 コントローラーは、Kubernetes との統合のためのコードとリバース プロキシ (この場合は NGINX) をバンドルした通常の Kubernetes ポッドです。 アプリが大量のトラフィックを受信する場合は、NGINX Ingress Controller が過負荷になったときに発生する遅延を回避するために、NGINX Ingress Controller ポッドレプリカの数を増やす必要がある可能性があります。

利用可能なメトリックの一覧

いつ、どの程度スケールするかを知るには、NGINX Ingress Controller のパフォーマンスに関する正確な情報が必要です。 このチュートリアルでは、スケーリングするタイミングを決定するために使用される NGINX メトリックは、アクティブな接続の数 ( nginx_connections_active ) です。 ここで、NGINX Ingress Controller がそのメトリックを追跡していることを確認します。

NGINX Ingress Controller は複数のメトリックを公開します。 このチュートリアルで使用している NGINX オープンソース ベースのモデルでは 8 つのメトリック、 NGINX Plus ベースのモデルでは 80 を超えるメトリックがあります。

  1. 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>
    
  2. Kubernetes クラスター内のホスト上にシェルを備えた一時的なBusyBoxポッドを作成します。

    $ kubectl run -ti --rm=true busybox --image=busyboxIf you don't see a command prompt, try pressing enter. 
    / # 
    
  3. NGINX Ingress Controller によって生成されたメトリックを一覧表示し、 nginx_connections_activeが含まれていることを確認します。 のために <IP アドレス> 手順 1 の値を代入します。

    /# wget -qO- <IP_address>:9113/metrics
    
  4. シェルを終了して Kubernetes サーバーに戻ります。

    /# exit 
    

Prometheusをデプロイする

NGINX Ingress Controller がnginx_connections_activeメトリックを追跡していることがわかったので、メトリックを収集 (「スクレイピング」) するためのツールが必要です。このチュートリアルではPrometheus を使用します。

NGINX Ingress Controller に関しては、 Helm がPrometheus をインストールする最も速い方法です。

  1. Prometheus リポジトリを Helm に追加します。

    $ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
    
  2. Prometheus をダウンロードしてインストールします。

    $ helm install prometheus prometheus-community/prometheus \ 
    --set server.service.type=NodePort --set server.service.nodePort=30010
    
  3. インストールを確認します。完了するまでに通常 60 秒ほどかかります。 次のサンプル出力では、検証コマンドがhelm installコマンドのわずか数秒後に実行されたため、インストールが進行中であり、一部の Prometheus ポッドのSTATUSフィールドにContainerCreating が報告されています。 すべてのポッドのステータスが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
    
  4. Prometheus を開きます。 minikube 環境で次のコマンドを実行すると、デフォルトのブラウザで Prometheus ダッシュボードが開きます。

    $ minikube service prometheus-server
    

    次のようなページが表示されれば、サーバーが動作していることが確認できます。

  5. アクティブ接続メトリックの現在の値を表示するには、検索バーに「nginx_ingress_nginx_connections_active」と入力します。 アクティブな接続が 1 つ表示されます。これは、NGINX Ingress Controller ポッドを 1 つデプロイしているためです。

Locustをインストールする

次のセクションでは、オープンソースの負荷テスト ツールであるLocust を使用してトラフィックの急増をシミュレートし、Prometheus で NGINX Ingress Controller のパフォーマンスを確認します。 ここで Locust を展開します。

  1. 任意のテキスト エディターを使用して、次の内容を含む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 
    
  2. ローカストを展開:

    $ kubectl apply -f 3-locust.yaml configmap/locust-script created 
    deployment.apps/locust created 
    service/locust created 
    

トラフィックの急増をシミュレートし、パフォーマンスへの影響を観察する

  1. ブラウザで Locust を開きます。

    $ minikube service locust
    

  2. フィールドに次の値を入力します。

    • ユーザー数– 1000
    • 出現率– 10
    • ホスト– http://main-nginx-ingress
  3. 「スウォーミングの開始」ボタンをクリックして、トラフィックを Podinfo アプリに送信します。

  4. Prometheus ダッシュボードに戻り、NGINX Ingress Controller がどのように応答するかを確認します。 変更を確認するには、 nginx_ingress_nginx_connections_activeに対して新しいクエリを実行する必要がある場合があります。

    次の画面出力に示されているように、多数の接続が確立されると、単一の NGINX Ingress Controller ポッドは、遅延なしで増加したトラフィックを処理するのに苦労します。 Prometheus グラフは、NGINX Ingress Controller ポッドあたり約 100 のアクティブ接続がレイテンシの急上昇の転換点であることを明らかにしています。 この情報を使用して、レイテンシの増加を回避するために NGINX Ingress Controller ポッドの数を増やす必要があるタイミングを判断できます。

課題4: NGINX Ingress コントローラーの自動スケール

最後の課題では、トラフィック量の増加に応じてリソースを自動スケーリングする構成を構築します。 このチュートリアルでは自動スケーリングに KEDA を使用するため、まずKEDA をインストールし、スケーリングがいつどのように行われるかを定義するポリシーを作成します。 チャレンジ 3 と同様に、Locust を使用してトラフィックの急増をシミュレートし、Prometheus を使用して、自動スケーリングが有効になっているときの NGINX Ingress Controller のパフォーマンスを観察します。

KEDAをインストールする

Kubernetes イベント駆動型オートスケーラーであるKEDA は、メトリック サーバー (Kubernetes のメトリックを保存および変換するコンポーネント) を統合し、Prometheus (およびその他のツール) から直接メトリックを消費できます。 これらのメトリックを使用してHorizontal Pod Autoscaler (HPA) を作成し、Prometheus によって収集されたメトリックをブリッジして、Kubernetes にフィードします。

NGINX Ingress Controller および Prometheus と同様に、チュートリアルでは Helm を使用して KEDA をインストールします。

  1. KEDA を Helm リポジトリに追加します。

    $ helm repo add kedacore https://kedacore.github.io/charts 
    "kedacore" has been added to your repositories 
    
  2. KEDA をインストールします。

    $ helm install keda kedacore/keda NAME: keda 
    NAMESPACE: default 
    STATUS: deployed 
    REVISION: 1 
    TEST SUITE: None
    
  3. KEDA が 2 つのポッドとして実行されていることを確認します。 (読みやすさを考慮して、 NAME列の一部の値は短縮されています。 また、 RESTARTS列は省略されており、値は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メトリックの値に基づいて自動スケーリングをトリガーします。
  • 既存のポッドがそれぞれ 100 のアクティブ接続に達すると、新しいポッドをデプロイします。
  • NGINX Ingress Controller ポッドを 1 個から最大 20 個まで自動スケールします。

次の手順を実行します。

  1. 任意のテキスト エディターを使用して、次の内容を含む4-scaled-object.yamlという 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" 
    
  2. ScaledObjectをデプロイします。

    $ kubectl apply -f 4-scaled-object.yaml scaledobject.keda.sh/nginx-scale created 
    

トラフィックの急増をシミュレートし、自動スケーリングがパフォーマンスに与える影響を観察する

自動スケーリングの有効性を実際にテストするには、チャレンジ 3 と比較して接続数を 2 倍にします。

  1. ブラウザで Locust サーバーに戻ります。 フィールドに次の値を入力し、 「Start swarming」ボタンをクリックします。

    • ユーザー数– 2000
    • 出現率– 10
    • ホスト– http://main-nginx-ingress
  2. Prometheus と Locust ダッシュボードに戻ります。 Prometheus グラフの下のピンク色のボックスは、スケールアップおよびスケールダウンする NGINX Ingress Controller ポッドの数を示しています。

  3. ターミナルに戻り、KEDA HPA を手動で検査します。 出力のREPLICASフィールドには、現在デプロイされているポッドレプリカの数が表示されます。 (読みやすくするために、出力は 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 Ingress Controller を NGINX Plus および NGINX App Protect とともに試用するには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、ユースケースについてご相談ください

NGINX Open Source で NGINX Ingress Controller を試すには、リリース ソース コードを入手するか、 DockerHubからビルド済みコンテナーをダウンロードします。


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