NGINX と Google Compute Engine を使用した HTTPS 負荷分散

HTTP(S)負荷分散はウェブサイトまたはウェブ アプリケーションの拡張に欠かせないツールで、単一 IP からトラフィックをルーティングし、それを複数のバックエンドに配布します。また、HTTP(S)負荷分散では、非常にきめ細かな受信リクエストのルーティングも可能にします。適切な設定を使用して、起点の地理的位置、リクエストされたコンテンツのタイプ、マシンリソースの利用可能性などに基づいたリクエストを、ロードバランサがルーティングするように設定することができます。

このチュートリアルでは、負荷分散の 1 つのソリューションである、Compute Engine での NGINX ベースの HTTP(S)ロードバランサについて説明します。NGINX は、完成度の高い機能セットと優れた設定性を備えた一般的な負荷分散ソリューションです。機能には次のものがあります。

  • SSL の暗号化と暗号解除
  • サーバーの重み付け
  • セッションの永続性
  • ヘルスチェック
  • いくつかの一般的な負荷分散アルゴリズム

Compute Engine の組み込み HTTP(S)負荷分散ソリューションと比較して、NGINX ベースのソリューションにも制限事項があります。

  • NGINX ベースのロードバランサは、単一の Compute Engine インスタンスにインストールされているため、このロードバランサは単一の障害発生点となります。一方 Compute Engine の HTTP(S)ロードバランサ ソリューションは、冗長性とフォールト トレランスが組み込まれたマネージド サービスです。
  • Compute Engine のインスタンスは、特定の Compute Engine のゾーンに関連付けられているため、すべてのトラフィックは、トラフィックが発生した地点に関係なく、ロードバランサのインスタンスが置かれるゾーンを経由して収集されます。一方、Compute Engine の HTTP(S)負荷分散ソリューションは、リクエスト側のクライアントに最も近いゾーンでトラフィックを受け取り、ルーティングできます。設定例については地域にまたがる負荷分散をご覧ください。

実装の概要

このチュートリアルでは、簡単な NGINX ベースの HTTP(S)ロードバランサを構築します。このロードバランサはエンドツーエンドの SSL/TLS 暗号化機能を備えているため、トラフィックは 3 つの SSL/TLS 対応 Apache ウェブサーバーのいずれか 1 つにルーティングされ、受信 HTTP トラフィックは、このロードバランサから渡されるときに暗号化されます。

次の図に、このロードバランサのアーキテクチャを示します。

NGINX ベースの HTTPS ロードバランサのアーキテクチャ
図 1: NGINX ベースの HTTPS ロードバランサのアーキテクチャ

事前準備

このチュートリアルは、次の設定タスクが実行済みであることを前提としています。

さらに、このチュートリアルでは、Linux または MacOSX で Bash コマンドラインを使用していることを前提としています。

SSL/TLS 証明書の取得

NGINX と Apache がトラフィックを暗号化できるようにするには、それぞれの設定に追加できる秘密鍵と署名済み SSL/TLS 証明書を用意しておく必要があります。

秘密鍵、証明書、認証局が発行した PEM ファイル(オプション)をすでに用意している場合は、ssl-certs という新しいディレクトリを作成し、そのディレクトリにファイルをコピーします。この作業が完了したら、このチュートリアルの次のセクションに進みます。

秘密鍵と証明書をまだ用意していない場合は、openssl コマンドを使用して、新しい鍵を作成し、自己署名証明書を生成することができます。

新しい秘密鍵を作成するには次のようにします。

  1. 鍵と証明書を格納する新しいディレクトリを作成します。

    mkdir ssl-certs
    
  2. この新しいディレクトリに移動します。

    cd ssl-certs
    
  3. openssl で鍵を生成します。

    openssl genrsa -out example.key 2048
    
  4. 鍵のパスフレーズを削除します(オプション)。

    openssl rsa -in example.key -out example.key
    

署名済み証明書を生成するには、証明書署名リクエスト(CSR)が必要です。次のコマンドを実行して作成してください。

openssl req -new -key example.key -out example.csr

この新しい CSR を使用して、有効な証明書を認証局から取得します。または、次のコマンドを実行して、自己署名証明書を生成します。

openssl x509 -req -days 365 -in example.csr -signkey example.key -out example.crt

ロードバランサのバックエンドを作成して設定する

ロードバランサを作成する前に、ロードバランサがルーティングできるバックエンド サーバーのインスタンスを用意しておく必要があります。このセクションでは、ロードバランサ用のバックエンドとして使用できる、同一の Compute Engine 仮想マシンのインスタンスを 3 つ作成します。バックエンドが作成されたら、SSL を使用できるようにそれぞれの Apache サーバーを設定します。

ロードバランサのバックエンドを作成する

ロードバランサのバックエンドを作成し、このバックエンドに外部 HTTPS トラフィックからアクセスできるようにするには、次のようにします。

  1. 仮想マシンのインスタンスを作成し、同じようにタグを付け、Apache ウェブサーバーをインストールして Apache の SSL モジュールを有効にします。

    for i in {1..3}; \
      do \
        gcloud compute instances create www-$i --tags be-tag \
          --zone us-central1-f \
          --metadata startup-script="#! /bin/bash
          apt-get update
          apt-get install -y apache2
          /usr/sbin/a2ensite default-ssl
          service apache2 reload
          /usr/sbin/a2enmod ssl
              "; \
      done
    
  2. 外部 HTTPS トラフィックがターゲット インスタンスにアクセスすることを許可するファイアウォール ルールを作成します。

    gcloud compute firewall-rules create https-firewall \
      --target-tags be-tag --allow tcp:443
    
  3. インスタンスの外部 IP アドレスを取得します。

    gcloud compute instances list
    
  4. curl を実行して、各インスタンスが起動して実行されていることを確認します。

    curl -k https://<ip_address>
    

SSL 証明書のインストール

これで、バックエンド サーバーのインスタンスは正常に動作するようになり、鍵、証明書、PEM ファイル(該当する場合)をインストールできます。次のようにファイルをインスタンスにコピーすることから始めます。

for i in {1..3};
  do \
    gcloud compute copy-files /local/path/to/ssl-certs \
      root@www-$i:/etc/apache2; \
  done

次に、各インスタンスに対して、次のタスクを実行します。

  1. インスタンスへの SSH 接続を確立します。

    gcloud compute ssh [INSTANCE_NAME]

  2. default-ssl: を編集します。

    sudo nano /etc/apache2/sites-enabled/default-ssl
    
  3. 次の行を検索します。

    SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
    SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
    
  4. この例のパスを独自の証明書と鍵へのパスに置き換えます。

    SSLCertificateFile    /etc/apache2/ssl-certs/example.crt
    SSLCertificateKeyFile /etc/apache2/ssl-certs/example.key
    
  5. SSLCertificateChainFile で始まる行が見つかったら、その行のパスを認証局が提供する SSL 証明書チェーン ファイルへのパスに置き換えます。

  6. Apache をリロードします。

    sudo service apache2 reload
    
  7. インスタンスごとにステップ 1~6 を繰り返します。

ロードバランサの作成と設定

バックエンド サーバーが適切な位置に設定されたので、次にロードバランサを作成し、バックエンド サーバーへのトラフィックをルーティングするように設定します。

NGINX インスタンスの作成

NGINX インスタンスを作成するには、次のようにします。

  1. 新しい静的 IP アドレスを作成します。

    gcloud compute addresses create lb-ip \
      --region us-central1
    
  2. 外部 HTTPS トラフィックがロードバランサのインスタンスにアクセスすることを許可するファイアウォール ルールを作成します。このチュートリアルの後半では、HTTPS プロキシ経由でこのトラフィックをリダイレクトするようにロードバランサを設定します。

    gcloud compute firewall-rules create http-firewall \
       --target-tags lb-tag --allow tcp:80
    
  3. Compute Engine インスタンスを新たに作成し、新しい静的 IP アドレスをインスタンスに割り当てて、インスタンスにタグ付けします。これで HTTP トラフィックと HTTPS トラフィックの両方を受信できるようになります。

    gcloud compute instances create nginx-lb \
      --zone us-central1-f --address lb-ip \
      --tags lb-tag,be-tag
    
  4. nginx-lb インスタンスへの SSH 接続を確立します。

    gcloud compute ssh nginx-lb

  5. インスタンスの Debian レポジトリを更新します(user@nginx-lb として)。

    sudo apt-get update
    
  6. NGINX をインストールします。

    sudo apt-get install -y nginx
    
  7. exit コマンドを実行して SSH セッションを終了します。

セッションを終了したら、gcloud compute を使用して、秘密鍵、SSL/TLS 証明書、認証局の PEM ファイル(該当する場合)をロードバランサにコピーします。

gcloud compute copy-files /local/path/to/ssl-certs \
  root@nginx-lb:/etc/nginx --zone us-central1-f

仮想ホストの作成

NGINX がインストールされ、SSL/TLS ファイルがインスタンスにコピーされたので、HTTPS ロードバランサとしての NGINX インストール環境の設定を開始できます。

  1. 次のコマンドを実行して、インスタンスの IP のリストを表示します。

    gcloud compute instances list
    

    ターゲット インスタンスの内部 IP を記録します。この IP は NGINX の設定を開始するときに必要になります。

  2. nginx-lb インスタンスへの SSH 接続を確立します。

    gcloud compute ssh nginx-lb

  3. 新しい仮想ホストファイルを作成して開きます。

    sudo nano /etc/nginx/sites-available/my-vhost
    
  4. 新しいトップレベルの upstream ディレクティブを作成し、バックエンド サーバーのインスタンスをここに追加して、インスタンスごとに内部 IP アドレスを指定します。バックエンド サーバーのインスタンスは SSL/TLS で暗号化されたトラフィックのみを受信するように設定されているため、次のようにポート 443 を各 IP に追加します。

    upstream lb {
      server <ip_address_1>:443;
      server <ip_address_2>:443;
      server <ip_address_3>:443;
    }
    
  5. 受信 HTTPS トラフィックと発信 HTTPS トラフィックをルーティングするようにロードバランサを設定します。仮想ホストファイルに新しいトップレベルの server ディレクティブを作成し、次のように指定します。

    server {
      listen 443 ssl;
      server_name lbfe;
      ssl on;
      ssl_certificate         /etc/nginx/ssl-certs/example.crt;
      ssl_certificate_key     /etc/nginx/ssl-certs/example.key;
      location / {
        proxy_pass https://lb;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
      }
    }
    

    このディレクティブは、ポート 443 で HTTPS トラフィックをリッスンすることを NGINX に指示し、鍵と証明書を使用してトラフィックの暗号化解除と暗号化を行い、upstream ディレクティブ(lb)で指定した 3 つのサーバーのいずれか 1 つにトラフィックをルーティングします。

  6. 追加のトップレベルの server ディレクティブを追加し、HTTP トラフィックを傍受し、それを HTTPS ゲートウェイにリダイレクトします。

    server {
      listen 80;
      return 301 https://$host$request_uri;
    }
    
  7. 仮想ホストファイルを保存して閉じます。

これでロードバランサの設定が完了したため、マイナーなクリーンアップとサニティ チェック作業を実行します。

  1. sites-enabled ディレクトリにシンボリック リンクを作成します。

    sudo ln -s /etc/nginx/sites-available/my-vhost \
      /etc/nginx/sites-enabled/my-vhost
    
  2. ホスト設定の競合を回避するため、デフォルトの仮想ホストファイルを削除します。

    sudo rm /etc/nginx/sites-enabled/default
    
  3. 設定をテストしてエラーの有無を確認します。

    sudo service nginx configtest
    

すべて問題がなければ、NGINX サービスをリロードして SSL/TLS 対応の仮想ホストを追加します。

sudo service nginx reload

これですべての操作に対応する HTTPS ロードバランサが設定されました。

ロードバランサの設定

ロードバランサが動作するようになったので、ニーズに適合するように設定します。

SSL/TLS 設定の強化

古い暗号や暗号化プロトコルによって引き起こされる可能性のある脆弱性を取り除くため、最新のベスト プラクティスが反映されるように SSL/TLS 設定をカスタマイズする必要があります。

SSL/TLS 設定を強化するには次のようにします。

  1. サーバーの暗号がクライアントの暗号よりも優先されるように ssl_prefer_server_ciphers ディレクティブを設定します。

    ssl_prefer_server_ciphers on;
    
  2. ssl_protocols ディレクティブを使用して推奨プロトコルをホワイトリストに登録し、安全性に問題があることが確認されている SSLv2 を無効にします。

    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    
  3. 暗号スイートを定義します。ここで提供される暗号スイートは、弱体化した、または時代遅れの暗号化方式を無効にする、強力な最小限のスイートです。実際に使用するスイートは、個々のユースケースで決定される必要があります。

    ssl_ciphers   EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED;
    
  4. 次の add_header ディレクティブを追加して、厳格な転送セキュリティを有効にします。このヘッダーによって、ウェブブラウザに HTTPS のみを使用するように明確に指示します。

    add_header Strict-Transport-Security "max-age=31536000";
    
  5. ウェブサイトのパフォーマンスを改善するため、SSL セッション キャッシュも有効にできます。次のディレクティブは、15 MB の共有キャッシュを有効にし、キャッシュの有効期間を 10 分に設定します。

    ssl_session_cache shared:SSL:15m;
    ssl_session_timeout 10m;
    

設定を強化したら、次にこの設定をテストしてエラーの有無を確認し、次に NGINX サービスをリロードします。

service nginx configtest && service nginx reload

負荷分散方式の選択

NGINX 負荷分散のデフォルトは、トラフィックをルーティングするラウンドロビン方式です。この方式では、ラウンドロビンの順序指定を使用してトラフィックをバックエンドにルーティングします。新しいリクエストはそれぞれ別のサーバーに送信されます。さらに、NGINX は次の負荷分散方式を提供します。

  • 最小接続

    受信トラフィックは、最小数のアクティブ接続でターゲット サーバーに送信されます。

  • IP ハッシュ

    受信トラフィックは、クライアントの IP アドレスを入力として使用するハッシュ関数に従ってルーティングされます。この方式は、セッションの持続性を必要とするユースケースに特に有用です。

適切なディレクティブを仮想ホストの upstream ブロックに追加することによって、デフォルトのラウンドロビン方式を別の方式に置き換えることができます。最小接続方法を使用する場合は、次のように least_conn ディレクティブを追加します。

upstream {
  least_conn;
  server 1.2.3.4;
  …
}

IP ハッシュ方式を使用する場合は、次のように ip_hash ディレクティブを追加します。

upstream {
  ip_hash;
  server 1.2.3.4;
  …
}

サーバーの重み付け

サーバーの重みを設定することにより、特定のサーバーへの送信トラフィック量を増やすようにロードバランサを調整することができます。サーバーの重みを設定する場合、次のように weight 属性を upstream ディレクティブの特定の server に追加します。

upstream {
  server 1.2.3.4 weight=3
  server 2.3.4.5
  server 3.4.5.6 weight=2
}

デフォルトのラウンドロビン負荷分散方式でこの設定を使用した場合、リクエストを 6 回受信するごとに、3 回は 1.2.3.4 に、1 回は 2.3.4.5 に、2 回は 3.4.5.6 に送信されます。IP ハッシュ方式と最小接続方式は、重み付けもサポートしています。

ヘルスチェックの設定

NGINX はサーバーのヘルスチェックを自動的に実行します。デフォルトでは、サーバーが 10 秒以内に応答しなかった場合、NGINX はサーバーを失敗とマークします。max_fails パラメータと fail_timeout パラメータを使用して、個々のサーバのヘルスチェックをカスタマイズすることができます。

server 1.2.3.4 max_fails=2 fail_timeout=15s

サーバーの状態の設定

他のサーバーが利用できない場合に限り、特定のバックエンド サーバーを使用できるように設定したい場合は、次のように backup パラメータを upstream ディレクティブの server 定義を追加します。

server 1.2.3.4 backup

同様に、サーバーが無期限に利用できないままであることがわかっている場合は、down パラメータを設定して、サーバーを利用不能にマークすることができます。

server 1.2.3.4 down

クリーンアップ

NGINX ロードバランサ チュートリアルが終了したら、Google Cloud Platform で作成したリソースについて料金が発生しないようにクリーンアップすることができます。以下のセクションで、このようなリソースを削除または無効にする方法を説明します。

プロジェクトの削除

課金を停止する最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除する手順は次のとおりです。

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

インスタンスを削除する

Compute Engine インスタンスを削除する方法は次のとおりです。

  1. GCP Console の [VM インスタンス] ページに移動します。

    [VM インスタンス] ページに移動

  2. nginx-lbインスタンスの隣のチェックボックスをオンにします。
  3. ページの上部にある、[削除] ボタンをクリックし、インスタンスを削除します。

ディスクを削除する

Compute Engine ディスクを削除する方法は次のとおりです。

  1. GCP Console で [ディスク] ページに移動します。

    [ディスク] ページに移動

  2. 削除したいディスクの隣にあるチェックボックスをオンにします。
  3. ページの上部にある [削除] ボタンをクリックし、ディスクを削除します。

次のステップ

他の使用可能な負荷分散ソリューションの確認

Google Cloud Platform で使用可能な他の負荷分散ソリューションについては以下をご覧ください。

ロードバランサ復旧方式の実装

NGINX ベースのロードバランサは、単一の障害発生点であるため、これが失敗した場合に迅速に復旧する方法を実装しておく必要があります。災害復旧クックブックアプリケーションの復旧でいくつかの方法を紹介しています。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Compute Engine ドキュメント