XenServerでサーバ仮想化+DeleGateでグローバルIPひとつを使い回す

『社内に開発環境がない!』
ということで、なるべくコストをかけずに開発環境を量産してみた。

概要

今回やることの全体図はこんな感じ。

  • 無線LANルータのNAPT、多機能ゲートウェイ/プロキシサーバのDeleGate、サーバ仮想化技術のCitrix XenServer5を利用。
  • XenServerは無償のExpress Editionを利用。同時実行VM数や、使用できる物理メモリ容量、使用できる物理CPU数に制限があったり、XenCenterから複数のXenServerを管理できない、ライブマイグレーションができないなどの制限があるけど、、開発環境を作る上では十分な機能を備えてる。
  • DeleGateを通して各仮想マシンSSHで行けるようにする(無線LANルータのNAPTでもできるけど、DeleGateの練習も兼ねて)。
  • DeleGateのリバースプロキシ機能によって、HTTP(80)、HTTPS(443)*1を別サーバ・複数ドメインで外部公開する。
  • 仮想マシンのホスト名やIP割り当てはわかりやすいように次のようなルールにした。
物理サーバ VMのホスト名 IP割り当てルール
xensv01 vm1x- + OS名 192.168.11.11〜
xensv02 vm2x- + OS名 192.168.11.21〜
xensv03 vm3x- + OS名 192.168.11.31〜
  • ノートパソコンにインストールしたXenCenterを使って、各XenServerを管理する。

無線LANルータ

わかりやすく、無線LANルータのWAN側IPにドメインを振っておく。dev.hoge.jp
NAPT機能を使って、WAN側へのアクセスを192.168.11.2へ流すように設定。


続きはこちら。

DeleGateのインストールと設定

DeleGate 9.9.0のインストールと設定 - yuhei.kagaya

*1:HTTPSのプロトコル的に、複数の証明書を1つのIPで公開することが無理。。。

XenServerのインストールと仮想マシンの作成

XenServerでサーバ仮想化+DeleGateでグローバルIPひとつを使い回す - yuhei.kagayaの続き。



ダウンロード | XenServer | 製品情報 | シトリックスから、英語の質問に答えてXenServerとLinuxパックをダウンロード。
ダウンロードしたら、isoイメージをCD-Rに焼く。
あと、管理ツールのXenCenterもダウンロードして、ノートパソコンにインストールしておく(要.NET Framework)。

下記のページを参考にさせていただき、XenServerとLinuxパックをインストール。
[XenServer 5.0] インストール(XenCenter) - BLUE21(xe5_install_center1)
[XenServer 5.0] インストール(XenServer) 1/3 - BLUE21(xe5_install_server1)
[XenServer 5.0] インストール(XenServer) 2/3 - BLUE21(xe5_install_server2)


次に、XenCenterから各XenServerに接続して、仮想マシンを作る。
の前に、各XenServerに入れるOSのISOイメージを192.168.11.2のサーバに置き、各XenServerから共通で使えるようにする。
これで、XenCenterのドライブメニューから選択できるようになる。

ISOライブラリ登録用NFSサーバの構築

DeleGateサーバ兼ISOライブラリ登録用NFSサーバ(192.168.11.2)のOSはCentOS4.7。
/home/storageを共有するように設定。

mkdir -p /home/storage/INSTALL/iso/Tools
vi /etc/exports
/home/storage 192.168.11.0/24(ro)

設定を反映させる。

exportfs -r

設定できたか確認。

exportfs -v
/home/storage   192.168.11.0/24(ro,wdelay,root_squash)

allowとdenyの設定。

vi /etc/hosts.deny
portmap mountd statd nfsd lockd rquotad: ALL

vi /etc/hosts.allow
portmap mountd statd nfsd lockd rquotad: 192.168.11.0/255.255.255.0

リスタートして確認。

/etc/init.d/portmap restart
/etc/init.d/nfs restart
rpcinfo -p
   プログラム バージョン プロトコル ポート
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100024    1   udp    635  status
    100024    1   tcp    638  status
    100011    1   udp    647  rquotad
    100011    2   udp    647  rquotad
    100011    1   tcp    650  rquotad
    100011    2   tcp    650  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100021    1   udp  35272  nlockmgr
    100021    3   udp  35272  nlockmgr
    100021    4   udp  35272  nlockmgr
    100021    1   tcp  40352  nlockmgr
    100021    3   tcp  40352  nlockmgr
    100021    4   tcp  40352  nlockmgr
    100005    1   udp    663  mountd
    100005    1   tcp    666  mountd
    100005    2   udp    663  mountd
    100005    2   tcp    666  mountd
    100005    3   udp    663  mountd
    100005    3   tcp    666  mountd


XenCenterから下記のように行う。

  1. New Storage
  2. NFSを選択して、Next
  3. 以下のように入力
    1. Name NFS ISO library(tools)
    2. ShareName 192.168.11.2:/home/storage/INSTALL/iso/Tools
  4. Finish


が、NFSマウントできず、失敗する。。。

xensv01から調べてみたところ、portmapperにたどり着けてないっぽい。

[root@xensv01 ~]# /usr/sbin/rpcinfo -p 192.168.11.2
rpcinfo: can't contact portmapper: RPC: Remote system error - No route to host

ファイヤーウォール開けてなかった。。。

NFSのポート番号を固定

rpc.statdやrpc.mountdはportmapでころころかわるらしい。
ファイヤーウォール全開は嫌なので、NFSのポート番号を固定にする。

portmap tcp,udp 111 既に固定されてる
nfs tcp,udp 2049 既に固定されてる
lockd tcp,udp 10001 今回固定する
statd tcp,udp 10002,10003 今回固定する
mountd tcp,udp 10004 今回固定する
rquotad tcp,udp 10005 今回固定する


設定ファイルを作成する。

vi /etc/sysconfig/nfs

### NFS port numbers ###
# rpc.statd
STATD_PORT=10002
STATD_OUTGOING_PORT=10003

# rpc.mountd
MOUNTD_PORT=10004

# rpc.rquotad
RQUOTAD_PORT=10005

# nlockmgr
LOCKD_UDPPORT=10001
LOCKD_TCPPORT=10001

ファイヤーウォールを開ける。

iptables -I RH-Firewall-1-INPUT 15 -p tcp -m state --state NEW -m tcp --dport 111 -j ACCEPT
iptables -I RH-Firewall-1-INPUT 15 -p udp -m state --state NEW -m udp --dport 111 -j ACCEPT

iptables -I RH-Firewall-1-INPUT 15 -p tcp -m state --state NEW -m tcp --dport 2049 -j ACCEPT
iptables -I RH-Firewall-1-INPUT 15 -p udp -m state --state NEW -m udp --dport 2049 -j ACCEPT

iptables -I RH-Firewall-1-INPUT 15 -p tcp -m state --state NEW -m tcp --dport 10001:10005 -j ACCEPT
iptables -I RH-Firewall-1-INPUT 15 -p udp -m state --state NEW -m udp --dport 10001:10005 -j ACCEPT

/etc/init.d/iptables save
/etc/init.d/iptables restart


設定を反映する。(nfslock、nfsの再起動)

service nfslock restart
service nfs restart

/usr/sbin/rpcinfo -p
   プログラム バージョン プロトコル ポート
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100024    1   udp  10002  status
    100024    1   tcp  10002  status
    100011    1   udp  10005  rquotad
    100011    2   udp  10005  rquotad
    100011    1   tcp  10005  rquotad
    100011    2   tcp  10005  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100021    1   udp  10001  nlockmgr
    100021    3   udp  10001  nlockmgr
    100021    4   udp  10001  nlockmgr
    100021    1   tcp  10001  nlockmgr
    100021    3   tcp  10001  nlockmgr
    100021    4   tcp  10001  nlockmgr
    100005    1   udp  10004  mountd
    100005    1   tcp  10004  mountd
    100005    2   udp  10004  mountd
    100005    2   tcp  10004  mountd
    100005    3   udp  10004  mountd
    100005    3   tcp  10004  mountd

コレでオッケー。固定したら、XenCenterからISOライブラリの登録ができた。


参考にさせていただきました。
Linuxシステム構築Tips - NFSサーバのポートを固定する設定方法 (RHEL編)
How can I configure a system as an NFSv3 server which sits behind a firewall with NFS clients outside of the firewall? - Red Hat Customer Portal

ISOライブラリをもってくる。

CentOSのホームページから、CentOS5.2をDVDイメージをダウンロードしてもってきた。
ファイルがかなりでかいので、nohupでバックグラウンドで動かしておく。
夜だったし、一晩寝た。起きたら終わってた。

cd /home/storage/INSTALL/iso/Tools
nohup wget http://www.ftp.ne.jp/Linux/packages/CentOS/5.2/isos/i386/CentOS-5.2-i386-bin-DVD.iso &

仮想マシンの作成

こちらを参考にさせていただき、各XenServerにCentOS5.2の仮想マシンを作成。
[XenServer 5.0] XenVM作成 - CentOS 5.0 ( 1/3 ) - BLUE21(xe5_centos5_1)


作成完了後自動起動してるので、XenCenterのConsoleタブを選択して、いつものOSインストールウィザード開始。


ちなみに、日本語UTF-8でインストールしたら、XenCenterのコンソールで文字化けして何してんだかわからない。。。
なのでEnglishでインストールしたほうがいい。
XenCenterのコンソールの文字コード、変えられないのかな?


XenServer自体にログインして、/etc/sysconfig/i18n のファイルを編集して文字コードを変え、再起動してみたけどダメだった。。
デフォルト。

LANG="en_US.UTF-8"
SYSFONT="drdos8x8"

これにしてみた。

LANG="ja_JP.UTF-8"
SUPPORTED="ja_JP.UTF-8:ja_JP:ja"
SYSFONT="latarcyrheb-sun16"

意味なし。。。とりあえず元に戻してEnglishのままにする。


XenCenterから仮想マシンのVirtualization Stateがとれない

仮想マシンにxs-tools.isoからツールを入れないといけないっぽい。


まずはXenCenterから仮想マシンを選択し、XenCenterのドライブメニューからxs-tools.isoを選択。

次に、XenCenterのConsoleタブを選択してログイン。

ドライブメニューで選択したxs-tools.isoをマウントしてインストール。

mount /dev/xvdd /mnt
/mnt/Linux/install.sh
/vinstall.sh 
Detected `CentOS release 5.2 (Final)' (centos version 5).

The following changes will be made to this Virtual Machine:		
  * packages to be installed/upgraded:
    - kernel-xen-2.6.18-92.1.10.el5.xs5.0.0.39.i686.rpm
    - xe-guest-utilities-5.0.0-361.i386.rpm

Continue? [y/n] ^[[A
Invalid response `ontinue? [y/n] 
Invalid response `['
Continue? [y/n] 
Invalid response `A'
Continue? [y/n] y

Preparing...                ########################################### [100%]
   1:xe-guest-utilities     ########################################### [100%]
Preparing...                ########################################### [100%]
   1:kernel-xen             ########################################### [100%]

You should now reboot this Virtual Machine.

んで、再起動。
すると、XenCenterから情報がとれた。
Virtualization State:Optimized(version 5.0 installed) になった。


参考にさせていただきました。
4.4.Linuxゲストエージェントのインストール
Chapter5.VMの更新

DeleGate 9.9.0のインストールと設定

XenServerでサーバ仮想化+DeleGateでグローバルIPひとつを使い回す - yuhei.kagaya
XenServerのインストールと仮想マシンの作成 - yuhei.kagaya
の続きで、DeleGateを使ってLAN内部のサーバを公開する。

  • DeleGateを通してLAN内部のサーバにSSHで行けるようにする。
  • DeleGateのリバースプロキシ機能によって、HTTP(80)、HTTPS(443)を別サーバ・複数ドメインで外部公開する。

ソースをもってきてコンパイル

DeleGateの現在の最終バージョン9.9.0をインストールした。

コンパイルするときに以下はとくにanonymous-FTPを必要なかったのでやらなかった。

vi src/Makefile

(*a) anonymous-FTP アクセス時などに、アクセス者名として使われるアドレスを、
      以下のように定義して下さい。

#ADMIN = undef
ADMIN = hoge@hoge.jp
cd /usr/local/src
wget ftp://ftp.delegate.org/pub/DeleGate/delegate9.9.0.tar.gz

tar xzvf tar xzvf delegate9.9.0.tar.gz
cd delegate9.9.0/src
make

...

make[1]: Entering directory `/usr/local/src/delegate9.9.0/src'
/usr/local/src/delegate9.9.0/mkmake.exe +r -ckconf Makefile.chk Makefile.tst DELEGATE_CONF "ar" "undef" ""
        ckconf:
        ADMIN = 'undef'
        get ADMIN value interactively ...
!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!   You should have defined ADMIN as:                      !
!     ADMIN = mail-address-of-the-DeleGate-administrator   !
!   either in DELEGATE_CONF or in the Makefile.      !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Enter your E-mail address [root@hoge.jp]: root@hoge.jp

コレで、src/deletaged ができた。

次に、インストール。

/usr/local/delegate にインストールして、
/usr/local/delegate/var 配下にキャッシュやログなどを置くことにした。

mkdir -p /usr/local/delegate/bin
mkdir -p /usr/local/delegate/conf/conf.d
mkdir -p /usr/local/delegate/var/cache
mv /usr/local/src/delegate9.9.0/src/delegated /usr/local/delegate/bin/

/usr/sbin/groupadd delegate
/usr/sbin/adduser -g delegate -d /usr/local/delegate/var -s /bin/false delegate

chown -R delegate.delegate /usr/local/delegate/var

起動スクリプトの作成

こちらを参考にさせていただき、起動スクリプト /etc/init.d/delegate を作成。
delegate設定

vi /etc/init.d/delegate
#!/bin/sh
#
# chkconfig: 35 90 10
# description: Delegated, multi-purpose application level gateway
# processname: delegated
#
# This file was automatically customized by debmake on Mon, 1 Dec 1997 17:23:23 +0900
#
# Written by Miquel van Smoorenburg <miquels@drinkel.ow.org>.
# Modified for Debian GNU/Linux by Ian Murdock <imurdock@gnu.ai.mit.edu>.
# Modified for Debian by Christoph Lameter <clameter@debian.org> 


DAEMON=/usr/local/delegate/bin/delegated

DGROOT=/usr/local/delegate/var
SITECONF=/usr/local/delegate/conf/site.conf
CONFDIR=/usr/local/delegate/conf/conf.d
OWNER=delegate/delegate



if [ ! -x $DAEMON ];
then
    echo "$DAEMON does not exist."
    exit 0
fi


if [ ! -r $SITECONF ];
then
    echo "$SITECONF does not exist."
    exit 0
fi


if [ ! -d $CONFDIR ];
then
    echo "$CONFDIR does not exist."
    exit 0
fi

for p in $CONFDIR/*:[0-9]*.conf
do
    if [ ! -f $p ];
    then
        echo "[addr:port].conf does not exist."
        exit 0
    fi
done


options="DGROOT=$DGROOT OWNER=$OWNER"

case "$1" in
    start)
        if [ "$2" = "" ];
        then
            for p in $CONFDIR/*:[0-9]*.conf
            do
                addrport=`basename $p .conf`
                $DAEMON -P$addrport $options +=$SITECONF +=$p
            done
        else
            if [ -f $CONFDIR/$2.conf ];
            then
                $DAEMON -P$2 $options +=$SITECONF +=$CONFDIR/$2.conf
            else
                echo "no configuration for address:port $2 found."
                exit 1
            fi
        fi
    ;;
   
   
    stop)
        if [ "$2" = "" ];
        then
            for p in $CONFDIR/*:[0-9]*.conf
            do
                addrport=`basename $p .conf`
                $DAEMON -Fkill -P$addrport $options +=$SITECONF
            done
        else
            $DAEMON -Fkill -P$2 $options +=$SITECONF
        fi
    ;;
   
    restart|reload)
        if [ "$2" = "" ];
        then
            for p in $CONFDIR/*:[0-9]*.conf
            do
                addrport=`basename $p .conf`
                $DAEMON -r -P$addrport $options +=$SITECONF +=$p
            done
        else
            if [ -f $CONFDIR/$2.conf ];
            then
                $DAEMON -r -P$2 +=$SITECONF $options +=$CONFDIR/$2.conf
            else
                echo "no configuration for address:port $2 found."
                exit 1
            fi
        fi
    ;;
   
   
    *)
         echo "Usage: /etc/init.d/delegate {start|stop|restart|reload} [addr:port]"
         exit 1
    ;;
   
esac

exit 0
chmod 770 /etc/init.d/delegate


こちらのページを参考にさせていただき、CONFDIR=/usr/local/delegate/conf/conf.d に置いたファイル名が、待ち受けアドレス:ポートを表し、ファイル内容で詳細を記述する形式にした。

設定ファイル例:/usr/local/delegate/conf/conf.d/192.168.11.2:11022.conf
※DeleGateの動作するサーバのIPアドレス192.168.11.2のポート番号11022で動作させる設定ファイル

自動起動の設定

cd /etc/init.d/
/sbin/chkconfig delegated on
/sbin/chkconfig --list delegated
delegated       0:off   1:off   2:on    3:on    4:on    5:on    6:of

DeleGate全体の設定 site.conf

vi /usr/local/delegate/conf/site.conf


CRON="0 3 * * * -expire 7"
ADMIN="hoge@hoge.jp"

LANのなかのサーバに外部ネットワークからSSHを中継するDeleGateの設定

XenServerでサーバ仮想化+DeleGateでグローバルIPひとつを使い回す - yuhei.kagayaのvm11(192.168.11.)に、
ポート番号11022に接続してSSHで行けるようにする。

vi /usr/local/delegate/conf/conf.d/192.168.11.2:11022.conf


RELIABLE="*"
SERVER="tcprelay://192.168.11.11:22/"
TIMEOUT=con:10800,io:10800,login:10800

ファイヤーウォールあけとく。

iptables -I RH-Firewall-1-INPUT 21 -p tcp -m state --state NEW -m tcp --dport 11022 -j ACCEPT
/etc/init.d/iptables save
/etc/init.d/iptables restart


この設定のDeleGateを起動、停止、再起動

/etc/init.d/delegate start 192.168.11.2:11022
/etc/init.d/delegate stop 192.168.11.2:11022
/etc/init.d/delegate restart 192.168.11.2:11022

DeleGateのリバースプロキシ機能を使ってLANのなかのサーバを公開する設定

XenServerでサーバ仮想化+DeleGateでグローバルIPひとつを使い回す - yuhei.kagayaの全体図のように
外部ネットワークから

  • http://dev31.hoge.jpのリクエストがきた場合にvm31へ
  • http://dev32.hoge.jpのリクエストがきた場合にvm32へ

と、リクエストをマウントしてDeleGateから代理リクエストしてクライアントへ返す。

vi /usr/local/delegate/conf/conf.d/192.168.11.2:80.conf


SERVER=http
URICONV=""

### vm31
HOSTLIST="vm31-virtualhost:dev31.hoge.jp"
MOUNT="/* http://192.168.11.31/* nvhost=vm31-virtualhost,nvserv=-thru"
REACHABLE="192.168.11.31"

### vm32
HOSTLIST="vm32-virtualhost:dev32.hoge.jp,aiueo.hoge.jp,kakikukeko.hoge.jp"
HOSTLIST="vm33-virtualhost:+,test.hoge.jp"
MOUNT="/* http://192.168.11.32/* nvhost=vm32-virtualhost,nvserv=-thru"
REACHABLE="192.168.11.32"


RELIABLE="*"
LOGFILE=""
PROTOLOG="${LOGDIR}/${PORT}/[date+%d].${PROTO}"
CONNECT="direct:*:*"

URICONVを設定しないと、クライアントに返すHTMLドキュメント中のURIが/に書き換えられてしまう。cssやimageタグ、aタグのsrcにhttp://〜から指定しても/から書き換えられてしまう。
なので、わざとURICONVの設定を効かないようにする。


http://www.delegate.org/delegate/Manual.htm#HOSTLISTはカンマで区切ることにより複数のホストに一つの名前をつけておける。
名前をつけたホストのリストはnvhostで指定できる。また、「+,」から始めれば同リストにホストを追加できる。
上の場合、

  • dev32.hoge.jp
  • aiueo.hoge.jp
  • kakikukeko.hoge.jp
  • test.hoge.jp

で来たリクエストをマウントして192.168.11.32に代理リクエストするようになる。


Mountオプションの「nvhost=domain,nvserv=-thru」を使うことで、ドメインで来たリクエストをそのまま対象のサーバにドメイン名でリクエストすることができる。なので、対象サーバ(上の例だと192.168.11.31や192.168.11.32)のApacheではVirtualHostをきる設定が使える。




こちらのサイトを参考にさせていただきました。
DeleGate Home Page (www.delegate.org)
delegate設定
猫ぐらし: DeleGate(9.1.1)インストール&設定
Delegateのインストール
delegate のインストール
DeleGate version 9.9 リファレンスマニュアル の日本語訳
DeleGate 設定例
DeleGate‚ðŽg‚Á‚ÄLAN“à•”‚̃T[ƒo‚ðŒöŠJ‚·‚é•û–@