HAProxyをインストールしてみた – このべん#4ハンズオンの復習


みなさんこんばんは。2014/12/15にGMO Yoursで行われた このべん第4回「ConoHa VPSとHAProxyでロードバランサーを構築してみよう!」  にハンズオン組として参加してきました。
インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門


nginxなどのL4プロキシと違い、HAProxyはL7での振り分けができるので、どんな機能が使えるのだろう?と楽しみにしてましたが、ハンズオンの時間が1時間ということもあり、インストールだけで終わってしまいました(どうやら最初からそういうタイムチャートだった模様)。こちらでハンズオンの手順が公開されているとのことでしたので、当日駆け足で進んだ手順を家に帰ってから復習してみましたので公開します。

なお、ハンズオン手順のページではプロンプトの変更など、作業の本筋に影響が少ないところに時間が割かれていましたが、こちらではHAProxy以外の手順はなるべく簡潔にします。そして、当日のハンズオンではあらかじめプライベートネットワークが作成されていましたが、今回ははじめてプライベートネットワークを作成しますので、その手順も記載します。

また、httpd.conf (バックエンドのサーバー) や haproxy.cfg (ロードバランサー) の編集は、どこを修正したらよいかをお伝えするためにvimで編集していますが、本筋とは関係ないところは手抜きしてヒアドキュメントなどを用いています。また、作業はすべてrootで実施しています。

前提と構成図

ハンズオン手順に記載されている構成とまったく一緒にしています。構成図は以下の通りです。

このべん第4回 構成図
このべん第4回 構成図

構成図ではバックエンドのWEBサーバーからグローバルIPアドレスを削除していますが、今回この手順は省略しています。ガチガチにセキュアな環境にしたい場合は、ifdown eth0するなどしてください。

ConoHaアカウント作成

実は私、ConoHaのアカウントを持っていなかったので、この作業を契機にアカウントを作成しました。詳細な手順は本エントリ末尾に記載しますので、はじめてConoHaを触る方はご参考までにどうぞ。なお、アカウント作成にはクレジットカードとプッシュ信号を発信できる電話(一部050電話はだめっぽい)が必要です。公式サイトのアカウント作成手順はこちらになります。

VPS作成

アカウント作成が最後まですすむと、VPS作成画面に遷移します。

20141216_132433_cp.conoha.jp-Service-VPS-Add

以下の内容で1台目のVPSを作成してください。

プラン種別 標準プラン
プラン メモリ1GBプラン
テンプレートイメージ CentOS 6.5 (64bit)

残りの2台については、ConoHaコントロールパネルから「サービス」->「VPS」の順にクリックし、「+VPS追加」のボタンから作成します。以下のように、3台のVPSが作成され、起動中であることを確認します。

20141216_134644_cp.conoha.jp-Service-VPS

3台のサーバーにsshログインするため、サーバーリストからサーバー名をクリックし、画面右上の青い下向き矢印をクリックします。

IPアドレス確認
IPアドレス確認

こんな感じでIPアドレスを確認することができます。

20141216_134825_cp.conoha.jp-Service-VPS-Control-Console

3台ぶんのグローバルIPアドレスを控えておき、秘密鍵をダウンロードします。もし、上記画面からダウンロードし忘れても、サーバーリストの下にある「Key Pair」から1回ダウンロードすればOKです(3台とも同じ鍵ペアを使っているので)。

20141216_142104_cp.conoha.jp-Service-VPS-keyPair

SSHクライアントがLinuxやMACの場合は、ダウンロードしてきた秘密鍵のパーミッションを600にしておいてください。

20141216_142400_VPS-key

3台ともSSH接続ができることを確認した後、プライベートネットワークを作成するため、一旦3台ともシャットダウンを行います。以下のように、サーバーリストから全サーバーにチェックを入れ、画面右上の「シャットダウン」をクリックします。

20141216_140043_cp.conoha.jp-Service-VPS

確認画面でシャットダウン対象が正しいことを確認し、次に決定ボタンを押下します。

20141216_140101_cp.conoha.jp-Service-VPS

20141216_140111_cp.conoha.jp-Service-VPS-Shutdown-Default

 

プライベートネットワーク作成

メニューから「サービス」->「ローカルネットワーク」をクリックし、「+ローカルネットワーク追加」ボタンをクリックします。

20141216_140518_cp.conoha.jp-Service-LAN

ハンズオン当日と同じく、ここでは「192.168.0.0/24」のセグメントを追加します。

20141216_140531_cp.conoha.jp-Service-LAN-Add

プルダウンメニューで選んだセグメントが「192.168.0.0/24」であることを確認し、決定ボタンをクリックします。

20141216_140540_cp.conoha.jp-Service-LAN-Add

プライベートネットワークが出来上がりました。

20141216_140605_cp.conoha.jp-Service-LAN-Added

ここまでできたら、サーバーリストに戻り、各サーバーとローカルネットワークを接続します。この時点では、まだサーバーの電源を入れないでください。まず、サーバーリストからロードバランサーのVPSをクリックし、「ネットワーク」をクリックします。

20141216_140658_cp.conoha.jp-Service-VPS-Control-Network

NIC No. 2の接続ネットワーク「ローカル」が未設定になっているので、右側の「設定」ボタンをクリックします。

20141216_140710_cp.conoha.jp-Service-VPS-Control-Network

上記のように、ネットワークインターフェース設定で、セグメント「192.168.0.0/24」を選択し、確認ボタンを押下します。

20141216_140719_cp.conoha.jp-Service-VPS-Control-Network

セグメントが「192.168.0.0/24」になったことを確認し、決定ボタンを押下します。先ほどの「ネットワーク」画面に戻るので、以下の図のように、接続ネットワーク「ローカル」が設定済になっていればOKです。

20141216_140733_cp.conoha.jp-Service-VPS-Control-Network

以上のネットワーク追加作業を、バックエンドの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://<VPSのグローバルIPアドレス>/ にアクセスしてみましょう。「このサーバのアドレス」で始まるページが表示されればOKです。

 

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です。

20141216_204942_157.7.84.17320141216_204952_157.7.84.173

そして、 http://[VPSのIPアドレス]:10080/?hastats にアクセスして統計情報を見てみましょう。認証ダイアログが表示されますので、ユーザー名「admin」パスワード「conoha」を入力します。

20141216_173912_157.7.84.173-10080-hastats

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のサインアップを行ったときのスクリーンショットを撮っておきましたので、サインアップに不安な方は次のページを参考にしてみてください。