Browse Month: August 2009

仮想化についての雑感

現在、サーバを仮想化 (Virtualization) して運用することがあたりまえになっている。個人的には、VMWare ESXi、業務では Xen、を導入しているので、仮想化することのメリットとデメリットをまとめてみる。

メリット

  • 仮想マシンごとに一つの役割だけをあたえることで、個別サーバの設定が単純になる
  • 普通は同じサーバに同居できないようなソフトウェアを、それぞれ仮想マシンにすることで物理的には一台に済む_(実際には、MySQL で同じデータベース名で異なるデータを格納している場合に仮想化を行っているが、4Gbps 本に mysqld-safe を使う方法がのっていたのでこちらの方がよいかも)
  • 仮想マシンの OS ごと含めた設定をまるごろコピーして他の物理サーバへ展開できる(いわゆるライブマイグレーション、使ったことはない)
  • 消費リソースが異なるサーバをうまく組み合わせて仮想化することで、物理サーバを少なくすることができる(空きラックが増えたり、消費電力が少なくすむ)

デメリット

  • 物理サーバでサービスするよりも、各種リソースのパフォーマンスが下がる(実際には使いきれないことが多いので、特に問題にならない)
  • Xen の場合、Dom0 の物理メモリ(512MB)、物理ハードディスク(10GB)、が必要になってしまう
  • Xen の場合、Dom0 のファイルシステムなどがクラッシュすると、その上にある DomU がダメになる(先日、初めて体験して大変なことになった)
  • Xen の場合、DomU から Dom0 の情報へアクセスできないので、モニタリングツールなどで管理しにくい傾向になる(今のところ、オープンソースでサポートしているモニタリングツールはなさそうなので、既存のモニタリングツールを改良するか自作するしかないと思う)。
  • 仮想化を前提としたハードウェアが必要なので、すこし高めのサーバになり初期コストが若干かかる(それほど大きくは変わらないが)

と考えてみると、仮想化するデメリットよりもメリットのほうが大きいと思って、現在はほとんどのサーバを仮想化している。

ただし、なんでも仮想化すればよいというものでなく、次のことを考える必要がある。

  • 物理サーバ上に一つの仮想マシンなら物理サーバが、そのままサービスを提供したほうがよい(あたりまえか)
  • サービスによっては、サービスに特化した物理サーバを用意することで初期コストを下げられる(例えば、LVS は安いマシンで十分とか、データベースは高速なディスクのものにするなど)
  • 仮想化したとき、どの程度リソースのパフォーマンスが下がるのか知っておく必要がある
  • 現在、必要なサービスが仮想化を導入することで、デメリットよりメリットの方がうわまっているか考える必要がある

と、このあたりのことを改めて考えて、今のところ次のような方針で仮想化を導入している。

  • LVS/マスターDB/Memcached/バッチ系などのサーバは、なるべく小さな単位にして仮想化する、例えば LVS は外側用のものと内側用のものは別々の仮想化している
  • Slave DB は、パフォーマンス重視(特にディスク I/O)のため仮想化しない
  • CPU とメモリの両方をたくさん使っているウェブサーバ(with Passenger なので、1台でなるべく多く捌きたい)は仮想化しない

現在はこんな方針でやっているが、そろそろ非同期処理系のクラスタマシン(Hadoop)が必要になってきたので、既存の物理サーバを最大限に使いつつ、新しい組み合わせを考える必要が出てきている。CentOS の場合、安定性の面、導入の容易さから、Xen を使うのが一番よいかなと思っているが、次の点を問題意識としてもっている。

  • Dom0 なしでできない(完全仮想化でできる?)
  • CentOS の Xen はもうサポートされないっぽい(RedHat は KVM サポートを発表したので)ので自分でサポートすることになりそう(例えば、新しいバージョンを使いたいなど)
  • 最近の 1U サーバは内蔵の起動可能な USB ポートをもっているが USB メモリとかでブートして、ハードディスクは DomU 専用にすることは可能?
  • Xen 以外の選択肢

まだまだ始めたばかりの仮想化なので、いろいろと試していきたい。

Smartd からエラーが届いた

Smartd から、次のようなメールが届いた。タイトルは、SMART error (CurrentPendingSector) detected on host: s1.example.com になっている。

This email was generated by the smartd daemon running on:

host name: s1.example.com
DNS domain: example.com
NIS domain: (none)

The following warning/error was logged by the smartd daemon:

Device: /dev/sda, 8 Currently unreadable (pending) sectors

For details see host’s SYSLOG (default: /var/log/messages).

You can also use the smartctl utility for further investigation.
No additional email messages about this problem will be sent.

ということで、該当のサーバの /vr/log/message を見てみた。どうすると、次のようなログが 30 分おきに出力されていた。

Aug  7 16:36:39 s4 smartd[30746]: Device: /dev/sda, 8 Currently unreadable (pending) sectors
Aug  7 16:36:39 s4 smartd[30746]: Device: /dev/sda, 8 Offline uncorrectable sectors

エラーの意味が分からなかったので調査したところ、どうやら不良セクタがあるっぽいが、修復することは可能なようだ。

まず、現状を調査する。

$ sudo smartctl -l selftest /dev/sda
smartctl version 5.38 [x86_64-redhat-linux-gnu] Copyright (C) 2002-8 Bruce Allen
Home page is http://smartmontools.sourceforge.net/

=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num  Test_Description               Status                          Remaining  LifeTime(hours)  LBA_of_first_error
# 1      Extended offline      Completed: read failure            90%              1189                             159802

159802 というが読み取り不要なセクタ番号のようだ。

このセクタがどのパーティションにあるか調査してみる。

$  sudo fdisk -lu /dev/sda

Disk /dev/sda: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders, total 1953525168 sectors
Units = sectors of 1 * 512 = 512 bytes

Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63      208844      104391   83  Linux
/dev/sda2          208845  1953520064   976655610   8e  Linux LVM

うーむ、どうやら boot パーティションにあるようだ。

再セットアップしても不良セクタがある以上はなんだか不安なので、手っ取り早くハードディスクを交換することした。

# ちなみに、このディスクは先日の ST31000340NS だった。ファームウェアアップデートしたのに、結局2台ともダメだった。仕方がないので処分しよう。

# 2009.09.03 追記:

kensugiさんからいただいたコメントで調査してみたところ、保証期限内であれば無料で交換してくれることにだったので、サポートセンターから登録して故障したハードディスクを送付してみた。そうしたら、1週間弱ほどで新しいハードディスクが届いた。ちなみに、故障したハードディスクを送付する前に 1TB を DBAN でフォーマットしてみたのですが約1日かかって驚いた。

kensugiさん、コメントありがとうございました!

iTunes スマートプレイリスト Tips

iTunes のスマートプレイリストは、とても便利でいつも使っています。スマートリストのよいところは、動的なプレイリストを作成できるところにあるのですが、アルバムやアーティストの名前から簡単にプレイリストを作ることができます。

スマートプレイリストを使って、あるアルバムの動画と音楽をそれぞれのプレイリストにわけたいと思って、いろいろ試行錯誤した結果、ファイルの種類を設定することができるので、これを使うと動画と音楽をわけてスマートプレイリストを作成することができます。

例えば、音楽の場合は kind に「MPEG audio File」というフィルターを追加します。

itunes

同様に音楽の場合は、kind に「MPEG-4 video file」というフィルターを追加します。

てっきり、iTunes なので簡単に音楽/動画用のプレイリストを作成できる思ったらこのようにコツがあるので、必要な方は使ってみてください。

Apache の mod_asis モジュール

Apache のモジュールに、mod_asis というモジュールがあります。このモジュールを使うと、静的ファイルに HTTP の応答ヘッダーの情報を含ませることができます。

このモジュールを使うと、例えば GIF ウェブビーコンファイルを配信するときにキャッシュさせないように HTTP の応答ヘッダーの情報を含ませて配信することができます。プログラムを通さずに、静的ファイルな配信となるところがよいです。

まず、mod_asis はデフォルトでは読み込まれていないので、次のように LoadModule でモジュールを読み込みます。下記は、64 ビット OS の場合です。

LoadModule asis_module /usr/lib64/httpd/modules/mod_asis.so

次に VirtualHost の中などで、mod_asis のハンドラを設定します。

AddHandler send-as-is asis

これで、asis という拡張子のファイルが mod_asis の対象になります。

あとは、asis ファイルを作成して DocumentRoot 以下に配置するだけです。次のようなテキストファイルと対象の GIF を cat コマンドで結合するだけです。

Status: 200 OK
Content-Type: image/gif
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache

HTTP の応答ヘッダーなので、最後に1行空行を追加するのを忘れないでください。

作成した GIF の asis ファイルは、次のようになります。

Status: 200 OK
Content-Type: image/gif
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache

GIF89 …<GIF のバイナリデータ>

あとは、curl –head などで、対象の GIF ファイルにアクセスしてみて、設定した応答ヘッダーを返しているかチェックして完了です。

例えば、メンテナンス中に、さきほど作成した画像を表示するには、次のように mod_rewrite を設定します。

AddHandler send-as-is asis

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/maintenance.html -f
RewriteRule ^(.*)$ /images/maintenance.gif.asis [NC,L]

ある HTTP 応答ヘッダーを返したいとき、プログラムを通さずにできるので重宝しそうな Apache モジュールです。

irqbalance が動かない

CentOS 5.3 x86_64 で、CPU が「Intel(R) Core(TM)2 Duo CPU     E7300  @ 2.66GHz」の環境で irqbalance を動かすと 10 秒くらいたったところで irqbalance のプロセスが終了してしまう。/var/log/messages にも何もログが出ないので原因不明。CPU のコア数が 2 以上だとサポートしているという理解をしていたんだけれど、間違っているのか。

$ cat /proc/interrupts
CPU0       CPU1
0: 3379916376          0    IO-APIC-edge  timer
1:          3          0    IO-APIC-edge  i8042
3:        296         57    IO-APIC-edge  serial
4:         31          0    IO-APIC-edge  serial
8:          1          0    IO-APIC-edge  rtc
9:          0          0   IO-APIC-level  acpi
12:          4          0    IO-APIC-edge  i8042
50:          0          0   IO-APIC-level  uhci_hcd:usb3
58:      15498    3422477   IO-APIC-level  ata_piix
66:     128442   56775151   IO-APIC-level  pata_sil680
74:        130  897873434         PCI-MSI  eth0
82:   11844282  355505890         PCI-MSI  eth1
233:         70          7   IO-APIC-level  ehci_hcd:usb1, uhci_hcd:usb2, uhci_hcd:usb4
NMI:      72279     118026
LOC: 3379915045 3379885383
ERR:          0
MIS:          0

/etc/sysconfig/irqbalance は特に何も設定していない。Xeon なサーバは、ちゃんと irqbalnace が動いている。

irqbalance が動作しているかどうかは、次のコマンドでそれぞれ確認した。

$ sudo /etc/init.d/irqbalance status

$ ps aux | grep irqbalance

参考資料:

64bit かどうか判定する方法

32bit あるいは 64bit かどうかを判定する方法は、たくさんありますが、とてもシンプルな判定方法を見つけたので紹介します。

次のコマンドを実行するだけです。

$ getconf LONG_BIT

64

CentOS と FreeBSD で確認しました。シンプルでいいですね!

Scribd での Squid によるキャッシング方法

Alexey Kovyrin’s BlogScribd での Squid によるキャッシング方法が紹介されていました。

かなり興味深い記事だったので、日本語で要約としてまとめておきます。このエントリでは、ハードウェア設定、ソフトウェア設定、キャッシングクラスター設定、の3つの章から説明されています。

ハードウェア設定

次のようなハードウェア仕様のサーバを使っています。

CPU: Xeon 5418 x 1(CPU 使用率平均は 1% 以下なので安い CPU を使っているとのことです)
RAM: 8GB
Disk: SAS 15000回転 x 4 で、JBOD(RAID 未使用、すべての RAID のタイプを試してみたが、I/O パフォーマンスを改善する助けになるものはなかった)

高回転型のディスクを使っていて、JBOD にしているところが興味深いです。CPU の負荷グラフも公開されています。

ソフトウェア設定

さまざまな Squid のバージョンを試したようです。最終的には、独自のビルドをした Squid 2.7 STABLE 6 を使っているとのことです。

それまでの過程は、次のようになっています。

最初は、Debin の apt-get コマンドでインストールできる Squid を使った。Squid 2.6 リリースでは I/O 操作が遅く、ファイルディスクプリタがリークする問題があったそうです。Squid 3.0 リリースまで待ちたかったが正式版のリリースに約5ヶ月ほどかかりそうという結論したそうです。

次に Squid 2.7 リリースを試してみたとのことです。2.7 リリースでは、Vary HTTP ヘッダによるキャッシングが改善に実装されている唯一のバージョンだそうです。3.0 でも同様の機能があるようですが、C++ へ以降されているようです。

キャッシングクラスター設定

ロードバランサーは HAProxy、ウェブサーバは Nginx を使っているようです。HAProxy と Nginx との間に Squid を挟んで URL ハッシュベースによる負荷分散をセットアップしているとのことです。
この方法で、とてもよく動いているとのことですが、一つだけ深刻な問題点があるとのことです。それは、もし一つの Squid サーバが落ちると HAProxy はすぐに問題を検出して、プールから落ちた Squid サーバを外します。そしてここで問題が起きるようです。それはプールからサーバを外すときハッシュされているキー空間が完全に変わってしまって、すべてのキャッシュされているリクエストが無効になってしまうとのことです。この問題を解決するために、 URL をハッシュする Nginx モジュールを開発して、現在は本番環境へ投入されているようです。(この Nginx モジュールは公開されていないようで残念です。)

かなり要約しましたが、Scribd は Rails で動いている大規模サイト(Alexa ランキング第2位)なので、こういう大規模サイトの情報はとても貴重です。先日の Velocity でも HAProxy はロードバランサーとして LVS よりも人気があったので HAProxy もどんなものか試してみたいと思いましたし、Squid もサーバインフラ本で読んだだけなので Varnish とあわせて試してみたいと思います。

僕はセンスがないせいか、実際に試してみないとどんな問題を解決するツールなのかほとんど理解できないので悔しいところです。

iptables の ip_conntrack の最大値を変更する方法

iptables を使っているとき、接続数が増えてくると /var/log/messages に次のようなエラーが表示されることがあります。

Aug  2 23:44:44 s13 kernel: ip_conntrack: table full, dropping packet.
Aug  2 23:44:51 s13 last message repeated 10 times
Aug  2 23:45:40 s13 kernel: printk: 2 messages suppressed.

このエラーメッセージの意味は iptables の ip_conntrack という接続テーブルが一杯になってパケットが破棄されたという意味です。詳しいことは、「中〜大規模サーバーを運用するときの勘所 – iptablesとip_conntrack」に解説されています。

まず、現在の ip_conntrack の最大値を確認するには、次のコマンドで確認します。

$ cat /proc/sys/net/ipv4/ip_conntrack_max
65535

どうやら、8GB メモリのマシンでも 65535 に設定されるようです。

次に、現在の ip_conntrack の数を確認するには、次のコマンドで確認します。

$ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count
53663

netfilter の FAQ をみると、ip_conntrack の 1 コネクションあたり 350 バイトのメモリを必要とのことです。 また、64MB なら 4096 個ということで、搭載物理メモリ容量 8GB で計算して 524288 に設定してみることにしました。

ip_conntrack の最大値を変更するには、/etc/sysctl.conf に次の内容を追記します。

# Maximum number of conntrack
net.ipv4.netfilter.ip_conntrack_max = 524288

あとは、この設定を有効にするために、次のコマンドを実行します。

$ sudo sysctl -p

念のため、 /proc/sys/net/ipv4/ip_conntrack_max を確認しておきます。

これで一晩様子を見ましたが、特にエラーメッセージもメモリ不足にもなっていないようなので問題がなくなりました。

iptables の ip_conntrack サイズは、現代のサーバマシンにとってかなり低いのでロードバランサーなどトラフィックが集中するサーバには忘れずに設定しておきたいものです。

ワンライナー Tips

シェル上で、ある値を加算してループしたいとき、いままで expr で頑張っていたけれど、seq というとても便利なコマンドがあることを知った。

例えば、次のようにすると、1 から 31 まで表示することができる。

$ for i in `seq 1 1 31`; do echo $i; done;

1

2

31

ワンライナーで実行するときには、とても便利なコマンドだと思う。

NIC の DHCP 設定を解除する方法

CentOS で NIC の DHCP 設定を解除するときは、/etc/sysconfig/network-scripts/ifcfg-ethX のファイルを変更してから、network サービスを再起動するのが普通です。しかし、本番サービス稼働中のサーバでどうしても network サービスを再起動したくなかったので、そのときの DHCP 設定を解除するのかまとめてみます。

これから説明するのは、すべて eth1 の NIC の場合の設定例です。

まず、DHCP クライアントが起動しているので、DHCP クライアントを強制終了します。

$ sudo kill `cat /var/run/dhclient-eth1.pid`
$ sudo rm -f /var/run/dhclient-eth1.pid

次に、DHCP で割り当てられた eht1 の IP アドレスをリセットします。リセットしたあと、念のため IP アドレスが割り当てられていないことを確認する。

$ sudo ifconfig eth1 0.0.0.0
$ ifconfig eth1

そして、ip コマンドで DHCP 設定を解除します。

$ sudo ip link set eth1 dynamic off

あとは、サーバが再起動しても大丈夫なように /etc/sysconfig/network-scripts/ifcfg-ethX のファイルを、次のように忘れずに設定します。

DEVICE=eth1
BOOTPROTO=none
HWADDR=xx:xx:xx:xx:xx:xx
ONBOOT=no