序章

リバースプロキシは、HTTP(S)リクエストを受け取り、それらを1つ以上のバックエンドサーバーに透過的に配信するタイプのプロキシサーバーです。 リバースプロキシは、多くの最新のWebアプリケーションが、ユーザーが直接アクセスすることを意図しておらず、基本的なHTTP機能のみをサポートするバックエンドアプリケーションサーバーを使用して着信HTTP要求を処理するため便利です。

リバースプロキシを使用して、これらの基盤となるアプリケーションサーバーに直接アクセスされないようにすることができます。 また、着信要求からの負荷を複数の異なるアプリケーションサーバーに分散して、大規模なパフォーマンスを向上させ、フェイルセーフを提供するためにも使用できます。 キャッシュ、圧縮、SSL暗号化など、アプリケーションサーバーが提供しない機能でギャップを埋めることができます。

このチュートリアルでは、mod_proxy拡張機能を使用してApacheを基本的なリバースプロキシとして設定し、同じネットワーク上で実行されている1つまたは複数のバックエンドサーバーに着信接続をリダイレクトします。 このチュートリアルでは、 Flask Webフレームワークで記述された単純なバックエンドを使用しますが、任意のバックエンドサーバーを使用できます。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • この初期サーバーセットアップチュートリアルでセットアップされた1台のCentOS7サーバー(sudo非rootユーザーを含む)。
  • CentOS 7 にLinux、Apache、MySQL、PHP(LAMP)スタックをインストールする方法のステップ1に従って、サーバーにApache2をインストールします。
  • オプションで、yum install nanoとともにインストールされたnanoテキストエディタ。 CentOSにはデフォルトでviテキストエディタが付属していますが、nanoの方がユーザーフレンドリーです。

ステップ1—必要なApacheモジュールの紹介

Apacheをリバースプロキシとして使用するために必要なモジュールには、mod_proxy自体と、さまざまなネットワークプロトコルをサポートするように機能を拡張するアドオンモジュールのいくつかが含まれます。 具体的には、以下を使用します。

  • mod_proxy、接続をリダイレクトするためのメインプロキシモジュールApacheモジュール。 これにより、Apacheが基盤となるアプリケーションサーバーへのゲートウェイとして機能できるようになります。
  • mod_proxy_http、HTTP接続のプロキシのサポートを追加します。
  • mod_proxy_balancerおよびmod_lbmethod_byrequestsは、複数のバックエンドサーバーの負荷分散機能を追加します。

CentOS 7の新規インストールでは、4つのモジュールすべてがデフォルトで有効になっています。 次のコマンドを実行して、それらが有効になっていることを確認できます。

  1. httpd -M

コマンド出力には、有効なすべてのApacheモジュールが一覧表示されます。 探している4行は、前述のモジュール名です。

Output
. . . proxy_module (shared) . . . lbmethod_byrequests_module (shared) . . . proxy_balancer_module (shared) . . . proxy_http_module (shared) . . .

モジュールが有効になっていない場合は、/etc/httpd/conf.modules.d/00-proxy.confnanoで開くことで有効にできます。

  1. sudo nano /etc/httpd/conf.modules.d/00-proxy.conf

行の先頭から#記号を削除して、必要なモジュールを含む行のコメントを解除し、ファイルが次のようになるようにします。

/etc/httpd/conf.modules.d/00-proxy.conf
. . . 
LoadModule proxy_module modules/mod_proxy.so
. . . 
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
. . . 
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
. . . 
LoadModule proxy_http_module modules/mod_proxy_http.so
. . . 

変更を有効にするには、ファイルを保存してApacheを再起動します。

  1. sudo systemctl restart httpd

これで、ApacheはHTTPリクエストのリバースプロキシとして機能する準備が整いました。 次のステップでは、2つの非常に基本的なバックエンドサーバーを作成します。 これらは、構成が正しく機能するかどうかを確認するのに役立ちますが、独自のバックエンドアプリケーションが既にある場合は、手順3にスキップできます。

ステップ2—バックエンドテストサーバーの作成

いくつかの単純なバックエンドサーバーを実行することは、Apache構成が正しく機能しているかどうかをテストする簡単な方法です。 ここでは、テキスト行を出力してHTTPリクエストに応答する2つのテストサーバーを作成します。 一方のサーバーはHelloworld!と表示し、もう一方のサーバーは Howdy world!と表示します。

注:テスト以外のセットアップでは、バックエンドサーバーは通常、すべて同じ種類のコンテンツを返します。 ただし、特にこのテストでは、2つのサーバーが異なるメッセージを返すようにすることで、負荷分散メカニズムが両方を使用していることを簡単に確認できます。

Flaskは、Webアプリケーションを構築するためのPythonマイクロフレームワークです。 基本的なアプリには数行のコードしか必要ないため、Flaskを使用してテストサーバーを作成しています。 これらを設定するためにPythonを知る必要はありませんが、学びたい場合は、これらのPythonチュートリアルを参照してください。

まず、IUSパッケージリポジトリファイルをインストールしましょう。 IUS(Inline with Upstream Stable)は、Python3を含む最新バージョンの選択したソフトウェアをCentOSに提供するコミュニティプロジェクトです。

  1. sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm

次に、Python 3と、推奨されるPythonパッケージマネージャーであるPipをインストールします。

  1. sudo yum -y install python35u python35u-pip

Pipを使用してFlaskをインストールします。

  1. sudo pip3.5 install flask

必要なすべてのコンポーネントがインストールされたので、現在のユーザーのホームディレクトリにある最初のバックエンドサーバーのコードを含む新しいファイルを作成することから始めます。

  1. 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。

2番目のバックエンドサーバーは、別のテキスト行に戻ることを除けば、最初のサーバーとまったく同じなので、最初のファイルを複製することから始めます。

  1. cp ~/backend1.py ~/backend2.py

新しくコピーしたファイルを開きます。

  1. nano ~/backend2.py

返されるメッセージをHelloworld!から Howdy world!に変更し、ファイルを保存して閉じます。

〜/ backend2.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'Howdy world!'

次のコマンドを使用して、ポート8080で最初のバックグラウンドサーバーを起動します。 これにより、Flaskの出力が/dev/nullにリダイレクトされます。これは、コンソール出力がさらに曇ってしまうためです。

  1. FLASK_APP=~/backend1.py flask run --port=8080 >/dev/null 2>&1 &

ここでは、flaskコマンドの前に、同じ行にFLASK_APP環境変数を設定しています。 環境変数は、シェルから生成されたプロセスに情報を渡すための便利な方法です。 環境変数の詳細については、 LinuxVPSで環境変数とシェル変数を読み取って設定する方法を参照してください。

この場合、環境変数を使用すると、設定が実行中のコマンドにのみ適用され、その後は使用できなくなります。これは、flaskコマンドに2番目のサーバーを起動するように指示するのと同じ方法で別のファイル名を渡すためです。

同様に、このコマンドを使用して、ポート8081で2番目のサーバーを起動します。 FLASK_APP環境変数の値が異なることに注意してください。

  1. FLASK_APP=~/backend2.py flask run --port=8081 >/dev/null 2>&1 &

curlを使用して、2つのサーバーが実行されていることをテストできます。 最初のサーバーをテストします。

  1. curl http://127.0.0.1:8080/

これにより、端末に Hello world!が出力されます。 2番目のサーバーをテストします。

  1. curl http://127.0.0.1:8081/

代わりにHowdyworld!が出力されます。

:このチュートリアルを終了するときのように、両方のテストサーバーが不要になった後で閉じるには、killall flaskを実行するだけです。

次のステップでは、Apacheの構成ファイルを変更して、リバースプロキシとして使用できるようにします。

ステップ3—リバースプロキシを有効にするためにデフォルト構成を変更する

このセクションでは、単一のバックエンドサーバーまたは負荷分散されたバックエンドサーバーのアレイのリバースプロキシとして機能するように、デフォルトのApache仮想ホストを設定します。

:このチュートリアルでは、仮想ホストレベルで構成を適用しています。 Apacheのデフォルトのインストールでは、仮想ホストは構成されていません。 すべてのトラフィックをキャッチする単一のデフォルトの仮想ホストを作成します。 ただし、これらすべての構成フラグメントを他の仮想ホストでも使用できます。 Apacheの仮想ホストの詳細については、この CentOS7でApache仮想ホストを設定する方法のチュートリアルをお読みください。

ApacheサーバーがHTTPサーバーとHTTPSサーバーの両方として機能する場合は、リバースプロキシ構成をHTTP仮想ホストとHTTPS仮想ホストの両方に配置する必要があります。 Apacheを使用したSSLの詳細については、この CentOS7用のApacheでSSL証明書を作成する方法チュートリアルをお読みください。

nanoまたはお気に入りのテキストエディタを使用して、/etc/httpd/conf.dディレクトリに新しい空のApache構成ファイルを作成することにより、新しいデフォルトの仮想ホストを作成します。

  1. sudo nano /etc/httpd/conf.d/default-site.conf

以下の最初の例では、単一のバックエンドサーバーのリバースプロキシにデフォルトの仮想ホストを構成する方法を説明し、2番目の例では、複数のバックエンドサーバーの負荷分散されたリバースプロキシを設定します。

例1—単一のバックエンドサーバーのリバースプロキシ

次の内容をdefault-site.confファイルに貼り付けると、構成ファイルは次のようになります。

/etc/httpd/conf.d/default-site.conf
<VirtualHost *:80>
    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

手順2のサーバーの例に従った場合は、上記のブロックに記述されているように127.0.0.1:8080を使用します。 独自のアプリケーションサーバーがある場合は、代わりにそれらのアドレスを使用してください。

ここには3つのディレクティブがあります。

  • ProxyPreserveHostにより、Apacheは元のHostヘッダーをバックエンドサーバーに渡します。 これは、バックエンドサーバーにアプリケーションへのアクセスに使用されるアドレスを認識させるので便利です。
  • ProxyPassはメインのプロキシ設定ディレクティブです。 この場合、ルートURL(/)の下にあるすべてのものを、指定されたアドレスのバックエンドサーバーにマップする必要があることを指定します。 たとえば、Apacheが/exampleの要求を受け取ると、http://your_backend_server/exampleに接続し、元のクライアントに応答を返します。
  • ProxyPassReverseProxyPassと同じ構成である必要があります。 バックエンドサーバーからの応答ヘッダーを変更するようにApacheに指示します。 これにより、バックエンドサーバーがロケーションリダイレクトヘッダーを返した場合、クライアントのブラウザはバックエンドサーバーアドレスではなくプロキシアドレスにリダイレクトされ、意図したとおりに機能しなくなります。

これらの変更を有効にするには、Apacheを再起動します。

  1. sudo systemctl restart httpd

これで、Webブラウザでhttp://your_server_ipにアクセスすると、標準のApacheウェルカムページではなく、バックエンドサーバーの応答が表示されます。 手順2を実行した場合、これは Hello world!が表示されることを意味します。

例2—複数のバックエンドサーバー間での負荷分散

複数のバックエンドサーバーがある場合、プロキシ時にトラフィックをサーバー間で分散する良い方法は、mod_proxyの負荷分散機能を使用することです。

VirtualHostブロック内のすべての内容を次のように置き換えると、構成ファイルは次のようになります。

/etc/httpd/conf.d/default-site.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ブロックを使用して複数のサーバーを定義しました。 ブロックの名前はbalancer://mycluster(名前は自由に変更できます)で、基になるバックエンドサーバーアドレスを指定する1つ以上のBalancerMemberで構成されます。 ProxyPassおよびProxyPassReverseディレクティブは、特定のサーバーの代わりにmyclusterという名前のロードバランサープールを使用します。

手順2のサーバーの例に従った場合は、上記のブロックに記述されているように、BalancerMemberディレクティブに127.0.0.1:8080および127.0.0.1:8081を使用します。 独自のアプリケーションサーバーがある場合は、代わりにそれらのアドレスを使用してください。

これらの変更を有効にするには、Apacheを再起動します。

  1. sudo systemctl restart httpd

Webブラウザでhttp://your_server_ipにアクセスすると、標準のApacheページではなく、バックエンドサーバーの応答が表示されます。 手順2を実行した場合、ページを複数回更新すると、 Hello world! Howdy world!が表示されます。これは、リバースプロキシが機能し、両方のサーバー間で負荷分散されていることを意味します。

結論

これで、Apacheを1つまたは複数の基盤となるアプリケーションサーバーへのリバースプロキシとして設定する方法がわかりました。 mod_proxyを効果的に使用して、PythonとDjango、RubyとRuby on Railsなど、さまざまな言語とテクノロジーで記述されたアプリケーションサーバーへのリバースプロキシを構成できます。 また、トラフィックの多いサイトの複数のバックエンドサーバー間でトラフィックのバランスをとったり、複数のサーバーを介して高可用性を提供したり、SSLをネイティブにサポートしていないバックエンドサーバーに安全なSSLサポートを提供したりするためにも使用できます。

mod_proxymod_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ドキュメントを参照してください。