こちらの記事の環境をvagrantで作ります。
解説は自分の覚書でほぼ全て元記事に記載があります。
LVS (Linux Virtual Server)
Linuxサーバーをロードバランサとして使用するためのソフトウェア。
ロードバランサを使ってリクエストを振り分けることで負荷の分散を図る。
Linuxカーネルに組み込んで使用するカーネルモジュールと設定や管理を行うためのipvsadmコマンドから構成。
LVSを使ったロードバランサを実現するためのネットワーク構成
-
レイヤ4スイッチング
- TCP/IPレベルでパケットを転送する方式
- サーバーの代わりにクライアントからリクエストを受け取り、そのリクエストを一定のルールでサーバーに転送する処理を実現
-
パケット転送方式
- NAT
- IPパケットに対しロードバランサでNATを行ってパケットをサーバーに転送する
- ローカルネットワークとWANの接続部分に設置する
- サーバーがローカルネットワーク内にある場合など、サーバーとクライアントが直接接続できない場合でも利用できる
- 最も一般的
-> サーバーをインターネットから直接アクセスできないローカルネットワーク内に設置し、ロードバランサーに対してのみインターネットからのアクセスが可能な構成にできる
-> サーバーを狙った攻撃をブロックすることができる
- ダイレクトルーティング
- IPパケットを書き換えずにパケットをサーバーに転送する
- サーバーからクライアントへの通信についてはロードバランサを経由しない
- トンネリング
- IPパケットをカプセル化した上でサーバーに転送する
- サーバーからクライアントへの通信についてはロードバランサを経由しない
- ロードバランサとサーバー間の通信にカプセル化されたIPパケットが利用される
-> ロードバランサとサーバーが別のネットワーク上にあっても利用できる
- NAT
ホスト情報
ホスト | IPアドレス |
---|---|
ロードバランサ(private) | 192.168.33.81 |
ロードバランサ(public) | 172.20.10.2 (DHCPで割り当てられたもの) |
APPサーバ1 (private) | 192.168.33.82 |
APPサーバ2 (private) | 192.168.33.83 |
Vagrantfile
ロードバランサーはpublicとprivateのネットワークを持つ。
APPサーバはprivateのみ。
[ホスト側]
$ vi Vagrantfile
===================
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "centos65-x86_64-20140116"
config.vm.box_url = "https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box"
config.ssh.forward_agent = true
config.vm.define :node1 do |node|
node.vm.box = "centos65-x86_64-20140116"
node.vm.network :forwarded_port, guest:22, host:2071, id:"ssh"
node.vm.network :forwarded_port, guest:80, host:8151, id:"http"
node.vm.network :private_network, ip:"192.168.33.81", virtualbox__intnet: "private_net"
# virtualbox__intnet を指定することでゲストOS同士の仮想内部ネットワークを構築できる
# 値は任意の文字列
node.vm.network :public_network
end
# publicネットワーク。vagrant upでインタフェースを聞かれる
# 公共のWi-Fiだと設定できない場合があります。iPhoneテザリングはOKでした。
# 「1) en0: Wi-Fi (AirPort)」を選ぶ
# 固定IPを割り振ることもできるが、何故かアクセスができないのでDHCPでアドレスを取得
config.vm.define :node2 do |node|
node.vm.box = "centos65-x86_64-20140116"
node.vm.network :forwarded_port, guest:22, host:2072, id:"ssh"
node.vm.network :forwarded_port, guest:80, host:8152, id:"http"
node.vm.network :private_network, ip:"192.168.33.82", virtualbox__intnet: "private_net"
end
config.vm.define :node3 do |node|
node.vm.box = "centos65-x86_64-20140116"
node.vm.network :forwarded_port, guest:22, host:2073, id:"ssh"
node.vm.network :forwarded_port, guest:80, host:8153, id:"http"
node.vm.network :private_network, ip:"192.168.33.83", virtualbox__intnet: "private_net"
end
end
===================
LVSインストール
パケット転送方式はNAT
[ロードバランサ]
# ipvsadmインストール
$ sudo yum install ipvsadm
# ポートフォワード設定
$ sudo vi /etc/sysctl.conf
===================
net.ipv4.ip_forward = 1
===================
$ sudo /sbin/sysctl -p
$ sudo /sbin/sysctl -a | grep net.ipv4.ip_forward
# LVS設定
$ sudo ipvsadm -C # LVSの設定がクリアされます。本番で叩かないでください!!
$ sudo ipvsadm -A -t 172.20.10.2:80 # ロードバランサのpublicネットワーク設定
$ sudo ipvsadm -a -t 172.20.10.2:80 -r 192.168.33.82:80 -m # 転送先の登録
$ sudo ipvsadm -a -t 172.20.10.2:80 -r 192.168.33.83:80 -m
$ sudo ipvsadm -l
===================
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.20.10.2:http wlc
-> 192.168.33.82:http Masq 1 0 0
-> 192.168.33.83:http Masq 1 0 0
===================
$ sudo /etc/init.d/ipvsadm save # 再起動後もLVSの設定を残す場合
$ sudo cat /etc/sysconfig/ipvsadm # 保存内容確認
$ sudo chkconfig ipvsadm on # 再起動後も自動でLVSを起動する場合
[APPサーバ1,2設定]
# Apacheインストール
$ sudo yum install httpd
# Apache起動
$ sudo service httpd start
# index.html作成
$ sudo vi /var/www/html/index.html
===================
[APPサーバ1のとき]
node2
[APPサーバ2のとき]
node3
===================
# デフォルトgw設定
$ netstat -rn # 現在の設定確認
$ sudo route add default gw 192.168.33.81 # ロードバランサのprivateネットワーク
$ netstat -rn # デフォルトgwがロードバランサーになっていることを確認する
この状態でブラウザでhttp://172.20.10.2
にアクセスするとnode2, node3にアクセス可能となる。デフォルトではブラウザを更新するごとにnode2, node3が交互に表示される。
備考
最初は仮想IPを設定してそちら経由でアクセスさせようとしたが、
明示的に決めたIPはなぜか外部から通信できなかったのでDHCPでNICに割り振られたアドレスをそのまま利用した。どなたかvagrantのpublicネットワークを明示的に設定して通信させる方法教えてください(>_<)