Flaskとロードバランサー(ALB/ELB)を連携!アクセス集中に強いアプリ作り
生徒
「Flaskで作ったアプリに、もし一度に何万人もアクセスが来たらどうなりますか?」
先生
「一つのサーバーだけではパンクして動かなくなってしまいます。そんな時は『ロードバランサー』という司令塔を使って、仕事を複数のサーバーに振り分けるんですよ。」
生徒
「司令塔ですか!AWSのALBやELBという名前を聞いたことがありますが、Flaskアプリ側でも何か特別な設定が必要なんですか?」
先生
「はい、正しいアクセス元の情報を読み取るための設定が必要です。一緒に手順を確認していきましょう!」
1. ロードバランサー(ALB/ELB)とは何かを学ぼう
プログラミング未経験の方にとって、ロードバランサーという言葉は聞き慣れないかもしれません。これは日本語で「負荷分散装置(ふかぶんさんそうち)」と言います。もっと簡単に例えると、行列ができる超人気レストランの「受付担当の店員さん」です。
お客さん(インターネットからのアクセス)が次々とやってきたとき、一人の料理人(サーバー)だけでは対応が追いつきません。そこで受付担当の店員さん(ロードバランサー)が、「あなたは1番テーブルの料理人へ」「あなたは2番テーブルの料理人へ」と、空いているサーバーへ順番に案内していきます。これにより、お店全体として大量の注文をさばけるようになるのです。
クラウドサービスのAWS(アマゾン・ウェブ・サービス)では、この受付担当を「ELB(エラスティック・ロード・バランシング)」と呼び、その中でもWebアプリに特化したものを「ALB(アプリケーション・ロード・バランサー)」と呼びます。
2. ロードバランサーを使うと起きる「情報の書き換え」問題
便利なロードバランサーですが、Flaskアプリと連携させるときに一つ困ったことが起きます。それは「本当のアクセス元が誰か分からなくなる」という問題です。
通常、Flaskアプリは「誰がアクセスしてきたか(IPアドレス)」を確認できます。しかし、ロードバランサーを間に挟むと、アプリ側からは「すべてのアクセスがロードバランサーからのもの」に見えてしまいます。これは、店員さんが注文を伝達するときに、お客さんの顔ではなく「店員さんの声」しか聞こえない状態に似ています。
これでは、特定の地域からのアクセスを制限したり、ログに正しい情報を残したりすることができません。この問題を解決するために、ロードバランサーは「本当のお客さんの情報はこれだよ!」というメモ(ヘッダー情報)を付けてアプリに送ってくれます。Flask側では、このメモを正しく読み取る設定が必要になります。
3. ヘルスチェック用の道を作っておこう
ロードバランサーは、裏側にいるサーバーが元気に動いているか定期的に確認しています。これを「ヘルスチェック(健康診断)」と呼びます。もし、あるサーバーが故障して返事をしなくなったら、ロードバランサーはそのサーバーへの案内を自動で停止します。
Flaskアプリ側では、この健康診断に答えるための専用の窓口を作っておく必要があります。以下のコードは、最もシンプルな健康診断用の設定です。
from flask import Flask
app = Flask(__name__)
# 健康診断(ヘルスチェック)用の窓口
@app.route('/health')
def health_check():
# ロードバランサーに対して「元気ですよ!」と返事をします
return 'OK', 200
@app.route('/')
def index():
return 'こんにちは!ロードバランサー経由で表示されています。'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
ロードバランサーの設定画面で、この「/health」という場所をチェックするように指定します。これにより、アプリが正常に動いている間だけ、お客さんのアクセスが届くようになります。
4. 本当のアクセス元を知るためのProxyFix設定
先ほどお話しした「本当のお客さんの情報を読み取る」ための設定を、Pythonのコードで書いてみましょう。これには、Flaskと一緒に使われる「Werkzeug(ヴェルクツォイク)」という道具箱の中にある「ProxyFix(プロキシ・フィックス)」という機能を使います。
from flask import Flask, request
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
# ロードバランサー(プロキシ)からの情報を正しく受け取る設定
# x_for=1 は、ロードバランサーが1台存在することを意味します
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
@app.route('/info')
def show_info():
# ProxyFixを設定することで、本当のIPアドレスが取得できます
user_ip = request.remote_addr
return f"あなたの本当のIPアドレスは {user_ip} ですね!"
if __name__ == '__main__':
app.run()
この「ProxyFix」という魔法の言葉を一行入れるだけで、Flaskは「あ、これは店員さん(ロードバランサー)が教えてくれた本当のお客さんの情報だ!」と判断できるようになります。セキュリティ対策やアクセス分析には欠かせない設定です。
5. HTTPS(暗号化)通信との連携に注意
最近のWebサイトは、URLが「https://」で始まる暗号化された通信が当たり前です。ロードバランサーを使う場合、暗号化の解除(重たい計算処理)をロードバランサー側で肩代わりしてもらうのが一般的です。
すると、ロードバランサーから先のFlaskアプリまでは、普通の通信(http)でデータが届くことがあります。このとき、Flaskアプリが「あ、今は暗号化されていない通信だな」と勘違いしてしまうと、セキュリティ上の警告が出たり、一部の機能が動かなくなったりします。先ほどの「ProxyFix」の「x_proto=1」という設定は、この「本当はhttpsでアクセスされていたんだよ」という情報を正しく伝える役割も持っています。
6. 複数のサーバーで「ログイン状態」を共有する方法
ロードバランサーでサーバーを複数に増やしたとき、もう一つ注意点があります。それは「ログイン状態の共有」です。1番のサーバーでログインしたのに、次のアクセスで2番のサーバーに案内されたとき、「あなたは誰?」と言われてしまったら困りますよね。
これを解決するには、サーバーの中に情報を保存するのではなく、外部の「Redis(レディス)」などの共通の倉庫を使うか、あるいはロードバランサー側の「スティッキーセッション」という機能を使います。これは、一度案内したお客さんは、しばらく同じ料理人が担当するように固定する仕組みです。初心者の方は、まずはこの「固定する機能」があることを覚えておきましょう。
7. セキュリティを高めるための信頼設定
ProxyFixは非常に便利ですが、注意点もあります。もし、悪い人がロードバランサーのふりをして偽の情報を送ってきたら、Flaskアプリは騙されてしまいます。そのため、「このロードバランサーからの情報だけを信じる」という設定をすることが推奨されます。
以下のコードは、より安全に、特定の情報の数だけを信頼するように指定する例です。プログラミングに慣れてきたら、このような細かい数値の調整も必要になってきます。
import os
from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
# 環境に合わせて信頼するプロキシの数を調整
# 例えば、クラウドの構成によって数値が変わります
trusted_proxies_count = int(os.environ.get('TRUSTED_PROXIES', 1))
app.wsgi_app = ProxyFix(
app.wsgi_app,
x_for=trusted_proxies_count,
x_proto=trusted_proxies_count
)
@app.route('/secure')
def secure_page():
return "信頼された通信経路でアクセスされています。"
8. ロードバランサー導入後のテスト方法
設定が終わったら、本当に正しく動いているかテストしましょう。まずは健康診断用の「/health」にアクセスして「OK」が出るかを確認します。次に、クラウドの管理画面で、わざとアプリを停止させてみて、ロードバランサーがそのサーバーを切り離すかを確認します。
パソコンを触ったことがない方にとって、サーバーを止めるのは勇気がいるかもしれませんが、クラウドならボタン一つでやり直せます。「失敗しても大丈夫」という気持ちで、いろいろな設定を試してみることが、エンジニアとしてのスキルアップに繋がります。
9. クラウド連携でスケールするアプリを目指そう
ロードバランサーとFlaskの連携ができるようになると、あなたのアプリは世界中の何百万人ものユーザーに対応できる可能性を手に入れます。一つ一つの設定は地味に見えるかもしれませんが、これらはすべて「壊れにくい、強いアプリ」を作るための大切な基礎です。
クラウドの世界には、他にも自動でサーバーの数を増減させる「オートスケーリング」など、ワクワクするような機能がたくさんあります。まずは今回のロードバランサー連携をマスターして、大規模なWebサービスへの第一歩を踏み出しましょう!応援しています。