← ハンズオン一覧に戻る

AWS Hands-on / Networking

振り分ける仕組みを、自分の手で組み立てる

マネージドサービスのロードバランサーを使わず、ふつうの EC2 インスタンスに nginx を入れて、自分の手で「振り分ける仕組み」を組み立てます。複数のサーバーへのアクセスをまとめて受け止め、順番に振り分け、調子の悪いサーバーを自動的に避ける——ロードバランサーが裏側でやっていることを、設定ファイルを書いて体感します。

● Lv.3 複数のサービスを組み合わせられる人 ⏱ 所要 50〜70 分 コンソール操作 + ローカルの PowerShell から SSH
01 — Prerequisites

はじめる前に

  • 必須AWS アカウントを持っていること
  • 必須マネジメントコンソールにサインインできること
  • 必須EC2 インスタンスを複数台起動した経験があること
  • 必須セキュリティグループの設定経験があること
  • 必須SSH で EC2 にログインした経験があること
  • あると良いWeb サーバーの設定ファイルを編集した経験

ローカルの PowerShell から Windows 標準の OpenSSH を使って、3 台の EC2 にそれぞれ SSH 接続します。

02 — References

参照する公式ドキュメント

手順に迷ったときや、用語の意味を確かめたいときに開きましょう。

※ リンク切れの場合は、ページタイトルで検索してください。

03 — Background

背景・シナリオ

1 台のサーバーだけでアクセスを受け止めていると、そのサーバーが処理しきれなくなったり、壊れたりしたときにサービスが止まってしまいます。マネージドサービスのロードバランサーを使えば、複数のサーバーへのアクセスの振り分けや、調子の悪いサーバーを自動的に避ける仕組みを AWS が代わりに用意してくれます。今回はその裏側にある考え方を理解するため、ふつうの EC2 に Web サーバーソフト「nginx」を入れ、自分の手で「振り分ける役(リバースプロキシ)」を組み立てます。

「リバースプロキシ」って何?

利用者からのアクセスをいったん受け止め、その裏にある別のサーバー(今回はバックエンドの 2 台のサーバー)へ転送する仕組みです。利用者からは 1 つの窓口(プロキシ)にアクセスしているように見えますが、実際の処理は背後の複数のサーバーが分担します。

「調子の悪いサーバーを自動的に避ける」とは、具体的にどういう動き?

nginx の設定で、一定回数連続して応答が失敗したサーバーを、しばらくの間振り分け先から外す、という挙動を設定できます。今回作る設定もこの挙動を持たせます。ただし、これは「実際にアクセスが失敗したとき」に初めて気づく仕組みです。マネージドサービスのロードバランサーは、アクセスがなくても定期的に様子を見に行く「ヘルスチェック」を行っており、この点で挙動が異なります。

Goal

2 台のバックエンド EC2(Web サーバー、それぞれ自分のホスト名を表示する簡単なページ)と、1 台のプロキシ用 EC2(nginx でリバースプロキシを構成)を作る。プロキシのパブリック IP にアクセスして、表示されるホスト名が 2 台の間で切り替わることを確認し、片方のバックエンドを止めても自動的に避けられることを確認する。

04 — Architecture

つくる構成

中央のプロキシ用 EC2 が利用者からのアクセスを受け止め、背後の 2 台のバックエンド EC2 へ順番に振り分けます(ラウンドロビン)。

利用者のアクセス
ブラウザから
プロキシの 1 か所へ
プロキシ EC2(nginx)
受付役。振り分けの
設定ファイルを自分で書く
バックエンド EC2:web-1
httpd でホスト名を
表示するページ
バックエンド EC2:web-2
httpd でホスト名を
表示するページ
マネージドサービスのロードバランサーが代わりにやってくれていることを、今回は設定ファイルとして自分で書きます。
プロキシは設定済みの台数だけを把握しており、応答に失敗し続けたバックエンドを一時的に振り分け先から外します。
05 — Requirements

要件

以下の要件を満たす構成を作り、ブラウザで振り分けと自動切り離しを確認してください。

No要件
1リージョンは「東京(ap-northeast-1)」を使用する。
2バックエンド用 EC2 を 2 台起動する(Amazon Linux 2023、無料利用枠タイプ、名前タグ自由・例:web-1web-2)。それぞれに httpd を導入し、自分のホスト名を表示する簡単なページを置く。
3バックエンド用セキュリティグループで、HTTP(80)をプロキシ用セキュリティグループからのみ許可する。
4プロキシ用 EC2 を 1 台起動する(Amazon Linux 2023)。セキュリティグループで HTTP(80)をインターネットから許可し、SSH をマイ IP から許可する。
5プロキシ EC2 に nginx を導入し、2 台のバックエンドのプライベート IP アドレスへ振り分ける設定(upstream ブロック、max_failsfail_timeout 付き)を行う。
6プロキシ EC2 のパブリック IP にブラウザでアクセスし、表示されるホスト名が 2 台のバックエンドの間で切り替わることを確認する。片方のバックエンドの httpd を停止し、しばらくアクセスを続けるとそちらが振り分け先から外れることを確認する。
06 — Steps

構築の進め方

「セキュリティグループ → バックエンド 2 台 → プロキキシ用 EC2 → nginx の設定 → 動作確認」の順に組み立てます。

  1. マネジメントコンソールにサインインし、リージョンを東京に合わせる

    ブラウザで AWS マネジメントコンソールにサインインし、画面右上のリージョンが「アジアパシフィック(東京)ap-northeast-1」になっていることを確認します。

  2. セキュリティグループを 2 つ作成する

    EC2 コンソールの「セキュリティグループ」から、次の 2 つを作成します。先にプロキシ用セキュリティグループを空の状態で作っておき、あとからバックエンド用のルールで参照すると迷いません。

    プロキシ用セキュリティグループインバウンド:HTTP(80)を 0.0.0.0/0(インターネット)から許可、SSH(22)を「マイ IP」から許可
    バックエンド用セキュリティグループインバウンド:HTTP(80)をソースにプロキシ用セキュリティグループを指定して許可(SSH も必要であれば「マイ IP」から許可しておくと、後片づけ時のログイン確認に使えます)
    なぜプロキシ経由だけに絞るのか

    バックエンドへの直接アクセスを閉じておくことで、利用者が必ずプロキシを通る経路にそろいます。振り分けや自動切り離しが効くのも、この経路が 1 本にそろっているからです。

  3. バックエンド用 EC2 を 2 台起動する

    EC2 コンソールで「インスタンスを起動」を 2 回行い、Amazon Linux 2023・無料利用枠タイプで、名前タグを自由に決めて(例:web-1web-2)起動します。セキュリティグループは手順 2 のバックエンド用を選びます。「高度な詳細」→「ユーザーデータ」に次の内容を貼り付けます。

    ユーザーデータ(web-1・web-2 共通)
    #!/bin/bash
    dnf install -y httpd
    echo "<h1>Hello from $(hostname)</h1>" > /var/www/html/index.html
    systemctl enable httpd
    systemctl start httpd

    1 行ずつ確認しましょう。

    dnf install -y httpdAmazon Linux 2023 のパッケージ管理コマンド dnf で、Web サーバーソフトの httpd(Apache)を確認なしで導入します。
    echo "..." > /var/www/html/index.htmlその時点のホスト名($(hostname))を埋め込んだ簡単なページを、Web サーバーの公開フォルダに作成します。これにより、どちらのサーバーが応答したか見分けられます。
    systemctl enable httpdインスタンスを再起動しても httpd が自動的に立ち上がるよう設定します。
    systemctl start httpdhttpd を今すぐ起動します。
    プライベート IP アドレスを控えておく

    起動後、各インスタンスの詳細画面でプライベート IP アドレスを確認し、メモしておきましょう。あとで nginx の設定に使います。

  4. プロキシ用 EC2 を 1 台起動する

    同じように「インスタンスを起動」から、Amazon Linux 2023・無料利用枠タイプで 1 台起動します。セキュリティグループは手順 2 のプロキシ用を選びます。パブリック IP の自動割り当てを有効にしておきます。

  5. プロキシ EC2 に SSH でログインし、nginx を導入する

    ローカルの PowerShell から、Windows 標準の OpenSSH を使ってプロキシ EC2 に接続します。

    PowerShell
    PS> ssh -i "C:\Users\you\Downloads\your-key.pem" ec2-user@<プロキシEC2のパブリックIP>

    ログインできたら、nginx を導入します。

    プロキシEC2内(SSH接続後)
    $ sudo dnf install -y nginx
    秘密鍵ファイルのアクセス権限

    Windows 標準の OpenSSH では、.pem ファイルのアクセス権限が緩すぎると接続を拒否されることがあります。エラーが出た場合は、鍵ファイルのプロパティから自分以外のアクセス権を外してみましょう。

  6. nginx の設定ファイルを作成する

    プロキシ EC2 内で、設定ファイル(例:/etc/nginx/conf.d/proxy.conf)を作成します。手順 3 で控えた 2 台のプライベート IP アドレスを使います。

    /etc/nginx/conf.d/proxy.conf
    upstream backend_pool {
        server <web-1のプライベートIP>:80 max_fails=2 fail_timeout=10s;
        server <web-2のプライベートIP>:80 max_fails=2 fail_timeout=10s;
    }
    
    server {
        listen 80;
        location / {
            proxy_pass http://backend_pool;
            proxy_next_upstream error timeout http_502 http_503 http_504;
        }
    }

    1 行ずつ確認しましょう。

    upstream backend_pool { ... }振り分け先のグループに backend_pool という名前を付けて定義します。
    server <IP>:80 max_fails=2 fail_timeout=10s;振り分け先のサーバーを 1 台ずつ記載します。max_fails=2 は「連続 2 回失敗したら」、fail_timeout=10s は「10 秒間は振り分け先から外す」という意味です。値は自由に決められますが、悩む場合はこの例の値から始めるとよいでしょう。
    listen 80;プロキシ自身が HTTP(80 番ポート)でアクセスを受け付けることを示します。
    proxy_pass http://backend_pool;受け付けたアクセスを、先ほど定義した backend_pool へ転送します。ここで台数や振り分け方式を意識せず書けるのが upstream の利点です。
    proxy_next_upstream error timeout http_502 http_503 http_504;転送先からエラーやタイムアウトが返ってきた場合に、別の振り分け先へ自動的に再試行する条件を指定します。
    IP アドレスは自由に決まる値です

    プライベート IP アドレスは、自分の VPC・サブネットの設定によって変わります。手順 3 で確認した値をそのまま使ってください。

  7. 構文チェックをして、nginx を起動する

    設定ファイルを保存したら、構文に誤りがないか確認します。

    プロキシEC2内(SSH接続後)
    $ sudo nginx -t
    # syntax is ok / test is successful と表示されれば問題ありません
    $ sudo systemctl enable nginx
    $ sudo systemctl start nginx
    # 既に起動している場合は次で設定を反映します
    $ sudo systemctl reload nginx
  8. 動作確認をする

    プロキシ EC2 のパブリック IP アドレスにブラウザでアクセスし(http://<プロキシEC2のパブリックIP>)、ホスト名が表示されることを確認します。再読み込みを繰り返して、表示が web-1web-2 の間で切り替わることを確認しましょう。

    続けて、片方のバックエンドに SSH でログインし、httpd を停止します。

    バックエンドEC2内(SSH接続後)
    $ sudo systemctl stop httpd

    その後、プロキシのパブリック IP に何度かアクセスを繰り返し、停止したサーバーが振り分け先から外れていく様子を観察しましょう。

    外れるまで少しアクセスが必要

    max_fails=2 の設定では、停止後すぐにではなく、2 回失敗した時点で振り分け先から外れます。最初の数回は失敗(つながらない、もしくは遅い)応答が混ざることがあります。

07 — Pitfalls

つまずきポイント

初学者がよく引っかかる箇所を先回りでまとめました。答えそのものは載せていませんが、「どこを見直せばよいか」の手がかりとして使ってください。

Pitfall 01 — プロキシからバックエンドにアクセスできない

「ブラウザでプロキシにアクセスしても、ページが表示されない・502 エラーになる」

①バックエンド用セキュリティグループが、プロキシ用セキュリティグループからの HTTP(80)を許可しているかupstream に書いた IP アドレスが、プライベート IP ではなくパブリック IP になっていないかを順に見直してみましょう。プロキシとバックエンドは同じ VPC 内の通信なので、パブリック IP は使いません。

Pitfall 02 — 設定ファイルを編集したのに反映されない

「ホスト名の表示や振り分けの挙動が、変更前と変わらない」

nginx -s reload または systemctl reload nginx を忘れていないか確認しましょう。また、設定ファイルに構文エラーがある場合、反映自体が失敗しています。sudo nginx -t を実行し、エラーが出ていないかをまず確認してください。

08 — Checklist

完了チェック

要件の再確認ではなく、画面のどこを見れば達成を確認できるかをまとめました。ブラウザと SSH 接続先のターミナルで、次を順に確かめましょう。

  • プロキシのパブリック IP にブラウザでアクセスすると、ホスト名を表示するページが表示される。
  • 複数回アクセス(再読み込み)すると、表示されるホスト名が web-1web-2 の間で切り替わる。
  • プロキシ EC2 内で sudo nginx -t を実行してもエラーが出ない。
  • 片方のバックエンドで httpd を停止すると、数回の失敗のあと、そちらのホスト名が表示されなくなる(振り分け先から外れる)。
  • 停止した httpd を再開すると、しばらくしてそのホスト名が再び表示されるようになる(振り分け先に戻る)。
09 — Think

考えてみよう

手を動かすことに加えて、次の問いに自分の言葉で答えられるようにしておくと、理解がより深まります。

  1. 実際のロードバランサーは、リクエストが来なくてもバックエンドの状態を定期的に確認しに行きます(アクティブヘルスチェック)。今回の nginx の設定は、リクエストが失敗したときに初めて気づく仕組みでした。この違いは、どんな場面で問題になりそうでしょうか。
    ヒント
    「リクエストが来てから気づく」方式では、最初にそのサーバーへ振り分けられた利用者が、必ず一度は失敗した応答を受け取ってしまいます。アクセスの頻度が低い時間帯や、サーバーが落ちた直後にアクセスが集中する場面を想像してみましょう。
  2. プロキシ自体(このEC2)が落ちたら、システム全体はどうなるでしょうか。
    ヒント
    バックエンドが 2 台とも正常でも、その手前にいる窓口が 1 つしかなければ、その窓口が止まった時点で利用者は誰もアクセスできなくなります。「振り分ける役」自体を複数台にする、または冗長化する方法がないか考えてみましょう。
  3. バックエンドを 3 台、4 台と増やしたら、設定ファイルのどこを変更する必要がありそうでしょうか。
    ヒント
    upstream backend_pool { ... } の中に並んでいる server 行を見てみましょう。台数が増えるたびに、この設定ファイルを自分で編集して反映し直す必要がある、という点が今回の方式の特徴です。
10 — Clean up

後片づけ

3 台の EC2 とセキュリティグループを、依存関係につまずかない順番で削除します。

  1. プロキシ用 EC2 を削除する:EC2 コンソールの「インスタンス」でプロキシ用のインスタンスを選び、「インスタンスを終了(Terminate)」を実行します。
  2. バックエンド用 EC2 を 2 台削除する:同様に web-1web-2 を選び、「インスタンスを終了(Terminate)」を実行します。
  3. セキュリティグループを削除する:今回作成したプロキシ用・バックエンド用の 2 つのセキュリティグループを、インスタンスを終了したあとに削除します。
Caution — 他で使っているリソースを間違えて消さない

削除するのは、このハンズオンで自分が作ったものだけ

セキュリティグループやインスタンスの一覧には、他のハンズオンや検証で使っているリソースが並んでいることもあります。名前タグをよく確認し、このハンズオンのために作ったものだけを選んで削除してください。デフォルト VPC やデフォルトのセキュリティグループは消さないようにしましょう。

コストに関する注意: 今回作成するのは通常のEC2 インスタンス 3 台のみで、それぞれインスタンスタイプに応じた時間課金が発生します。マネージドサービスのロードバランサーのような時間課金や、処理量に応じた課金(LCU)は発生しません。各インスタンスに付くディスク(EBS ボリューム)や、割り当てられるパブリック IPv4 アドレスにも料金がかかる場合があります。セキュリティグループ自体には料金はかかりません。検証が終わったら、上の「後片づけ」に沿って 3 台とも削除してください。最新の料金は AWS の公式料金ページで確認してください。