Raspberry PI シリーズで分散環境構築(その9: Webクラスタ構築のケース(後半))

# 序(連載一覧)
1. [Raspberry PI シリーズで分散環境構築(その1:モデル別、ディスクレスクライアント化の可否まとめ)](https://qiita.com/p_cub/items/e81dd0f49b3f6fb024a5)
2. [Raspberry PI シリーズで分散環境構築(その2: PiServer の解析と代替システムの設計まで)](https://qiita.com/p_cub/items/69fa32a9a62890ca1d04)
3. [Raspberry PI シリーズで分散環境構築(その3: dnsmasq のインストールと設定)](https://qiita.com/p_cub/items/e7c889b0f92a868a6c20)
4. [Raspberry PI シリーズで分散環境構築(その4: NFSサーバの構築とクライアント用OSのインポート)](https://qiita.com/p_cub/items/dd682de7de28276129e6)
5. [Raspberry PI シリーズで分散環境構築(その5: クラスタノード向け Raspberry PI OS のカスタマイズ(1))](https://qiita.com/p_cub/items/ecf4c48b7ecb08d971b1)
6. [Raspberry PI シリーズで分散環境構築(その6: クラスタノード向け Raspberry PI OS のカスタマイズ(2))](https://qiita.com/p_cub/items/73dc833302c3f064dc39)
7. [Raspberry PI シリーズで分散環境構築(その7: 各ラズパイ向けの tftp ルート設定と起動試験)](https://qiita.com/p_cub/items/ecef742e86ab2991c1b0)
8. [Raspberry PI シリーズで分散環境構築(その8: Webクラスタ構築のケース(前半))](https://qiita.com/p_cub/items/10751e2daa2d3b74c5d5)
9. [Raspberry PI シリーズで分散環境構築(その9: Webクラスタ構築のケース(後半))](https://qiita.com/p_cub/items/c4c837a57e6487a076d4)

本稿は連載の[その9]()となります。

# 概要
![RaspiCloudSystem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267238/9d0ab7af-1f13-cf7b-3cc9-9b4e8c6cb4fd.png)
連載の[その1](https://qiita.com/p_cub/items/e81dd0f49b3f6fb024a5)から[その7](https://qiita.com/p_cub/items/ecef742e86ab2991c1b0)までに、ラズパイを利用したディスクレスクラスタの基盤環境の構築が完了していますので、[前回](https://qiita.com/p_cub/items/10751e2daa2d3b74c5d5)から Web クラスタを構築しているわけですが、今回は上図の「PXEサーバ」または「分散環境コントローラ」に相当するホストに Apache 2.4 をインストールし、リバースプロキシ+負荷分散コントローラを構築していきます。

以後、Apache をインストールするホストを「コントローラ」と呼びます。

# 前提条件
1. 既存の OS に、30分程度で Apache をインストール+最低限のセキュリティを確保した状態の設定が終了し、サービスを立ち上げることができる人向けの文章です。Apache を初めて触る人向けの文章ではありません。
2. インストールするホストの OS/ディストリビューションは何でも構いませんが、インストールする環境によって httpd.conf 内でインクルードするサブファイルをどう分割するか、という作法が異なります。全ての環境での方法を説明するのは無理ですし、httpd.conf は内容が肥大化しやすいので、本稿に関連する部分だけ記載します。
3. 基本的に今回構築する Apache の機能はクラスタのノードであるディスクレスラズパイに、自分が受け付けた全ての要求をぶん投げるリバースプロキシ機能のみとします。認証や SSL化に関する詳細は記載しません(軽く言及する予定ですが)。

<dl>
<dt>コントローラのIP(ユーザーアクセス用)</dt><dd>172.16.0.80/24</dd>
<dt>コントローラのホスト名</dt><dd>IPそのまま(ServerName は設定しない)</dd>
<dt>コントローラがリッスンする HTTP ポート番号</dt><dd>80/TCP</dd>
<dt>コントローラのIP(対ラズパイ用)m</dt><dd>192.168.172.17/24</dd>
<dt>ディスクレスラズパイのIP</dt><dd>192.168.172.32 〜 192.168.172.35/24</dd>
<dt>ディスクレスラズパイがリッスンする HTTP ポート番号</dt><dd>8000/TCP</dd>
</dl>

# 実際の作業
## 1. Apache のインストール
(省略)

## 2. httpd.conf 全体設定で、必要なモジュールを追加(コメントアウトの解除/新規で行を追加)

Apache 用 DSO モジュールは /usr/lib/apache2/modules に保存されていることとします。
関連する代表的なモジュールを列挙しますが、これら全てが必要なわけではありません。

```config
# 必須: proxy_balancer に必要
LoadModule alias_module /usr/lib/apache2/modules/mod_alias.so
# 必須: proxy フレームワークモジュール(実際の接続にはプロトコルに応じたhttp/ftp/ajp/ws等のドライバ使う)
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
# 必須: proxy_balancer に必要
LoadModule slotmem_shm_module /usr/lib/apache2/modules/mod_slotmem_shm.so
# 必須: 負荷分散フレームワークモジュール(要求を分散する対象ホストを決定するためのアルゴリズムドライバが必須)
LoadModule proxy_balancer_module /usr/lib/apache2/modules/mod_proxy_balancer.so
# (ほぼ必須): HTML コンテンツ内のリンクなどを処理するための Proxy データドライバ
LoadModule proxy_html_module /usr/lib/apache2/modules/mod_proxy_html.so
# (ほぼ必須): HTTP 1.1 まで用の Proxy プロトコルドライバ
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
# (ほぼ必須): 負荷分散アルゴリズムドライバ 重み付きラウンドロビン
LoadModule lbmethod_byrequests_module /usr/lib/apache2/modules/mod_lbmethod_byrequests.so
# (ほぼ必須): 負荷分散アルゴリズムドライバ トラフィック量の少ないホストを優先するアルゴリズム
LoadModule lbmethod_byrequests_module /usr/lib/apache2/modules/mod_lbmethod_bytraffic.so
# (ほぼ必須): 負荷分散アルゴリズムドライバ CPU/メモリ等がアイドルなホストを優先するアルゴリズム
LoadModule lbmethod_byrequests_module /usr/lib/apache2/modules/mod_lbmethod_bybusyness.so

# (オプション): FTP 用 Proxy プロトコルドライバ
LoadModule proxy_ftp_module /usr/lib/apache2/modules/mod_proxy_ftp.so
# (オプション): HTTP2 用プロトコルドライバ (HTTP2 proxy ドライバがこれに依存)
LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so
# (オプション): HTTP2 用 Proxy プロトコルドライバ
LoadModule proxy_http2_module /usr/lib/apache2/modules/mod_proxy_http2.so
# (オプション): AJP(対Tomcat) Proxy プロトコルドライバ
LoadModule proxy_ajp_module /usr/lib/apache2/modules/mod_proxy_ajp.so 
# (オプション): CONNECT (トンネル) Proxy プロトコルドライバ
LoadModule proxy_connect_module /usr/lib/apache/modules/mod_proxy_connect.so
# (オプション): WebSocket Proxy プロトコルドライバ
LoadModule proxy_wstunnel_module /usr/lib/apache/modules/mod_proxy_wstunnerl.so
```

## 3. デフォルトのバーチャルホスト設定

```config
<virtualhost *:80>
   # サーバ名・ログ形式等の設定は省略

   # ドキュメントルートの設定はしない(コメントアウト)
   # DocumentRoot /var/www/html

   # SSL化したい場合はここに SSL/TLS 証明書関連設定を記述
   # (内容は省略)

   # ProxyPass / ProxyPassReverse 設定
   # クラスタ名はスラッシュで終了させないと、500番台エラーを返すので注意(これに気づくのに1日かかった)
   #   balancer://任意のクラスタ名/ (ラズパイ群を 'raspicluster' と名付けているがここ以外でこの名前は使わない)
   #   lbmethod=負荷分散方式(byrequest/bybusyness/bytraffic)
   #   timeout=秒数(ノードがダウンしていると判断するまでの時間)
   #   maxattempts=回数(ノードがダウンしているときの再挑戦の上限回数)
   ProxyPass / "balancer://raspicluster/" lbmethod=bytraffic timeout=1 maxattempts=1

   # なお、ノード側でサーバサイドプログラムを動かす場合等でセッション管理が必要な場合は以下の設定を利用すること。
   # stickysession に指定する値は、サーバサイド側のプログラムに依存。この例は PHP の例
   #ProxyPass / "balancer://raspicluster/" lbmethod=bytraffic timeout=1 maxattempts=1 nofailover=On stickysession=PHPSESSIONID 

   ProxyPassReverse / "balancer://raspicluster/"

   <Proxy balancer://raspicluster>
     # 認証させたい場合はここに記載
     # (省略)

     # 負荷分散するラズパイ群の指定
     # loadfactor の値は 1〜100 で、数値が大きいほど優先される.
     # 設定しない場合は全メンバー優先度1で統一される
     BalancerMember "http://192.168.172.35:8000/" loadfactor=6
     BalancerMember "http://192.168.172.34:8000/" loadfactor=5
     BalancerMember "http://192.168.172.33:8000/" loadfactor=4
     BalancerMember "http://192.168.172.32:8000/" loadfactor=1
   </Proxy>
</VirtualHost>
```

セッション管理が必要な、サーバサイドプログラムをラズパイで動かす場合の設定は、[こちら](http://www.hiihah.info/index.php?mod_proxy_balancer%E5%8D%98%E4%BD%93%E3%81%A7stickysession%E3%82%92%E8%A8%AD%E5%AE%9A) で詳しく解説されています。
以上で、負荷分散コントローラの設定は終了となります。

## 4. Apache の単体試験と Apache の起動

```shell-session
hoge@コントローラ $ sudo apachectl configtest
(中略)
Syntax OK.
hoge@コントローラ $ sudo systemctl start apache2
```

## 5. 結合試験
ここから結合試験となりますが、プロダクションレベルのスループットは求めていないので、以下の点を確認して終了とします。

+ Apache にアクセスしているのに HTTP レスポンスヘッダが Nginx になっている
+ Apache には存在しないが、Nginx には登録されているファイルを要求してエラーが出ることなく表示される
+ bash等 の for 文 + w3m(コマンドラインブラウザ)を利用して、Apache に対して連続してHTTP要求を行い、ディスクレスラズパイの Nginx アクセスログが適切に分散されているか確認

```shell-session
hoge@端末 $ for N in `seq 1 32`; do w3m -dump_head http://192.168.172.17/hoge.html; done
(中略)

HTTP/1.1 200 OK
Date: Tue, 30 Jun 2020 08:08:26 GMT
Server: nginx/1.14.2
Content-Type: text/html
Last-Modified: Tue, 30 Jun 2020 04:47:13 GMT
ETag: W/"5efac3d1-5e"
Content-Encoding: gzip
Connection: close

hoge@端末 $
```
Server は nginx になっていますし、HTTP レスポンスも 200 です。
ログの分散を確認した所、きちんと分散されていましたので、簡易的な結合試験は終了、となります。

# 次回予告
次回は、クラスタの構築ではなく、一旦脇道に逸れて、ディスクレスラズパイの syslog を集積する syslog サーバの構築をやってみたいと思います。