Ubuntu20.04でmod proxyを使用してApacheをリバースプロキシとして使用する方法
序章
リバースプロキシは、HTTP(S)リクエストを受け取り、それらを1つ以上のバックエンドサーバーに透過的に配信するタイプのプロキシサーバーです。 最近の多くのWebアプリケーションは、バックエンドアプリケーションサーバーを使用して着信HTTP要求を処理するため、リバースプロキシは便利です。 これらのサーバーは、ユーザーが直接アクセスすることを意図したものではなく、多くの場合、基本的なHTTP機能のみをサポートします。
リバースプロキシを使用して、これらの基盤となるアプリケーションサーバーに直接アクセスされないようにすることができます。 また、着信要求からの負荷を複数の異なるアプリケーションサーバーに分散して、大規模なパフォーマンスを向上させ、フェイルセーフを提供するためにも使用できます。 キャッシュ、圧縮、SSL暗号化など、アプリケーションサーバーが提供しない機能でギャップを埋めることができます。
このチュートリアルでは、mod_proxy
拡張機能を使用してApacheを基本的なリバースプロキシとして設定し、同じネットワーク上で実行されている1つまたは複数のバックエンドサーバーに着信接続をリダイレクトします。 このチュートリアルでは、 Flask Webフレームワークで記述されたバックエンドを使用しますが、任意のバックエンドサーバーを使用できます。
前提条件
このチュートリアルに従うには、次のものが必要です。
- この初期サーバーセットアップチュートリアルでセットアップされた1つのUbuntu20.04サーバー。これには、
sudo
非rootユーザーとファイアウォールが含まれます。 - [X43X] Ubuntu 20.04にApacheWebサーバーをインストールする方法のステップ1および2に従って、サーバーにApache2をインストールします。
ステップ1—必要なApacheモジュールを有効にする
Apacheには多くのモジュールがバンドルされており、これらは使用可能ですが、新規インストールでは有効になりません。 まず、このチュートリアルで使用するものを有効にする必要があります。
必要なモジュールは、mod_proxy
自体と、さまざまなネットワークプロトコルをサポートするように機能を拡張するアドオンモジュールのいくつかです。 具体的には、以下を使用します。
mod_proxy
:接続をリダイレクトするためのメインプロキシモジュール。 これにより、Apacheが基盤となるアプリケーションサーバーへのゲートウェイとして機能できるようになります。mod_proxy_http
:HTTP接続のプロキシのサポートを追加します。mod_proxy_balancer
およびmod_lbmethod_byrequests
:これらは複数のバックエンドサーバーの負荷分散機能を追加します。
これらの4つのモジュールを有効にするには、次のコマンドを実行します。
sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests
これらの変更を有効にするには、Apacheを再起動します。
sudo systemctl restart apache2
これで、ApacheはHTTPリクエストのリバースプロキシとして機能する準備が整いました。 次のオプションの手順では、2つの基本的なバックエンドサーバーを作成します。 これらは、構成が正しく機能するかどうかを確認するのに役立ちますが、独自のバックエンドアプリケーションが既にある場合は、ステップ3にスキップできます。
ステップ2—バックエンドテストサーバーの作成(推奨)
一部のバックエンドサーバーを実行すると、Apache構成が正しく機能しているかどうかをテストするのに役立ちます。 ここでは、1行のテキストを出力してHTTPリクエストに応答する2つのテストサーバーを作成します。 一方のサーバーはHelloworld!と表示し、もう一方のサーバーは Howdy world!と表示します。これにより、複数のサービス間の負荷分散をテストできます。
注:実際のセットアップでは、バックエンドサーバーは通常、すべて同じ種類のコンテンツを返します。 ただし、このテストでは、2つのサーバーが異なるメッセージを返すようにすることで、負荷分散メカニズムが両方を使用していることを確認できます。
Flask は、Webアプリケーションを構築するためのPythonマイクロフレームワークです。 このステップでは、最小限のアプリケーションで数行のコードしか必要としないため、Flaskを使用してテストサーバーを作成する方法の概要を説明します。 これらを設定するためにPythonを知っている必要はありませんが、学びたい場合は、Pythonでコーディングする方法のシリーズをチェックしてください。
まず、apt
を使用してパッケージインデックスリストを更新します。
sudo apt update
次に、推奨されるPythonパッケージマネージャーであるpip
をインストールします。
sudo apt install python3-pip
次に、pip
を使用してFlaskをインストールします。
sudo pip3 install Flask
必要なすべてのコンポーネントがインストールされたので、現在のユーザーのホームディレクトリにある最初のバックエンドサーバーのコードを含む新しいファイルを作成します。 お好みのテキストエディタでこれを行うことができます。ここではnano
を使用します。
nano ~/backend1.py
次のコードスニペットをファイルに挿入します。
〜/ backend1.py
from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Hello world!'
コードの最初の2行は、Flaskフレームワークを初期化します。 1行のテキスト(Hello world!
)を返すhome()
という1つの関数があります。 home()
関数定義の上の@app.route('/')
行は、/
ルートに向けられたHTTPリクエストへの応答としてhome()
'の戻り値を使用するようにFlaskに指示しますアプリケーションのURL。
完了したら、ファイルを保存して終了します。 nano
を使用している場合は、CTRL + X
、Y
、ENTER
の順に押すとこれを行うことができます。
2番目のバックエンドサーバーは、異なる行のテキストを返すことを除けば、最初のサーバーとまったく同じです。 したがって、cp
を実行して、最初のファイルbackend1.py
からbackend2.py
ファイルにコンテンツをコピーします。
cp ~/backend1.py ~/backend2.py
次に、お好みのテキストエディタを使用して、新しくコピーしたファイルを開きます。
nano ~/backend2.py
Hello world!メッセージを返すメッセージを更新して、代わりに Howdy world!を読み取ります。
〜/ backend2.py
from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Howdy world!'
更新が完了したら、ファイルを保存して閉じます。
次に、次のコマンドを使用して、ポート8080
で最初のバックグラウンドサーバーを起動します。 これにより、Flaskの出力が/dev/null
にリダイレクトされます。これは、コンソール出力がさらに曇ってしまうためです。
FLASK_APP=~/backend1.py flask run --port=8080 >/dev/null 2>&1 &
ここでは、flask
コマンドの前に、同じ行にFLASK_APP
環境変数を設定しています。 環境変数は、シェルから生成されたプロセスに情報を渡すための便利な方法です。 環境変数の詳細については、LinuxVPSで環境変数とシェル変数を読み取って設定する方法のガイドを参照してください。
この場合、環境変数を使用すると、設定が実行中のコマンドにのみ適用され、その後は使用できなくなります。 これは、flask
コマンドに2番目のサーバーを起動するように指示するのと同じ方法で別のファイル名を渡すため、混乱を避けるために必要です。
同様に、次のコマンドを実行して、ポート8081
で2番目のサーバーを起動します。 FLASK_APP
環境変数の値が異なることに注意してください。
FLASK_APP=~/backend2.py flask run --port=8081 >/dev/null 2>&1 &
これで、curl
コマンドを使用して、2つのサーバーが実行されているかどうかをテストできます。 最初のサーバーをテストすることから始めます。 このコマンドは、curl
を使用して、localhostを表す特別なIPアドレスである127.0.0.1
に接続します。 これは、次のコマンドがサーバーに接続して独自の応答を出力するように指示することを意味します。
curl http://127.0.0.1:8080/
これにより、サーバーから次の応答が出力されます。
OutputHello world!
次に、2番目のサーバーをテストします。
curl http://127.0.0.1:8081/
以前と同様に、これによりサーバーからの期待される応答が出力されます。
OutputHowdy world!
次のステップでは、Apacheの構成ファイルを変更して、リバースプロキシとして使用できるようにします。
ステップ3—リバースプロキシを有効にするためにデフォルト構成を変更する
このセクションでは、単一のバックエンドサーバーまたは負荷分散されたバックエンドサーバーのアレイのリバースプロキシとして機能するように、デフォルトのApache仮想ホストを設定します。
注:このチュートリアルでは、仮想ホストレベルで構成を適用しています。 Apacheのデフォルトのインストールでは、有効になっているデフォルトの仮想ホストは1つだけです。 ただし、これらすべての構成フラグメントを他の仮想ホストでも使用できます。 Apacheの仮想ホストの詳細については、 Ubuntu20.04でApache仮想ホストを設定する方法のチュートリアルを参照してください。
ApacheサーバーがHTTPサーバーとHTTPSサーバーの両方として機能する場合は、リバースプロキシ構成をHTTP仮想ホストとHTTPS仮想ホストの両方に配置する必要があります。 Apacheを使用したSSLの詳細については、 Ubuntu20.04チュートリアルでApacheの自己署名SSL証明書を作成する方法に関するチュートリアルを参照してください。
お好みのテキストエディタを使用して、デフォルトのApache設定ファイルを開きます。
sudo nano /etc/apache2/sites-available/000-default.conf
そのファイル内には、最初の行から始まる<VirtualHost *:80>
ブロックがあります。 次の最初の例では、単一のバックエンドサーバーのリバースプロキシにこのブロックを構成する方法を説明し、2番目の例では、複数のバックエンドサーバーの負荷分散されたリバースプロキシを設定します。
例1—単一のバックエンドサーバーのリバースプロキシ
まず、VirtualHost
ブロック内のすべての内容を置き換えて、構成ファイルが次のようになるようにします。 ステップ2のサンプルサーバーを実行した場合は、127.0.0.1:8080
を使用してください。 独自のアプリケーションサーバーがある場合は、代わりにそれらのアドレスを使用してください。
/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80> ProxyPreserveHost On ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ </VirtualHost>
表示されるディレクティブは3つあり、それらが実行していることの概要は次のとおりです。
ProxyPreserveHost
:Apacheが元のHost
ヘッダーをバックエンドサーバーに渡すようにします。 これは、バックエンドサーバーにアプリケーションへのアクセスに使用されるアドレスを認識させるので便利です。ProxyPass
:メインプロキシ構成ディレクティブ。 この場合、ルートURL(/
)の下にあるすべてのものを、指定されたアドレスのバックエンドサーバーにマップする必要があることを指定します。 たとえば、Apacheが/example
の要求を受け取ると、http://your_backend_server/example
に接続し、元のクライアントに応答を返します。ProxyPassReverse
:ProxyPass
と同じ構成にする必要があります。 バックエンドサーバーからの応答ヘッダーを変更するようにApacheに指示します。 これにより、バックエンドサーバーがロケーションリダイレクトヘッダーを返す場合、クライアントのブラウザはバックエンドサーバーアドレスではなくプロキシアドレスにリダイレクトされ、意図したとおりに機能しなくなります。
このコンテンツの追加が完了したら、ファイルを保存して終了します。
これらの変更を有効にするには、Apacheを再起動します。
sudo systemctl restart apache2
これで、Webブラウザでhttp://your_server_ip
にアクセスすると、標準のApacheウェルカムページではなく、バックエンドサーバーの応答が表示されます。 ステップ2に従った場合、これは、ブラウザーに Hello world!が表示されることを意味します。
例2—複数のバックエンドサーバー間での負荷分散
複数のバックエンドサーバーがある場合、プロキシ時にトラフィックをサーバー間で分散する良い方法は、mod_proxy
の負荷分散機能を使用することです。
まず、お好みのテキストエディタを使用してデフォルトのApache設定ファイルを開きます。
sudo nano /etc/apache2/sites-available/000-default.conf
次に、VirtualHost
内のすべてのコンテンツを置き換えて、構成ファイルが次のようになるようにします。 ステップ2のサンプルサーバーに従った場合は、BalancerMember
ディレクティブに127.0.0.1:8080
および127.0.0.1:8081
を使用します。 独自のアプリケーションサーバーがある場合は、代わりにそれらのアドレスを使用してください。
/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80> <Proxy balancer://mycluster> BalancerMember http://127.0.0.1:8080 BalancerMember http://127.0.0.1:8081 </Proxy> ProxyPreserveHost On ProxyPass / balancer://mycluster/ ProxyPassReverse / balancer://mycluster/ </VirtualHost>
構成は前の構成と似ていますが、単一のバックエンドサーバーを直接指定する代わりに、これらのディレクティブは次のことを実行します。
Proxy
:この追加のProxy
ブロックは、複数のサーバーを定義するために使用されます。 ブロックの名前はbalancer://mycluster
(名前は自由に変更できます)で、基になるバックエンドサーバーアドレスを指定する1つ以上のBalancerMember
で構成されます。- 特定のサーバーの代わりに、
ProxyPass
およびProxyPassReverse: these directives use the load balancer pool named
mycluster`。
ステップ2のサンプルサーバーに従った場合は、上記のブロックに記述されているように、BalancerMember
ディレクティブに127.0.0.1:8080
および127.0.0.1:8081
を使用します。 独自のアプリケーションサーバーがある場合は、代わりにそれらのアドレスを使用してください。
このコンテンツの追加が完了したら、ファイルを保存して終了します。
これらの変更を有効にするには、Apacheを再起動します。
sudo systemctl restart apache2
Webブラウザでhttp://your_server_ip
にアクセスすると、標準のApacheページではなく、バックエンドサーバーの応答が表示されます。 ステップ2を実行した場合、ページを複数回更新すると、 Hello world!と Howdy world!が表示されます。これは、リバースプロキシが機能し、サーバー間の負荷分散が行われていることを意味します。両方のサーバー。
注:このチュートリアルを終了するときのように、両方のテストサーバーが不要になった後で閉じるには、killall flask
コマンドを実行できます。
結論
これで、1つまたは複数の基盤となるアプリケーションサーバーへのリバースプロキシとしてApacheを設定する方法がわかりました。 mod_proxy
を効果的に使用して、PythonやDjango、RubyやRubyonRailsなどのさまざまな言語やテクノロジーで記述されたアプリケーションサーバーへのリバースプロキシを構成できます。 また、トラフィックの多いサイトの複数のバックエンドサーバー間でトラフィックのバランスをとったり、複数のサーバーを介して高可用性を提供したり、SSLをネイティブにサポートしていないバックエンドサーバーに安全なSSLサポートを提供したりするためにも使用できます。
mod_proxy
とmod_proxy_http
はおそらく最も一般的に使用されるモジュールの組み合わせですが、さまざまなネットワークプロトコルをサポートする他のいくつかのモジュールがあります。 このチュートリアルではそれらを使用しませんでしたが、他の一般的なモジュールには次のものがあります。
- FTP(ファイル転送プロトコル)の場合は
mod_proxy_ftp
。 - SSLトンネリングの場合は
mod_proxy_connect
。 mod_proxy_ajp
for AJP(Apache JServ Protocol)、Tomcatベースのバックエンドなど。- Webソケットの場合は
mod_proxy_wstunnel
。
mod_proxy
の詳細については、公式のApachemod_proxyドキュメントを参照してください。