みなさんこんばんは。2014/12/15にGMO Yoursで行われた このべん第4回「ConoHa VPSとHAProxyでロードバランサーを構築してみよう!」 にハンズオン組として参加してきました。
インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門
nginxなどのL4プロキシと違い、HAProxyはL7での振り分けができるので、どんな機能が使えるのだろう?と楽しみにしてましたが、ハンズオンの時間が1時間ということもあり、インストールだけで終わってしまいました(どうやら最初からそういうタイムチャートだった模様)。こちらでハンズオンの手順が公開されているとのことでしたので、当日駆け足で進んだ手順を家に帰ってから復習してみましたので公開します。
なお、ハンズオン手順のページではプロンプトの変更など、作業の本筋に影響が少ないところに時間が割かれていましたが、こちらではHAProxy以外の手順はなるべく簡潔にします。そして、当日のハンズオンではあらかじめプライベートネットワークが作成されていましたが、今回ははじめてプライベートネットワークを作成しますので、その手順も記載します。
また、httpd.conf (バックエンドのサーバー) や haproxy.cfg (ロードバランサー) の編集は、どこを修正したらよいかをお伝えするためにvimで編集していますが、本筋とは関係ないところは手抜きしてヒアドキュメントなどを用いています。また、作業はすべてrootで実施しています。
前提と構成図
ハンズオン手順に記載されている構成とまったく一緒にしています。構成図は以下の通りです。

構成図ではバックエンドのWEBサーバーからグローバルIPアドレスを削除していますが、今回この手順は省略しています。ガチガチにセキュアな環境にしたい場合は、ifdown eth0するなどしてください。
ConoHaアカウント作成
実は私、ConoHaのアカウントを持っていなかったので、この作業を契機にアカウントを作成しました。詳細な手順は本エントリ末尾に記載しますので、はじめてConoHaを触る方はご参考までにどうぞ。なお、アカウント作成にはクレジットカードとプッシュ信号を発信できる電話(一部050電話はだめっぽい)が必要です。公式サイトのアカウント作成手順はこちらになります。
VPS作成
アカウント作成が最後まですすむと、VPS作成画面に遷移します。
以下の内容で1台目のVPSを作成してください。
プラン種別 | 標準プラン |
プラン | メモリ1GBプラン |
テンプレートイメージ | CentOS 6.5 (64bit) |
残りの2台については、ConoHaコントロールパネルから「サービス」->「VPS」の順にクリックし、「+VPS追加」のボタンから作成します。以下のように、3台のVPSが作成され、起動中であることを確認します。
3台のサーバーにsshログインするため、サーバーリストからサーバー名をクリックし、画面右上の青い下向き矢印をクリックします。

こんな感じでIPアドレスを確認することができます。
3台ぶんのグローバルIPアドレスを控えておき、秘密鍵をダウンロードします。もし、上記画面からダウンロードし忘れても、サーバーリストの下にある「Key Pair」から1回ダウンロードすればOKです(3台とも同じ鍵ペアを使っているので)。
SSHクライアントがLinuxやMACの場合は、ダウンロードしてきた秘密鍵のパーミッションを600にしておいてください。
3台ともSSH接続ができることを確認した後、プライベートネットワークを作成するため、一旦3台ともシャットダウンを行います。以下のように、サーバーリストから全サーバーにチェックを入れ、画面右上の「シャットダウン」をクリックします。
確認画面でシャットダウン対象が正しいことを確認し、次に決定ボタンを押下します。
プライベートネットワーク作成
メニューから「サービス」->「ローカルネットワーク」をクリックし、「+ローカルネットワーク追加」ボタンをクリックします。
ハンズオン当日と同じく、ここでは「192.168.0.0/24」のセグメントを追加します。
プルダウンメニューで選んだセグメントが「192.168.0.0/24」であることを確認し、決定ボタンをクリックします。
プライベートネットワークが出来上がりました。
ここまでできたら、サーバーリストに戻り、各サーバーとローカルネットワークを接続します。この時点では、まだサーバーの電源を入れないでください。まず、サーバーリストからロードバランサーのVPSをクリックし、「ネットワーク」をクリックします。
NIC No. 2の接続ネットワーク「ローカル」が未設定になっているので、右側の「設定」ボタンをクリックします。
上記のように、ネットワークインターフェース設定で、セグメント「192.168.0.0/24」を選択し、確認ボタンを押下します。
セグメントが「192.168.0.0/24」になったことを確認し、決定ボタンを押下します。先ほどの「ネットワーク」画面に戻るので、以下の図のように、接続ネットワーク「ローカル」が設定済になっていればOKです。
以上のネットワーク追加作業を、バックエンドのWEBサーバーにも繰り返し行います。3台ともできたら、VPSの電源を入れましょう。
WEBサーバー構築
WEBサーバーに行う作業は「追加NICの設定」「iptables設定」「Apache(httpd)インストール」「テストコンテンツ配置」の4つです。
追加NICの設定
NICが追加されていることを確認します。ただし、この時点ではまだNICがDownしています。
# ip link | grep eth1 3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
インターフェイス設定ファイル(ifcfg-eth1)を作成します。ハンズオン手順ではifcfg-eth0からコピーしてifcfg-eth1を作成する手順になっていますが、設定ミスによるインターフェイス名の重複などが怖いので、ヒアドキュメントで作成しちゃいます。2台のWEBサーバーで重複した値にならないよう気をつけましょう。
(WEBサーバー1台目)# cat << _EOF_ >> /etc/sysconfig/network-scripts/ifcfg-eth1 DEVICE="eth1" BOOTPROTO="none" ONBOOT="yes" TYPE="Ethernet" IPADDR="192.168.0.12" NETMASK="255.255.255.0" _EOF_
(WEBサーバー2台目)# cat << _EOF_ >> /etc/sysconfig/network-scripts/ifcfg-eth1 DEVICE="eth1" BOOTPROTO="none" ONBOOT="yes" TYPE="Ethernet" IPADDR="192.168.0.13" NETMASK="255.255.255.0" _EOF_
ここまでできたら、2台のWEBサーバーでインターフェイスをUPします。ハンズオン手順では service network restart する手順になっていますが、ConoHaのネットワークが重たい場合、eth0まで巻き込んで応答が帰ってこないこともあるので、eth1だけ起動すればOKです。
# ifup eth1 Determining if ip address 192.168.0.12 is already in use for device eth1...
上記のようなメッセージが表示され、プロンプトが戻ればOKです。それでは再度ip linkしてstateがUPになったことを確認しましょう。
# ip link | grep eth1 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
先ほどはstateがDOWNでしたが、今度はUPになっていますね。それでは、IPアドレス設定が正しいかを確認してみましょう。ハンズオンの手順では「ip addr」で確認する手順になっていますが、IPv6のアドレスが最初から17個振られているため、少々見づらいです。なので私は「ip route」で確認しました。以下のようになっていればOKです。
# ip route | grep eth1 192.168.0.0/24 dev eth1 proto kernel scope link src 192.168.0.12 169.254.0.0/16 dev eth1 scope link metric 1003
WEBサーバー1台目が192.168.0.12、WEBサーバー2台目が192.168.0.13であればOKです。
iptables設定
初期のiptables設定は以下の通りです。
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) target prot opt source destination
iptablesにhttpの穴を開けます。
# cp -p /etc/sysconfig/iptables /etc/sysconfig/iptables.orig # service iptables stop # iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # iptables -A INPUT -p icmp -j ACCEPT # iptables -A INPUT -i lo -j ACCEPT # iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT # iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT # iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited # iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited # service iptables save # service iptables restart
再度iptables設定を確認しましょう。80番ポートがACCEPTになっているはずです。
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:80 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) target prot opt source destination
設定ファイルでも確認してみます。
# egrep '(22|80)' /etc/sysconfig/iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
Apache(httpd)インストール
ConoHaのVPSは最初からPHPがインストールされているので、Apache(httpd)のみをインストールします。最初にパッケージの確認です。
# rpm -qa | egrep '^(php|httpd)' php-cli-5.3.3-27.el6_5.x86_64 php-pear-1.9.4-4.el6.noarch php-common-5.3.3-27.el6_5.x86_64 httpd-2.2.15-30.el6.centos.x86_64 php-gd-5.3.3-27.el6_5.x86_64 php-xml-5.3.3-27.el6_5.x86_64 php-pdo-5.3.3-27.el6_5.x86_64 httpd-tools-2.2.15-30.el6.centos.x86_64 php-5.3.3-27.el6_5.x86_64
サクッとyumでhttpdをインストールしちゃいましょう。
# yum -y install httpd
はい、インストールされました。
# rpm -qa | egrep '^(php|httpd)' php-cli-5.3.3-27.el6_5.x86_64 httpd-2.2.15-39.el6.centos.x86_64 php-pear-1.9.4-4.el6.noarch php-common-5.3.3-27.el6_5.x86_64 httpd-tools-2.2.15-39.el6.centos.x86_64 php-gd-5.3.3-27.el6_5.x86_64 php-xml-5.3.3-27.el6_5.x86_64 php-pdo-5.3.3-27.el6_5.x86_64 php-5.3.3-27.el6_5.x86_64
httpdインストール後、httpd.confのログ設定を修正します。Apacheに限らず(nginxなども)、ロードバランサーやリバースプロキシ配下にあるWEBサーバーでは、リモートホストのログを記録する設定にしていると上位のサーバーのIPアドレスが記録されてしまいます。このため、上位のサーバーが吐き出す環境変数「X-Forwarded-For」を記録するようにすることで、本来のアクセス元が記録されるようになります。Apache2.2のログフォーマットにどんなのがあるかはこちらを参照してください。
# cd /etc/httpd/conf # cp -p httpd.conf httpd.conf.orig # vi httpd.conf
497〜498行目のLogFormat設定を以下のように変更します。
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common
↓
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined #LogFormat "%h %l %u %t \"%r\" %>s %b" common LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common
ここまで終わったら、httpdを起動します。
# service httpd start Starting httpd: [ OK ] # chkconfig httpd on
テストコンテンツ配置
ロードバランサーを組んだときのために、WEB1,WEB2のどちらにアクセスしているのかわかるようにしておきます。環境変数などを表示するPHPスクリプトを用意していただいたので、これをドキュメントルートに保存しましょう。
# cd /var/www/html/ # wget https://gist.githubusercontent.com/ConoHa/fb7c783153a37c7a4882/raw/87ea58fb87f1fc7bb0c096b95fff212d9344a73f/index.php
以上の作業ができたらWEBサーバーの構築はおしまいです。手元のPCから http://
HAProxy構築
次に、ロードバランサーの構築を行います。SSHクライアントから、ロードバランサー用VPSにアクセスします。行う作業は「eth1インターフェイス作成」「iptables設定」「HAProxyインストール」「syslog、ログローテーション設定」です。
eth1インターフェイス作成
はい、いつものようにヒアドキュメントで作成です。
# cat << _EOF_ >> /etc/sysconfig/network-scripts/ifcfg-eth1 DEVICE="eth1" BOOTPROTO="none" ONBOOT="yes" TYPE="Ethernet" IPADDR="192.168.0.11" NETMASK="255.255.255.0" _EOF_
# ifup eth1
確認はWEBサーバーと同じく行ってくださいね。
iptables設定
WEBサーバーと同様、80番ポートに穴を開けますが、HAProxyのステータス確認用に10080番ポートも穴を開けます。
# cp -p /etc/sysconfig/iptables /etc/sysconfig/iptables.orig # service iptables stop # iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # iptables -A INPUT -p icmp -j ACCEPT # iptables -A INPUT -i lo -j ACCEPT # iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT # iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT # iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 10080 -j ACCEPT # iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited # iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited # service iptables save # service iptables restart
はい確認。
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:80 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:10080 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) target prot opt source destination
HAProxyインストール
haproxyパッケージをyumでインストールします。
# yum -y install haproxy # rpm -q haproxy haproxy-1.5.2-2.el6.x86_64
設定ファイルを編集します。
# cd /etc/haproxy/ # cp -p haproxy.cfg haproxy.cfg.orig # vi haproxy.cfg
「main frontend which proxys to the backends」セクションの待ち受けポートを変更します。
frontend main *:5000
↓
#frontend main *:5000 frontend main *:80
「main frontend which proxys to the backends」セクションのその他項目を以下のように変更します。
acl url_static path_beg -i /static /images /javascript /stylesheets acl url_static path_end -i .jpg .gif .png .css .js use_backend static if url_static default_backend app
↓
# acl url_static path_beg -i /static /images /javascript /stylesheets # acl url_static path_end -i .jpg .gif .png .css .js # use_backend static if url_static acl url_favicon path_end -i favicon.ico use_backend blackhole if url_favicon default_backend app
「static backend for serving up images, stylesheets and such」セクションをすべてコメントアウトします。
backend static balance roundrobin server static 127.0.0.1:4331 check
↓
#backend static # balance roundrobin # server static 127.0.0.1:4331 check
「round robin balancing between the various backends」セクションにあるデフォルト設定を削除し、WWW001とWWW002の設定を書き、faviconのログを出さない設定を付け加えます。
backend app balance roundrobin server app1 127.0.0.1:5001 check server app2 127.0.0.1:5002 check server app3 127.0.0.1:5003 check server app4 127.0.0.1:5004 check
↓
backend app balance roundrobin server app1 192.168.0.12:80 check weight 1 server app2 192.168.0.13:80 check weight 1 backend blackhole errorfile 403 /dev/null
haproxy.cfg の末尾に、以下の設定を付け加え、統計情報を見る設定を行います。
# 統計情報の確認画面を有効にする # http://[VPSのIPアドレス]:10080/?hastats listen hastats *:10080 mode http maxconn 64 stats enable stats show-legends stats uri /?hastats # IDとパスワード stats auth admin:conoha
ここまでできたら、haproxyを起動します。
# service haproxy start Starting haproxy: [ OK ] # chkconfig haproxy on
ブラウザで何度かリロードして確認します。「このサーバのアドレス」が192.168.0.12と192.168.0.13で交互に表示されていればOKです。
そして、 http://[VPSのIPアドレス]:10080/?hastats にアクセスして統計情報を見てみましょう。認証ダイアログが表示されますので、ユーザー名「admin」パスワード「conoha」を入力します。
syslog、ログローテーション設定
さて、設定はもう少しです。デフォルトの設定だと /var/log/messages にhaproxyのログが出力されて見づらいので、rsyslogの設定を変更します。
# cp -p /etc/rsyslog.conf /etc/rsyslog.conf.orig # vi /etc/rsyslog.conf
13〜14行目にある、syslogをUDPで受け付ける設定のコメントアウトを外します。
#$ModLoad imudp #$UDPServerRun 514
↓
$ModLoad imudp $UDPServerRun 514
42行目にある /var/log/messages の設定で、local2ファシリティを受け付けないようにします。
*.info;mail.none;authpriv.none;cron.none /var/log/messages
↓
#*.info;mail.none;authpriv.none;cron.none /var/log/messages *.info;mail.none;authpriv.none;cron.none;local2.none /var/log/messages
最後に以下を追記します。
local2.* /var/log/haproxy.log
ここまでできたら、rsyslogを再起動します。
# service rsyslog restart
rsyslogの設定が終わったら、ログローテーションの設定を変更します。/etc/logrotate.d 配下の設定ファイルがsyslogとhaproxyで別れているのですが、これではrsyslogの設定が2回HUPされてしまいます。なので、これを1つにまとめてしまいます(この手順はハンズオンにありませんでした)。
# cd /etc/logrotate.d/ # mkdir BACKUP # mv haproxy BACKUP/ # cp -p syslog BACKUP/syslog.orig # vi syslog
先頭行に「/var/log/haproxy.log」を追記します。出来上がりはこんな感じです。
# cat /etc/logrotate.d/syslog /var/log/haproxy.log /var/log/cron /var/log/maillog /var/log/messages /var/log/secure /var/log/spooler { sharedscripts postrotate /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true endscript }
以上で、haproxyの設定はおしまいです。いかがでしたでしょうか?今回はシンプルな振り分け設定を行いましたが、httpだけでなくTCPでの振り分けもできるそうなので、例えばSMTPやMySQLなどのロードバランスもできるようです。また機会があればチャレンジしてみようと思います。
おまけ
ConoHaのサインアップを行ったときのスクリーンショットを撮っておきましたので、サインアップに不安な方は次のページを参考にしてみてください。