hnakamur’s blog

ものすごい勢いで忘れる私のために未整理でもいいからとりあえずメモ

2009-08-27

NAT構成ネットワークでkeepalivedによるロードバランサの実験

libvirtでNAT構成にするための設定ApacheのServer-Side Includesの設定の準備ができたところで、いよいよロードバランサの実験です。

ホストOS上の/etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
    state BACKUP
    interface br0
    virtual_router_id 50
    priority 200
    advert_int 1
    garp_master_delay 10
    virtual_ipaddress {
        192.168.11.100
    }
}

virtual_server 192.168.11.100 80 {
    delay_loop 1
    lvs_sched rr
    lvs_method NAT #DR
    protocol TCP
    real_server 192.168.122.11 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status 200
            }
            connect_timeout 3
        }
    }
    real_server 192.168.122.12 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status 200
            }
            connect_timeout 3
        }
    }
}

実験用スクリプト

$ while :; do curl http://192.168.11.100; env LANG=C date; sleep 1; done

実行結果はこんな感じ。

Hello, this is vm11.
Thu Aug 27 02:47:03 JST 2009
Hello, this is vm10.
Thu Aug 27 02:47:05 JST 2009
Hello, this is vm11.
Thu Aug 27 02:47:06 JST 2009
Hello, this is vm10.
...(略)...

vm10でhttpdを止めてみるとvm11のみにいくようになりました。その前に

curl: (52) Empty reply from server

が1回出るときと1回も出ずにスムーズにvm11に切り替わるときがありました。

その後、vm10でhttpdを再開してみたのですが、引き続きvm11にしかいきません。ホストOSで

# /etc/init.d/keepalived reload

と実行してみると再びvm10とvm11に交互に投げるようになりました。inhibit_on_failureというオプションがあるぐらいなので指定しない場合は復活するのかと思っていたのですが。これはこういうものなのかは今後調査したいと思います。

ApacheのServer-Side Includesの設定

背景

ロードバランサの実験用にゲストOSのホスト名を入れたindex.htmlを

Hello, this is vm10.

といった感じで作っていたのですが、ゲストOSごとに書き換えずに済ませたいので Server-Side Includesを使う事にしました。

設定

mod_includeを参考にしました。CentOSの/etc/httpd/conf/httpd.confには

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
は設定済みだったので、<Directory "/var/www/html">セクションのOptions行に
    Options Indexes Includes FollowSymLinks
のようにIncludesを追加し、DirectoryIndexの行に
DirectoryIndex index.html index.shtml index.html.var
のようにindex.shtmlを追加しました。

そして、index.htmlをindex.shtmlに改名して

Hello, this is <!--#exec cmd="echo -n `hostname`"-->.
のように変更しました。

最初は

Hello, this is <!--#echo var="SERVER_NAME"-->.
にしたのですが、ロードバランサ経由だとリクエストURLのホスト名もしくはIPアドレスになってしまうのでだめでした。

次は

Hello, this is <!--#exec cmd="hostname"-->.
としたのですが、ドットの前に改行が入ってしまうことが判明したので、echo -n `hostname`に変更しました。

2009-08-26

libvirtでNAT構成にするための設定

ブリッジを止めてNATに切り替えたわけ

KVMのゲストOSのネットワークをブリッジにするの環境でkeepalivedでのVRRPの実験は成功したのですが、DSR構成でのロードバランサの実験がどうもうまくいきませんでした。仮想環境でのネットワーク構築がよくわかっていない私がいきなり上級者編のDSRにチャレンジというのに無理があったということで、まずはNAT構成でチャレンジすることにしてみました。

libvirtでNAT構成

libvirt: Wiki: Networkingを参考にしました。また、今まではゲストOSを実運用に近い設定にしようとして固定IPにしていましたが、virt-cloneでゲストOSイメージをコピーしたあとにゲストOS毎に設定を変えるのが面倒なので、今回から極力ゲストOS毎の設定変更箇所を少なくするという方針に変更しました。

試行錯誤しながらホストOSでのlibvirtの設定変更を変更したので、手順は無しで設定ファイルだけメモしておきます。

ホストOS (Ubuntu) の設定

/etc/libvirt/qemu/networks/default.xml

<network>
  <name>default</name>
  <uuid>212ea219-055f-bd26-1c76-52817e607642</uuid>
  <bridge name="virbr%d" />
  <forward mode="nat"/>
  <ip address="192.168.122.1" netmask="255.255.255.0">
    <dhcp>
      <range start="192.168.122.100" end="192.168.122.254" />
      <host mac="52:54:00:12:34:56" name="vm10" ip="192.168.122.11" />
      <host mac="52:54:00:12:34:57" name="vm11" ip="192.168.122.12" />
    </dhcp>
  </ip>
</network>

/etc/libvirt/qemu/vm10.xml

<domain type='kvm'>
  <name>vm10</name>
  <uuid>35e92166-78c8-641f-15d7-5a30af377d55</uuid>
  <memory>524288</memory>
  <currentMemory>524288</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='i686' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/kvm</emulator>
    <disk type='file' device='disk'>
      <source file='/home/hnakamur/kvm_work/vm10.qcow2'/>
      <target dev='hda' bus='ide'/>
    </disk>
    <disk type='file' device='cdrom'>
      <target dev='hdc' bus='ide'/>
      <readonly/>
    </disk>
    <interface type='network'>
      <mac address='52:54:00:12:34:56'/>
      <source network='default'/>
    </interface>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
  </devices>
</domain>

/etc/sysctl.confでは以下の設定変更をしてsysctl -pで読み込みました。

net.ipv4.ip_forward=1

/etc/resolv.conf

nameserver 192.168.122.1
nameserver 192.168.11.1

ゲストOS (CentOS) の設定

/etc/sysconfig/network (ホスト名はDHCPで設定するので空にしました)

NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=

/etc/resolv.conf

nameserver 192.168.122.1

/etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
DNS1=192.168.122.1

(追記) その後試していると/etc/resolv.confの設定が消されてしまってeth0が上がらないことがありました。/etc/sysconfig/network-scripts/ifcfg-eth0にDNS1=で指定しておくとOKでした。これがまっとうなのかはわかりませんが、とりあえずこれで。

(2009-08-27追記) CentOSのDeployment Guideの14.2. Interface Configuration Filesに説明がありました。PEERDNSがyesの場合DNS1とDNS2に指定した値で/etc/resolv.confが修正されます。dhcpの場合PEERDNSのデフォルト値はyesです。

ホストOSでのlibvirtの設定の試行錯誤

手順として整理したものは無いのですが、どんな試行錯誤をしたかのメモを書いておきます。

/etc/libvirt/qemu/networks/default.xmlの変更と反映での試行錯誤

libvirt: Wiki: Networkingを参考にしたのですが、結局のところvirshを起動してhelpコマンドで出てくるネット関連のコマンド(net-*)を手当たり次第に試して変更しました。net-editで変更してみたり、net-destroyやnet-undefineで消してからnet-createで作り直したり。net-destroyかnet-undefineを実行したときは、/etc/libvirt/qemu/networks/default.xmlが消えてしまって慌てたりしました。事前にバックアップをとっておいたほうがいいです。

また途中でnet-editを実行したときに

error: invalid network pointer in no network with matching uuid
というエラーが出て困りました。どうやら、/etc/libvirt/qemu/networks/default.xmlを直接エディタで変更したのがよくなかったようで、常にnet-editで編集するようにしておいたほうがいいみたいです。あと、確か元々の/etc/libvirt/qemu/networks/default.xmlにはuuidの要素は無かったのが、net-editで見たときは入っていました。/etc/libvirt/qemu/networks/default.xmlはテンプレートみたいなものでvmを作るときにそこからコピーされるのかとも思ったのですが、net-editで編集した結果は/etc/libvirt/qemu/networks/default.xmlに反映されるようです。そのときにどこか別の場所にも反映されているのかな、まだよくわかってないです。

ゲストOSでのlibvirt組み込みのDNSサーバーdnsmasqの設定変更の試行錯誤

libvirt: Wiki: Networking

If you are already running dnsmasq on your machine, please see libvirtd and dnsmasq.
という説明があります。libvirt: Wiki: Libvirtd and dnsmasqを読んで、psで見てみるとdnsmasqのプロセスがありますが/etc/dnsmasq.confはありませんでした。というわけでこれはlibvirtが起動したもののようです。ただ、/etc/init.d/dnsmasqとかはないんですよね。Bug #231060 in libvirt (Ubuntu): “packages dnsmasq and libvirt-bin conflict with each other”とかが関係ありそうですが、とりあえずスルーしました。

libvirtのネットワークをうまく設定できた今の状態ではpsで見るとこんな感じです。

# ps auxww|grep dnsmasq
root      5077  0.0  0.0   2076   564 pts/7    S+   00:52   0:00 grep dnsmasq
nobody   31008  0.0  0.0   2388   716 ?        S    Aug26   0:00 dnsmasq --strict-order
 --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file=  
--listen-address 192.168.122.1 --except-interface lo --dhcp-range 192.168.122.100,192.168.122.254
 --dhcp-host 52:54:00:12:34:56,vm10,192.168.122.11 --dhcp-host 52:54:00:12:34:57,vm11,192.168.122.12

こうなるまでにいろいろ試行錯誤しました。/etc/libvirt/qemu/networks/default.xmlの<dhcp>タグの設定に対応していることはわかったのですが、viやvirsh net-editで変更するだけでは反映されないようなので、killして上げ直そうとしたのですが起動方法をまた試行錯誤するはめに。どうやらnet-startのときに同時にあがるのかと思いきや

virsh# net-start default
error: Failed to start network default
error: internal error network is already active
というエラーになったり。1

今、再度試してみたところ以下の手順でとりあえず変更できることを確認しました。

virsh # net-destroy default

ここでviで/etc/libvirt/qemu/networks/default.xmlを編集

virsh # net-create /etc/libvirt/qemu/networks/default.xml
Network default created from /etc/libvirt/qemu/networks/default.xml

net-createを実行した時点でdnsmasqのプロセスが上がっていました。

さらに一覧を確認して自動実行する設定にします。

virsh # net-list --all
Name                 State      Autostart
-----------------------------------------
default              active     no
virsh # net-autostart default
error: failed to mark network default as autostarted
error: Failed to create symlink '/etc/libvirt/qemu/networks/autostart/default.xml' 
to '/etc/libvirt/qemu/networks/default.xml': File exists

別端末にて/etc/libvirt/qemu/networks/autostart/default.xmlというシンボリックリンクを削除します。

# ls -l /etc/libvirt/qemu/networks/autostart/default.xml 
lrwxrwxrwx 1 root root 38 Aug 26 20:43 /etc/libvirt/qemu/networks/autostart/default.xml -> /etc/libvirt/qemu/networks/default.xml
# rm /etc/libvirt/qemu/networks/autostart/default.xml

これでようやく設定変更できた状態でdnsmasqが起動できたと思ったら今度は、ゲストOSの変更前のIPアドレスがキャッシュされて残っていたようでdigコマンドで引いても古い値を返されてしまいました。そこでkillして

# dnsmasq --clear-on-reload

を実行した後再度killしてvirshでnet-destroy、net-createとして再起動などとしてなんとかdigで新しい設定のIPアドレスが返されるところまでこぎつけました。このへんの手順も試行錯誤してたまたま見つけただけで、まっとうな手順はまだよくわかっていません。が、とりあえず目的は達成できたのでよしということで。

DHCPの恩恵

ホストOSもゲストOSも192.168.122.1のdnsmasqを使うようにしたので、/etc/hostsからvm10とvm11のエントリを削除できました。DHCPといっても、/etc/libvirt/qemu/networks/default.xmlの<host>タグでMACアドレスに対してホスト名とIPアドレスを指定しているので、各vmのIPアドレスが変動することはありません。

2009-09-29追記

  1. これはdnsmasqのプロセスが残っていたからでした。単にpsでdnsmasqのPIDを調べてkillした後、net-defineコマンドでxmlの内容を反映し、net-startコマンドでdnsmasqを起動します。ちなみに、net-destroyは定義ファイルを削除するのでやりすぎです。

2010-09-19追記

定義ファイルごと削除されるのはnet-undefineを実行したときです。net-destroyはdnsmasqのプロセスを止めます。

2010-12-16追記

DHCPで運用しているとゲストを上げたまま一日ぐらいたつとゲストのIPアドレスが消失してネットワークが繋がらなくなるという現象を何度か体験しました。仕方が無いのでDHCPはやめて静的にIPアドレスを指定する運用に切り替えました。

2009-08-25

QEMU WikiのSlirpやTapについての解説がわかりやすい

QemuNetwork - #qemu WikiからたどれるSlirpやTapの解説が非常に分かりやすかったです。後から読み返すこともありそうなのでメモ。

  • Slirpについての説明
    • ルート権限が無くても使えます。→Slirpによるネットワークはuser mode networkingあるいは略してuser networkingとかuser-netとも呼ばれます。
    • Slirp自体はダイアルアップの時代にSLIP接続とのやりとりをソケットに見せかけるために作られたプログラムのことです。
    • KVMのネットワークページのUser Networkingセクションに対応します。
  • Tapに付いての説明
    • The 'tap' deviceの項とNote5:によると、Tapはホスト・ゲスト間の通信に使われるそうです。LinuxやBSDのカーネルでは直接eth0にパケットを送るということはできないので、間にtap0を挟む必要があるということです。で、tap0からホストを宛先にして送ればホストのeth0に届くということになります。
    • Possibility 2: NAT routing with one "external" net, and one "virtual internal" LANsがKVMのネットワークページのprivate virtual bridgeセクションに対応します。
    • Possibility 3: NO routing, one LAN made up of real and virtual devicesがKVMのネットワークページのpublic bridgeセクションやKVM Networking - Community Ubuntu DocumentationのCreating a network bridge on the hostセクションに対応します。

WiresharkのCLI版tsharkのインストール

Wiresharkとは

WiresharkはネットワークプロトコルアナライザEtherealの後継にあたるらしい。

インストール

リモートのサーバーにsshで入って使うことを想定しているのでGUI版ではなくCLI版を使います。CLI版のコマンドはtsharkです。

CentOS 5.2の場合

# yum install wireshark

ちなみにGUI版のパッケージ名はwireshark-gnome

Ubuntu 9.04の場合

$ sudo aptitude install tshark

ちなみにGUI版のパッケージ名はwireshark

テスト

CLI版のコマンドはtsharkです。

# tshark -n -i br0 tcp port 80

別の端末で以下のコマンドを実行。

$ telnet 192.168.11.241 80
GET /

tsharkの端末で^Cを入力。出力結果はこんな感じ。

# tshark -n -i br0 tcp port 80
Running as user "root" and group "root". This could be dangerous.
Capturing on br0
  0.000000 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=1738335 TSER=0 WS=6
  0.000905 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=3965771 TSER=1738335 WS=4
  0.000978 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSV=1738335 TSER=3965771
  1.362928 192.168.11.102 -> 192.168.11.241 HTTP GET /
  1.363635 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [ACK] Seq=1 Ack=8 Win=5792 Len=0 TSV=3967134 TSER=1738471
  1.364764 192.168.11.241 -> 192.168.11.102 HTTP Continuation or non-HTTP traffic 
  1.364829 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [ACK] Seq=8 Ack=22 Win=5888 Len=0 TSV=1738471 TSER=3967135
  1.364852 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [FIN, ACK] Seq=22 Ack=8 Win=5792 Len=0 TSV=3967136 TSER=1738471
  1.365315 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [FIN, ACK] Seq=8 Ack=23 Win=5888 Len=0 TSV=1738471 TSER=3967136
  1.366978 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [ACK] Seq=23 Ack=9 Win=5792 Len=0 TSV=3967138 TSER=1738471
^C10 packets captured

ちなみにtcpdumpの場合はこんな感じ。

# tcpdump -n -i br0 tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br0, link-type EN10MB (Ethernet), capture size 96 bytes
11:49:01.942466 IP 192.168.11.102.36673 > 192.168.11.241.80: S 3722872408:3722872408(0) win 5840 <mss 1460,sackOK,timestamp 1722908 0,nop,wscale 6>
11:49:01.943604 IP 192.168.11.241.80 > 192.168.11.102.36673: S 1321486056:1321486056(0) ack 3722872409 win 5792 <mss 1460,sackOK,timestamp 3811486 1722908,nop,wscale 4>
11:49:01.943673 IP 192.168.11.102.36673 > 192.168.11.241.80: . ack 1 win 92 <nop,nop,timestamp 1722909 3811486>
11:49:04.794205 IP 192.168.11.102.36673 > 192.168.11.241.80: P 1:8(7) ack 1 win 92 <nop,nop,timestamp 1723194 3811486>
11:49:04.795714 IP 192.168.11.241.80 > 192.168.11.102.36673: . ack 8 win 362 <nop,nop,timestamp 3814337 1723194>
11:49:04.795782 IP 192.168.11.241.80 > 192.168.11.102.36673: P 1:22(21) ack 8 win 362 <nop,nop,timestamp 3814338 1723194>
11:49:04.795818 IP 192.168.11.102.36673 > 192.168.11.241.80: . ack 22 win 92 <nop,nop,timestamp 1723194 3814338>
11:49:04.795838 IP 192.168.11.241.80 > 192.168.11.102.36673: F 22:22(0) ack 8 win 362 <nop,nop,timestamp 3814339 1723194>
11:49:04.796667 IP 192.168.11.102.36673 > 192.168.11.241.80: F 8:8(0) ack 23 win 92 <nop,nop,timestamp 1723194 3814339>
11:49:04.798567 IP 192.168.11.241.80 > 192.168.11.102.36673: . ack 9 win 362 <nop,nop,timestamp 3814341 1723194>
^C
10 packets captured
10 packets received by filter
0 packets dropped by kernel

2009-08-22

CentOS-Testingからkeepalivedを入れてVRRPの実験

インストール

# yum --enablerepo=c5-testing install keepalived

ファイアウォール設定

keepalivedを利用する際に気をつけておくこと - よかろうもん!を参考にしました。

iptables設定変更

# vi /etc/sysconfig/iptables

変更内容

--- /etc/sysconfig/iptables     2009/08/23 00:54:44     1.3
+++ /etc/sysconfig/iptables     2009/08/23 07:47:37
@@ -15,6 +15,7 @@
 -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
 -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
+-A RH-Firewall-1-INPUT -m state --state NEW -p 112 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

man iptablesして確認したところ、-pの後にしているのはプロトコル番号。/etc/protocolsに

vrrp    112     VRRP            # Virtual Router Redundancy Protocol

という行があるので112ではなくvrrpとも書けるが、他が数値での指定なので合わせた。ちなみにRFC3768によると使用するポート番号も112。

iptables再起動

# /etc/init.d/iptables restart

VRRPによる仮想IP設定

# vi /etc/keepalived/keepalived.conf

作成内容

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 200
    advert_int 1
    garp_master_delay 5
    virtual_ipaddress {
        192.168.11.240
    }
}

実IPアドレスが192.168.11.241, 192.168.11.242の2台で仮想IPアドレスが192.168.11.240という想定です。priorityはもう1台では100などと違う値にします。

RFC3768によるとAuthentication Type 1, Authentication Type 2はRFC2338との互換性のために残されているが使用されないとのこと。なので、Authentication Type 0つまり認証無しということでkeepalivedのauthentication {}の部分は指定しない。

keepalived起動およびサービス設定

# /etc/init.d/keepalived start
# chkconfig keepalived on

CentOSのyumレポジトリにCentOS-Testingを追加

AdditionalResources/Repositories - CentOS WikiのCentOS-Testingの項を読んで位置づけを理解した上で追加。

# cd /etc/yum.repos.d
# wget http://dev.centos.org/centos/5/CentOS-Testing.repo

priorityを追加しておく。

# vi CentOS-Testing.repo

変更内容

--- /etc/yum.repos.d/CentOS-Testing.repo        2009/08/22 08:43:19     1.1
+++ /etc/yum.repos.d/CentOS-Testing.repo        2009/08/22 08:43:31
@@ -4,6 +4,7 @@
 enabled=0
 gpgcheck=1
 gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
+priority=21
 
 # CentOS-Testing:
 # !!!! CAUTION !!!!

普段はenabled=0にしておいて、必要な際はyum実行時に--enablerepo=c5-testingをつけて使う。

試行錯誤でheartbeatを設定して動作確認するがうまくいかず

HAクラスタシステム構築(Heartbeat+DRBD) - CentOSで自宅サーバー構築を参考に/etc/ha.d/haresourcesという設定ファイルを作り、それを変換して/var/lib/heartbeat/crm/cib.xmlを作ってみた。Linux HAのharesources2cib.pyについての説明ページのConversion ExamplesのActive/Active Two IP address configurationの設定をまねて/etc/ha.d/haresourcesを作成。

# vi /etc/ha.d/haresources

作成内容

vm10 192.168.11.241
vm11 192.168.11.242

これを変換して/var/lib/heartbeat/crm/cib.xmlを作成。

# cd /var/lib/heartbeat/crm
# mv cib.xml cib.xml.orig
# /usr/lib/heartbeat/haresources2cib.py --stdout -c /etc/ha.d/ha.cf /etc/ha.d/haresources > cib.xml

vm10とvm11でheartbeat起動

# /etc/init.d/heartbeat start

crm_monでモニター

# /usr/sbin/crm_mon -i 3

しかし、vm10ではvm10しか一覧にしか出ないし、vm11ではvm11しか一覧に出ない。OFFLINEからonlineになるまでも数分ぐらいかかるし。なんだかよくわからないが、うまくいってないようだ。

とりあえず起動時に上げないようにしておく。

# chkconfig heartbeat off

EPELからheartbeatをインストール

インストール試すが依存関係で失敗

# yum install heartbeat

すると依存するlibnet.so.1が無いというエラー発生

Resolving Dependencies
--> Running transaction check
---> Package heartbeat.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: libstonith.so.1 for package: heartbeat
--> Processing Dependency: libpils.so.1 for package: heartbeat
--> Processing Dependency: libltdl.so.3 for package: heartbeat
--> Processing Dependency: libnet.so.1 for package: heartbeat
--> Running transaction check
---> Package libtool-ltdl.i386 0:1.5.22-6.1 set to be updated
---> Package heartbeat-stonith.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: net-snmp-libs for package: heartbeat-stonith
--> Processing Dependency: libnetsnmp.so.10 for package: heartbeat-stonith
---> Package heartbeat-pils.i386 0:2.1.4-9.el5 set to be updated
---> Package heartbeat.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: libnet.so.1 for package: heartbeat
--> Running transaction check
---> Package net-snmp-libs.i386 1:5.3.2.2-5.el5_3.2 set to be updated
---> Package heartbeat.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: libnet.so.1 for package: heartbeat
--> Finished Dependency Resolution
heartbeat-2.1.4-9.el5.i386 from epel has depsolving problems
  --> Missing Dependency: libnet.so.1 is needed by package heartbeat-2.1.4-9.el5.i386 (epel)
Error: Missing Dependency: libnet.so.1 is needed by package heartbeat-2.1.4-9.el5.i386 (epel)

libnet.soを求めて(失敗の巻)

libnet.soを含むパッケージを調べる。

# yum provides libnet.so
...(略)...
1463 packages excluded due to repository priority protections
1:java-1.6.0-openjdk-1.6.0.0-0.25.b09.el5.i386 : OpenJDK Runtime Environment
Matched from:
Other       : libnet.so



1:java-1.6.0-openjdk-1.6.0.0-0.30.b09.el5.i386 : OpenJDK Runtime Environment
Matched from:
Other       : libnet.so



1:java-1.6.0-openjdk-1.6.0.0-1.2.b09.el5.i386 : OpenJDK Runtime Environment
Matched from:
Other       : libnet.so

heartbeatがOpenJDKに依存しているってほんとかと思いつつ一応入れてみる。まずどこのレポジトリか確認。

# yum info java-1.6.0-openjdk

によるとupdatesレポジトリにあるらしい。

# yum install java-1.6.0-openjdk

libnet.soがインストールされたか確認

# rpm -ql java-1.6.0-openjdk | grep libnet
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/jre/lib/i386/libnet.so

ここに入るってことはOpenJDKしかみないよな。こんなとこにLD_LIBRARY_PATH通すとも思えないし。

yum install heartbeatを再度試すがやはり同じエラーが出ました。ということでOpenJDKを依存パッケージごとアンインストールします。

# yum remove java-1.6.0-openjdk giflib jpackage-utils libXtst

libnet.soを求めて(成功の巻)

libnetで検索してみる

# yum search libnet
...(略)...
=============================== Matched: libnet ================================
echoart.i386 : Responds to or drops ICMP echo requests packets
libnet.i386 : Routines to help with network packet contruction and handling
libnet-devel.i386 : Development files for the libnet library
libnet10.i386 : High-level API (toolkit) to construct and inject network packets
libnet10-devel.i386 : Development files for the libnet library
libnetfilter_conntrack.i386 : Netfilter conntrack userspace library
libnetfilter_conntrack-devel.i386 : Header files, libraries and development
                                  : documentation for libnetfilter_conntrack.
perl-Net-ARP.i386 : Create and send ARP packets
perl-Net-TFTP.noarch : TFTP Client class

libnetとかlibnet10がそれっぽい。

libnetを入れてみる

# yum install libnet

内容を確認

# rpm -ql libnet | lv

/usr/lib/libnet.aはあるが、libnet.soは確かに無い。

libnet10を入れてみる

# yum install libnet10

内容を確認

# rpm -ql libnet10 | lv

/usr/lib/libnet10.so.0というファイルならあったがlibnet.soはない。

libnetとlibnet10をアンインストール後、どのレポジトリか確認。

# yum remove libnet libnet10
# yum info libnet

extrasと判明。extrasからlibnet*を除外。

# vi /etc/yum.repos.d/Cent-Base.repo

変更内容

--- /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 15:08:54     1.4
+++ /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 15:22:08
@@ -48,7 +48,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
-exclude=heartbeat-*
+exclude=heartbeat-*,libnet*
 
 #additional packages that extend functionality of existing packages
 [centosplus]

再度確認

# yum info libnet

今度はrpmforgeでヒットしたので、ここからも除外

# vi /etc/yum.repos.d/rpmforge.repo

変更内容

--- /etc/yum.repos.d/rpmforge.repo      2009/08/21 09:09:14     1.2
+++ /etc/yum.repos.d/rpmforge.repo      2009/08/21 15:22:29
@@ -10,3 +10,4 @@
 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
 gpgcheck = 1
 priority = 11
+exclude=libnet*
# yum info libnet

これでRepo: epelになったので、インストール。

# yum install libnet
# rpm -ql libnet | lv

/usr/lib/libnet.so.1が含まれている事を確認。

heartbeatのインストール再実行して成功

# yum install heartbeat
...(略)...
Dependencies Resolved

================================================================================
 Package                Arch      Version                    Repository    Size
================================================================================
Installing:
 heartbeat              i386      2.1.4-9.el5                epel         1.6 M
Installing for dependencies:
 heartbeat-pils         i386      2.1.4-9.el5                epel          90 k
 heartbeat-stonith      i386      2.1.4-9.el5                epel         169 k
 libtool-ltdl           i386      1.5.22-6.1                 base          37 k
 net-snmp-libs          i386      1:5.3.2.2-5.el5_3.2        updates      1.2 M
...(略)...

今度は無事インストールできました。今回の教訓は先にexcludeを調整して希望のパッケージが希望のレポジトリから取得できるようにすることが大切ということです。

CentOSのyumレポジトリにEPELを追加

EPELを追加してみる理由

AdditionalResources/Repositories - CentOS WikiExtra Packages for Enterprise Linux (EPEL)というサードパーティレポジトリが紹介されていました。

CentOSでheartbeatを使おうとしたがうまくいかずでインストールしたheartbeatはyum info heartbeatで確認したところバージョンは2.1.3でextrasリポジトリからインストールされたもの。

一方、RepoView: "Fedora EPEL 5 - i386"ではheartbeat-2.1.4-9.el5.i386とこちらのほうが新しい。というわけで試してみることに。

まずextrasリポジトリから入れたheartbeatパッケージを削除

heartbeatを入れた際に同時に入れられたパッケージ名を確認

# yum list installed | grep heartbeat
heartbeat.i386                          2.1.3-3.el5.centos             installed
heartbeat-pils.i386                     2.1.3-3.el5.centos             installed
heartbeat-stonith.i386                  2.1.3-3.el5.centos             installed

アンインストール

# yum remove heartbeat heartbeat-pils heartbeat-stonith

EPELのセットアップ

AdditionalResources/Repositories - CentOS WikiのEPELのセクションに従ってセットアップ

EPELを有効にするためのrpmをインストール

$ wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
# rpm -ivh epel-release-5-3.noarch.rpm

EPELのpriorityを設定

# vi /etc/yum.repos.d/epel.repo

変更内容

--- epel.repo   2009/08/21 12:50:02     1.1
+++ epel.repo   2009/08/21 12:59:18
@@ -6,6 +6,7 @@
 enabled=1
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
+priority=12
 
 [epel-debuginfo]
 name=Extra Packages for Enterprise Linux 5 - $basearch - Debug

base, updates, addons, extrasからはheartbeat-*を除外

# vi /etc/yum.repos.d/CentOS-Base.repo

変更内容

--- CentOS-Base.repo    2009/08/21 08:56:14     1.3
+++ CentOS-Base.repo    2009/08/21 15:08:31
@@ -18,6 +18,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #released updates 
 [updates]
@@ -27,6 +28,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #packages used/produced in the build but not released
 [addons]
@@ -36,6 +38,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #additional packages that may be useful
 [extras]
@@ -45,6 +48,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #additional packages that extend functionality of existing packages
 [centosplus]

動作確認

# yum info heartbeat
...(略)...
Available Packages
Name       : heartbeat
Arch       : i386
Version    : 2.1.4
Release    : 9.el5
Size       : 1.6 M
Repo       : epel
Summary    : Heartbeat subsystem for High-Availability Linux
URL        : http://linux-ha.org/
License    : GPLv2 and LGPLv2+
...(略)...

epelのheartbeatを見つけられるようになりました。

2009-08-21

CentOSでheartbeatを使おうとしたがうまくいかず

2009-08-27追記: その後keepalivedに乗り換えました

CentOS-Testingからkeepalivedを入れてVRRPの実験に書きました。

選定理由

手元の本ではkeepalivedを使っていたので当初そちらにしようかと思いましたが、yum searchでは見つかりませんでした。調べてみると同等の機能としてheartbeatというパッケージがあるらしい。23. High Availability LVS: Failover protectionには以下のような説明がありました。

This is handled by having a redundant director available. Director failover is handled in the Ultra Monkey Project by heartbeat. Other code used for failover is vrrpd in keepalived.

Ultra Monkey Projectもyum searchでは見つからず、また調べてみるとheartbeat-ldirectordというパッケージで同等の機能が使えるっぽい。ということでこちらを試すことにしました。

セットアップ

以下のサイトを参考にしました。

$ sudo yum install ipvsadm heartbeat heartbeat-ldirectord

haclusterユーザが既に存在するという旨のエラーが出てheartbeatがインストールされないので、再度行う。

$ sudo yum install heartbeat

設定ファイル作成

/etc/ha.d/ha.cf

$ cd /etc/ha.d
$ sudo cp /usr/share/doc/heartbeat-2.1.3/ha.cf .
$ sudo vi ha.cf

変更内容

--- ha.cf       2009/08/21 10:57:54     1.1
+++ ha.cf       2009/08/21 11:42:22
@@ -49,7 +49,7 @@
 #
 #      keepalive: how long between heartbeats?
 #
-#keepalive 2
+keepalive 2
 #
 #      deadtime: how long-to-declare-host-dead?
 #
@@ -57,12 +57,12 @@
 #              split-brain (or cluster partition) problem.
 #              See the FAQ for how to use warntime to tune deadtime.
 #
-#deadtime 30
+deadtime 30
 #
 #      warntime: how long before issuing "late heartbeat" warning?
 #      See the FAQ for how to use warntime to tune deadtime.
 #
-#warntime 10
+warntime 10
 #
 #
 #      Very first dead time (initdead)
@@ -72,12 +72,12 @@
 #      we have a separate dead time for when things first come up.
 #      It should be at least twice the normal dead time.
 #
-#initdead 120
+initdead 120
 #
 #
 #      What UDP port to use for bcast/ucast communication?
 #
-#udpport       694
+udpport        694
 #
 #      Baud rate for serial ports...
 #
@@ -92,7 +92,7 @@
 #
 #      What interfaces to broadcast heartbeats over?
 #
-#bcast eth0            # Linux
+bcast  eth0            # Linux
 #bcast eth1 eth2       # Linux
 #bcast le0             # Solaris
 #bcast le1 le2         # Solaris
@@ -212,8 +212,8 @@
 #
 #      Tell what machines are in the cluster
 #      node    nodename ...    -- must match uname -n
-#node  ken3
-#node  kathy
+node   vm10
+#node  vm11
 #
 #      Less common options...
 #
@@ -255,6 +255,7 @@
 #
 #respawn userid /path/name/to/run
 #respawn hacluster /usr/lib/heartbeat/ipfail
+respawn root /usr/lib/heartbeat/pingd -m 100 -d 5s -a default_ping_set
 #
 #      Access control for client api
 #              default is no access
@@ -324,7 +325,7 @@
 #      more infomartion can be fould in http://www.linux-ha.org/ha_2ecf_2fUseLogdDirective
 #      Setting use_logd to "yes" is recommended
 #
-# use_logd yes/no
+use_logd yes
 #
 #      the interval we  reconnect to logging daemon if the previous connection failed
 #      default: 60 seconds
@@ -342,3 +343,5 @@
 #      will be compressed, the default is 2 (KB)
 #compression_threshold 2

+#      Enable cluster resource manager
+crm yes

なお、ja/pingd_ja: Linux HAによるとpingdはipfailにとって代わるコマンドらしい。

/etc/ha.d/logd.cf

$ sudo cp /usr/share/doc/heartbeat-2.1.3/logd.cf .
$ sudo vi logd.cf

変更内容

--- logd.cf     2009/08/21 11:45:09     1.1
+++ logd.cf     2009/08/21 11:45:46
@@ -1,18 +1,18 @@
 #      File to write debug messages to
 #      Default: /var/log/ha-debug
-#debugfile /var/log/ha-debug
+debugfile /var/log/ha-debug
 
 #
 #
 #      File to write other messages to
 #      Default: /var/log/ha-log
-#logfile       /var/log/ha-log
+logfile        /var/log/ha-log
 
 #
 #
 #      Facility to use for syslog()/logger 
 #      Default: daemon
-#logfacility   daemon
+logfacility    none
 
 
 #      Entity to be shown at beginning of a message

/etc/ha.d/authkeys

$ sudo cp /usr/share/doc/heartbeat-2.1.3/authkeys .
$ sudo chmod 600 /etc/ha.d/authkeys
$ sudo vi authkeys

変更内容

--- authkeys    2009/08/21 11:46:47     1.1
+++ authkeys    2009/08/21 11:47:40
@@ -20,7 +20,7 @@
 #      crc adds no security, except from packet corruption.
 #              Use only on physically secure networks.
 #
-#auth 1
-#1 crc
+auth 1
+1 crc
 #2 sha1 HI!
 #3 md5 Hello!

VMクローン

インストールや設定ファイルの変更をvm10と同様にvm11でも行うのは手間なので、vm10の1台でセットアップして、KVMのゲストOSイメージをコピーの手順でvm11を作り直しました。こっちのほうが楽です。

動作実験するも問題発生

サービス開始。2台で実行。

$ sudo /etc/init.d/heartbeat start

モニターしてみる。1台で実行。しかしエラー発生。

$ /usr/sbin/crm_mon -i 3
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode
Critical: Unable to connect to the CIB

調べてみると既知バグで0003226: heartbeat crm_mon not compiled with ncurses - CentOS Bug Trackerに登録されていました。

CentOSのyumレポジトリにrpmforgeを追加

yum-prioritiesを導入

AdditionalResources/Repositories/RPMForge - CentOS Wikiを参考にしました。

$ sudo yum install yum-priorities
$ sudo vi /etc/yum.repos.d/CentOS-Base.repo

変更内容

--- /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 08:48:25     1.1
+++ /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 08:56:14     1.3
@@ -17,6 +17,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #released updates
 [updates]
@@ -25,6 +26,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #packages used/produced in the build but not released
 [addons]
@@ -33,6 +35,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/addons/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #additional packages that may be useful
 [extras]
@@ -41,6 +44,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #additional packages that extend functionality of existing packages
 [centosplus]
@@ -50,6 +54,7 @@
 gpgcheck=1
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=2

 #contrib - packages by Centos Users
 [contrib]
@@ -59,3 +64,4 @@
 gpgcheck=1
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=2

rpmforgeのセットアップ

$ wget http://apt.sw.be/redhat/el5/en/i386/RPMS.dag/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
$ sudo rpm --import http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt
$ rpm -K rpmforge-release-0.3.6-1.el5.rf.i386.rpm 
$ sudo rpm -i rpmforge-release-0.3.6-1.el5.rf.i386.rpm
$ sudo vi /etc/yum.repos.d/rpmforge.repo

変更内容

--- /etc/yum.repos.d/rpmforge.repo      2009/08/21 09:08:58     1.1
+++ /etc/yum.repos.d/rpmforge.repo      2009/08/21 09:09:11
@@ -9,3 +9,4 @@
 protect = 0
 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
 gpgcheck = 1
+priority = 11

設定の確認

$ sudo yum check-update

rpmforgeの行が出ればOK。

virsh consoleを使うためにCentOSのシリアル端末を設定

CentOSのシリアル端末を設定

Setting up a serial console | HowtoForge - Linux Howtos and Tutorialsを参考にしました。

# vi /etc/inittab
S0:12345:respawn:/sbin/agetty ttyS0 115200 # この行を追加
1:2345:respawn:/sbin/mingetty tty1
# vi /etc/grub.conf
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1 # この行を追加
terminal --timeout=5 serial console # この行を追加
title CentOS (2.6.18-128.4.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-128.4.1.el5 ro root=/dev/VolGroup00/LogVol00 console=tty0 console=ttyS0,115200n8 # console以降を追加
        initrd /initrd-2.6.18-128.4.1.el5.img

再起動すればシリアル端末が使えるようになります。

virsh consoleからの利用手順

まずゲストOSを起動します。

$ sudo virsh start vm10

ゲストOSが事前に起動済みの状態で、シリアル端末に接続します。

$ sudo virsh console vm10

シリアル端末から切断する方法はわかりませんでした。screenを使っていれば、別端末に切り替えてvirshのPIDを調べてkillするか、端末を切り替えずにscreenのkillコマンドでウィンドウごとkillすることができます。screenってほんと便利ですね。

kenyaさんからのコメントでCtrl+](右角括弧)で抜けられることを教わりました。これは便利です。

2009-08-20

virt-cloneでゲストOSイメージをコピー

コピー実行

以下のコマンドで起動します。

$ sudo virt-clone --original vm10 --name vm11 --file vm11.qcow2 --mac 52:54:00:12:34:57

設定変更

その後vm11を起動してホスト名、MACアドレス、IPアドレスを変更します。

ホスト名変更

# vi /etc/sysconfig/network
HOSTNAME=vm11 # この行を修正

さらに今すぐ変更するためにコマンドも実行します。

# hostname vm11

一旦ログアウトしてログインし直すとプロンプトも変わりました。

MACアドレス、IPアドレスを変更

# service network stop
# cd /etc/sysconfig/network-scripts
# ls ifcfg-eth0*
ifcfg-eth0  ifcfg-eth0.bak
# rm ifcfg-eth0
# mv ifcfg-eth0.bak ifcfg-eth0
# vi ifcfg-eth0
HWADDR=52:54:00:12:34:57 # この行と
IPADDR=192.168.11.242    # この行を修正
# service network start

設定変更用のスクリプト

毎回手動で上記の設定変更を行うのも面倒なので、シェルスクリプトを書いてみました。ゲストOSに入れておきます。

#!/bin/bash
if [ $EUID -ne 0 ]; then
    echo "This script must be run by root." 1>&2
    exit 1
fi

if [ $# -ne 1 ]; then
    echo "Usage: chgvm hostname" 1>&2
    exit 1
fi

hostname=$1

case $hostname in
vm10)
    ipaddr=192.168.11.241
    macaddr=52:54:00:12:34:56
    ;;
vm11)
    ipaddr=192.168.11.242
    macaddr=52:54:00:12:34:57
    ;;
*)
    echo "Wrong hostname: $1" 1>&2
    exit 1
esac

hostname $hostname
sed -i -e "s/^HOSTNAME=.*/HOSTNAME=$hostname/" /etc/sysconfig/network

service network stop

cat > /etc/sysconfig/network-scripts/ifcfg-eth0 <<EOF
# Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+
DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
HWADDR=$macaddr
NETMASK=255.255.255.0
IPADDR=$ipaddr
GATEWAY=192.168.11.1
TYPE=Ethernet
EOF

service network start

上記のvirt-cloneでコピーした後、以下のようにして変更します。

host$ sudo virsh start vm11
host$ sudo virsh console vm11
# ここでrootでログインして上記のシェルスクリプトを実行

virt-cloneした後はネットワークの設定がvm10と同一になっているので、まずvm11だけを起動してsshではなくconsoleからログインして、上記のシェルスクリプトで設定を変えるという手順をとる必要があります。

既存のKVMのゲストOSイメージをlibvirtに登録

手順

既存のKVMのゲストOSイメージをlibvirtに登録するのは、通常の手順としては用意されていないそうです。インストールに見せかけて即座に失敗するがエントリは作られるという方法で実現します。

ここでも--os-variant=centos5を試してみたのですがやはりエラーになってしまいました。

$ sudo virt-install -n vm10 -r 512 --vcpus=1 -f vm10.qcow2 -s 12 \
> --os-type linux --accelerate --network=bridge:br0 --hvm -c /dev/null --nographics -m 52:54:00:12:34:56 --os-variant=centos5
ERROR    OS variant 'centos5; does not exist in our dictionary for OS type 'linux'
Traceback (most recent call last):
  File "/usr/bin/virt-install", line 709, in 
    main()
  File "/usr/bin/virt-install", line 590, in main
    guest.set_os_variant(options.os_variant)
  File "/usr/lib/python2.6/dist-packages/virtinst/Guest.py", line 683, in set_os_variant
    {'var' : val, 'ty' : self._os_type}
ValueError: OS variant 'centos5; does not exist in our dictionary for OS type 'linux'

--os-variantをつけずに実行するとOKでした。

$ sudo virt-install -n vm10 -r 512 --vcpus=1 -f vm10.qcow2 -s 12 \
> --os-type linux --accelerate --network=bridge:br0 --hvm -c /dev/null --nographics -m 52:54:00:12:34:56

ここで別の端末でpsでプロセスIDを調べてkill -9します。

$ sudo virsh
virsh # destroy vm10
virsh # quit

-mで指定するMACアドレスは、一旦VMを起動してifconfigで調べておいたものです。virt-installの前にはシャットダウンしておきます。

man virt-installによるとXenの場合'00:16:3e'で始まる必要があり、QEMUの場合'54:52:00''52:54:00'で始まる必要があるそうです(2011-11-25追記: MACアドレスの値が間違っていました。タイプではなくコピペすべき>自分。←実はマニュアルが修正されていたようです。Bug 620838 – mistype in virt-install manpage - 54:52 should be 52:54)。 -mを指定しないとvirt-installがランダムに生成した値になりました(確か'00:16:3e'で始まっていました)。

この後確認すると/etc/libvirt/qemu/vm10.xmlという設定ファイルが作られていました。

参考にしたページ

KVMのゲストOSのネットワークをブリッジにする

Networking - KVMを参考にしました。

sudo kvm -hda vm10.qcow2 -m 256 -curses -net nic,00:23:7d:29:e1:02 -net tap,script=/etc/kvm/kvm-ifup

メモ

  • 00:23:7d:29:e1:02はランダムなMACアドレスです。ifconfigで表示された他のアドレスを変更してでっちあげました。
  • tunctlは無くてもいけました。ちなみにuml-utilitiesパッケージに含まれているらしい。
$ sudo aptitude show uml-utilities
Package: uml-utilities
State: not installed
Version: 20070815-1.1ubuntu2
Priority: extra
Section: universe/otherosfs
Maintainer: Ubuntu MOTU Developers 
Uncompressed Size: 336k
Depends: adduser, libc6 (>= 2.4), libfuse2 (>= 2.6), libncurses5 (>= 5.6+20071006-3), libreadline5 (>= 5.2), lsb-base (>= 3.0-10)
Suggests: user-mode-linux
Description: User-mode Linux (utility programs)
 User-mode Linux is a port of the Linux kernel to its own system call interface.  It provides a kind of virtual machine, which runs
 Linux as a user process under another Linux kernel.  This is useful for kernel development, sandboxing, jailing, experimentation,
 and many other things. 
 
 This package contains userspace utilities for use with User-mode Linux, including uml_mconsole, uml_moo, uml_switch, uml_net and
 tunctl.

Ubuntuでネットワークブリッジを作成

KVM Networking - Community Ubuntu Documentationを参考にしました。

bridge-utilsパッケージをインストールします。

$ sudo aptitude install bridge-utils

/etc/network/interfacesを以下のように書き換えます。

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
  address 192.168.11.102
  netmask 255.255.255.0
  gateway 192.168.11.1
  bridge_ports eth0
  bridge_stp off
  bridge_fd 0
  bridge_maxwait 0

で以下のコマンドを実行します。

$ sudo /etc/init.d/networking restart

libvirt: Wiki: Networkingによると/etc/sysctl.confも変更するらしいです。

$ sudo vi /etc/sysctl.conf

追加内容

net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

以下のコマンドを実行して変更を反映。

$ sudo sysctl -p /etc/sysctl.conf

KVMでCentOSをテキストモードでインストールする

KVMのインストール

基本的にはKVM Installation - Community Ubuntu Documentationに従って実行しました。

$ sudo apt-get install kvm libvirt-bin python-vm-builder qemu bridge-utils
$ sudo adduser $USER libvirtd

ゲストOS環境作成

以下のページを参考にしました。

うまく行かなかった手順

$ sudo aptitude install python-virtinst
$ qemu-img create -f qcow2 vm10.qcow2 10G
$ sudo virt-install --connect qemu:///system -n vm10 -r 512 --vcpus=1 -f vm10.qcow2 -s 12 \
  -c CentOS-5.3-i386-bin-DVD.iso --vnc --noautoconsole --os-type linux \
  --accelerate --network=bridge:br0 --hvm

シングルコアなのでvcpusは1に。上記の2つめの記事に従って--os-variant=は指定しない(man virt-installを見ると--os-variant=centos5でよさそうなのだがやってみるとうまくいかない)。インストールは始まるが、途中で"800 x 600 Graphic mode"と表示されてしまいだめだった。

さらに--nographicsオプションをつけて実行してみたが、途中で行頭に?が表示された状態でにっちもさっちもいかなくなった。

Shadows of epiphany » Blog Archive » How to run KVM without Xというページも見つけたがこれは試していない。

うまく行った手順

ググってみるとvirt-installerは使わずに直接KVMを使えばいけるらしい。あと、qemuとkvmはコマンドレベルで互換性があり、qemuと書く代わりにkvmと書けば動くそうだ。試したらそのままいけました。QemuやKVMのドキュメントやmanを見て以下のようにした。

$ qemu-img create -f qcow2 vm10.qcow2 10G
$ sudo kvm -hda vm10.qcow2 -cdrom CentOS-5.3-i386-bin-DVD.iso -boot d -m 256 -curses

大切なのは最初に"640 x 480 Graphic mode"と表示された時。見えないがこのタイミングでCentOS5インストール - CentOSで自宅サーバー構築の1枚目のスクリーンショットの画面が表示されている。単に<ENTER>を押すとGUIインストールが始まってしまうので、linux text<ENTER>と入力すること。

試した環境

ハードウェア
HP ML115G5
CPU
AMD Athlon 1640B (2.7GHz、L2 512KB、45W、AM2)
RAM
8GB
ホストOS
Ubuntu 9.04 server i386
$ uname -a
Linux sunshine12 2.6.28-15-server #49-Ubuntu SMP Tue Aug 18 19:30:06 UTC 2009 i686 GNU/Linux
$ dpkg -l | egrep '(kvm|libvirt-bin|python-vm-builder|qemu|bridge-utils)'
ii  bridge-utils                              1.4-5                             Utilities for configuring the Linux Ethernet
ii  kvm                                       1:84+dfsg-0ubuntu12.3             Full virtualization on i386 and amd64 hardwa
ii  libvirt-bin                               0.6.1-0ubuntu5.1                  the programs for the libvirt library
ii  python-vm-builder                         0.10-0ubuntu2                     VM builder
ii  qemu                                      0.10.0-1ubuntu1                   fast processor emulator

2009-08-14

WebWorkerの実行速度測定実験

実行結果

Safari 4.0.3

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; ja-jp) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=3.805
worker result=4999999950000000, elapsed=3.781
worker result=4999999950000000, elapsed=3.78
elapsedAverage=3.789

Chromium 4.0.202.0 r23297

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.202.0 Safari/532.0
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=1.734
worker result=4999999950000000, elapsed=1.652
worker result=4999999950000000, elapsed=1.658
elapsedAverage=1.681

Chrome 3.0.198.1

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.198 Safari/532.0
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=1.735
worker result=4999999950000000, elapsed=1.655
worker result=4999999950000000, elapsed=1.654
elapsedAverage=1.681

Firefox 3.5.2

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ja-JP-mac; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=0.589
worker result=4999999950000000, elapsed=0.439
worker result=4999999950000000, elapsed=0.438
elapsedAverage=0.489

動作環境

機種 ID
MacBook5,1
プロセッサ名
Intel Core 2 Duo
プロセッサ速度
2 GHz

ソース

  • sum.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Web worker sample</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="stopwatch.js"></script>
    <script type="text/javascript">
    $(function() {
      var worker = new Worker("sum.js"),
        n = 100000000,
        tryCount = 3,
        tryIndex = 0,
        stopwatch = new Stopwatch();
     
      function log(message) {
        $('#result').append(message + '<br>');
      }
      log('userAgent=' + navigator.userAgent);
      log('Start testing workers for ' + tryCount + ' times. n=' + n);
      
      worker.onmessage = function(event) {
        stopwatch.stop(); 
        log('worker result=' + event.data + ', elapsed=' + stopwatch.elapsedTime());
        if (++tryIndex < tryCount) {
          startTry();
        }
        else {
          log('elapsedAverage=' + stopwatch.elapsedTimeAverage().toFixed(3));
        }
      }
      worker.onerror = function(event) {
        log("worker error: " + event.data);
      }
    
      function startTry() {
        stopwatch.start();
        worker.postMessage('' + n);
      }
      startTry();
    });
    </script>
    </head>
    <body>
    <div id="result"></div>
    </body>
    </html>
    
  • sum.js
    onmessage = function(event) {
      var n = parseInt(event.data);
      var sum = 0;
      for (var i = 0; i < n; i++) {
        sum += i; 
      }
      postMessage('' + sum);
    }
    
  • stopwatch.js
    function Stopwatch() {
      this.elapsedTimes = [];
    } 
      
    Stopwatch.prototype.start = function() {
      this.startTime = new Date();
    } 
    
    Stopwatch.prototype.stop = function() {
      this.stopTime = new Date();
      var time = (this.stopTime.getTime() - this.startTime.getTime()) / 1000;
      this.elapsedTimes.push(time);
    }
    
    Stopwatch.prototype.elapsedTime = function() {
      return this.elapsedTimes[this.elapsedTimes.length - 1];
    }
    
    Stopwatch.prototype.elapsedTimeAverage = function() {
      var n = this.elapsedTimes.length,
        total = 0;
      for (var i = 0; i < n; i++) {
        total += this.elapsedTimes[i];
      }
      return total / n;
    }
    

ブログ アーカイブ