Archive for November, 2009
lsコマンドのあまり使わないオプション
多くの人はlsを叩くときに定説となっているオプションがあると思います。
ls -lとか、
ls -aとか、
ls -laとか、はたまたそもそも、
llとか。僕は大抵このあたりで収まっている小市民です。
惰性で生きているとあまりman lsとかする機会がないのですが、今日たまたま必要に迫られてman lsしました。
やりたかったのは、シンボリックリンクから何らかオリジナルファイルの情報を得る、というものです。単純に考えるとls -lして一番右のカラム(オリジナルファイルへのパス)をcutとかawkとかで引っこ抜けばいいのですが、なんとなく納得いかなかったので少し調べました。すると、シンボリックリンクをlsしたときにオリジナルファイルの情報を返す-Lオプションを発見。例えば、通常-iオプションはinodeを表示します。シンボリックリンクのinodeはオリジナルのファイルのinodeを共有しているわけではなく、それぞれがユニークなinodeを持っています。なので通常、
ls -i [シンボリックリンク]
するとそのシンボリックリンクのinodeが表示されますが、
ls -iL [シンボリックリンク]
すると、そのシンボリックリンクが指し示すファイルのinodeを表示してくれます。
用例がないと何に使えるのかサッパリですが、とりあえず今書いているツールには使えそうなオプションなので自己満足的に紹介してみました。
VMテンプレートのディスクサイズを変更(拡張)する方法
Oracle VMのVMテンプレートは小さなサイズで作成されています。Oracle Enterprise Linux 5 update 3のテンプレートで言えば、容量は4GByte程になっています。これは後から簡単に仮想ディスクを追加できるという理由と、逆に最初に大きなサイズで作ると小さくするのは厄介という理由からです。大きくするのはそれほど難しい作業ではありません。
今回は仮想ディスクを追加するのではなく、元々のディスクサイズを拡張させる方法を紹介します。Oracle Enterprise Linux 5 update 3のテンプレートを例に話を進めていきます。
*Oracle Enterprise Linux 5 update 3のVMテンプレートはこちらからダウンロードできます。
http://edelivery.oracle.com/oraclevm
まずはOracle Enterprise Linux 5 update 3のテンプレートをダウンロードし、VM Serverの/OVS/seed_pool以下に保存します。そして解凍、展開します。
[root@vmserver]# cd /OVS/seed_pool/ [root@vmserver]# tar xvfz OVM_EL5U3_X86_64_PVM_4GB.tgz
次に展開したディレクトリの中にある仮想ディスクファイルのサイズをddコマンドで変更します。今回はディスクサイズを20Gbyteに伸ばしています。
[root@vmserver]# cd OVM_EL5U3_X86_64_PVM_4GB/ [root@vmserver]# ls README System.img vm.cfg [root@vmserver]# dd if=/dev/zero of=System.img bs=1M count=0 seek=20000
*Oracle VM 2.2からSparse Fileをサポートしているのでこのddコマンドは一瞬で終了し、拡張分の容量はSparse形式で追加されます。
次に設定ファイルを編集してvfbの行をコメントアウトします。これはxmコマンドから簡単にゲストOSのコンソールに接続するためです。
[root@vmserver]# vi vm.cfg
bootloader = '/usr/bin/pygrub'
disk = ['file:/OVS/seed_pool/OVM_EL5U3_X86_64_PVM_4GB/System.img,xvda,w']
memory = '1024'
name = 'OVM_EL5U3_X86_64_PVM_4GB'
on_crash = 'restart'
on_reboot = 'restart'
vcpus = 1
#vfb = ['type=vnc,vncunused=1,vnclisten=0.0.0.0']
vif = ['']
編集が終わったらゲストOSを起動します。-cスイッチを付けることで起動と同時にゲストOSのコンソールに接続できます。
[root@vmserver]# xm create -c vm.cfg
ここからの手順は設定の様子を動画を交えてご覧ください。
起動してきたゲストOSでは新しいパーティションテーブルが有効になっていますが、まだdfコマンドでみてもファイルシステムは大きくなっていません。現時点ではパーティションは拡大したものの、その上のファイルシステムが従来の状態のままになっているため、ファイルシステムをパーティションのサイズに合わせる必要があります。これをresize2fsコマンドで行います。
これで/(ルート)領域のファイルシステムが拡張されました。後、現在swap領域が無効になってしまっています。従来の領域はパーティションのレイアウト変更で消失してしまっているからです。新たに作成した/dev/xvda3をswapとして指定します。
mkswapでswap領域を作成し、swaponで有効化する
これでswap領域も新しいパーティションレイアウトに沿って有効になりました。あとは再起動後もswapが有効になるようにfstabを編集しておきます。
[root@guest]# oraclevm-template --cleanup [root@guest]# oraclevm-template --enable
Deduplication, 圧縮, スナップショットはどう違うのか?
前のエントリで予告したDeduplication, 圧縮, スナップショットの違いについて簡潔にまとめておきます。
Deduplicationと圧縮
例えば10Gbyteの仮想マシンイメージをgzipのようなアルゴリズムで圧縮した場合、10Gbyteのイメージにどれだけ空きスペースが含まれているかによりますが、もし空きスペースがほとんどなければあまり大きな圧縮効果は望めないでしょう。逆にもし10Gbyte中の4Gbyteが空きスペースであったなら、その部分はほとんど圧縮されるので最悪でも6Gbyte程度までは圧縮できるでしょう。ただしこの仮想マシンを10個クローンしたらどうでしょうか。ストレージは6Gbyte x 10 = 60Gbyteの容量を消費してしまいます。実際は同じデータであるにも関わらず、です。このストレージでDeduplication(重複排除)が有効であればどうでしょうか。10Gbyteの仮想マシンイメージを10個作成しても消費する容量は10Gbyteです。先ほどのgzip圧縮と比較するとトータルでこ重複排除の方が容量を節約できています。
ただしここで注意したいのはケースバイケースだということです。前述の仮想マシンイメージのような例は、特にDeduplicationが効果を発揮する環境です。Jeff Bonwick氏も自身のBlogエントリで度々仮想マシンイメージの例を引き合いに出しています。
そしてDeduplicationと圧縮は排他的な関係ではありません。補完し得る関係です。前述のシチューエーションをそれぞれのパターンでまとめてみます。
命題:10Gbyte (空き容量4Gbyte)の仮想マシンイメージを10個クローンする
gzip圧縮のみ
10Gbyteを圧縮して6Gbyteに。6Gbyteを10個クローンして最終的に60Gbyte消費
Deduplicationのみ
10Gbyteを10個クローンするが、10個のクローンはすべてのブロックが一致するはずなので新しいデータ領域は確保されない。最終的に10Gbyte消費
gzip圧縮 + Deduplication
まず10Gbyteを圧縮して6Gbyteに。それを10個クローンするがすべてのブロックが一致するはずなので新しいデータ領域は確保されない。最終的に6Gbyte消費
実際にテストしていませんが、理論的には上記のようになり得ます。要件によっては圧縮とDeduplicationを組み合わせたら最もディスク領域を節約できるケースがあることがわかります。
Deduplicationとスナップショット
Deduplicationとスナップショットは非常に近しい技術だと思います。どちらのコンセプトも「重複するデータの実体は一つしか保持しない」がベースになっています。僕は大きな違いは次の2点だと思っています。
主従関係
スナップショットでは主従関係が存在します。ほとんどのスナップショットの実装ではマスターのイメージがあり、スナップショットとはそのイメージのスレーブとして作成されます。なのでマスターとスレーブは対等な関係ではありません。スレーブは維持するけれどもマスターを削除する、という操作は行うことができません。ZFSのスナップショットでも同様です。
*ZFSでマスターを削除するにはマスターとスレーブの主従関係を逆転させるという選択肢はあります
これはDeduplicationの仕様とは明らかにことなります。前述の仮想マシンイメージの例で言えば、Deduplicationを使って10個の仮想マシンをクローンしてもそのオリジナルとクローンとの間には主従関係はありません。あるのはディスクに格納されているブロックの実体と、それを参照しているカウンタです。どの仮想マシンを削除するのも自由です。例えば大本の仮想マシンイメージを削除するにしてもそのブロックへの参照カウンタが一つ減るだけでスナップショットのように依存関係には縛られません。
コピー速度
ほとんどの実装においてスナップショットの作成は一瞬です。オリジナルイメージのスキャンが行われることもなければ新たなブロックが確保されてデータがコピーされることもありません。これはそもそもストレージ(あるいはボリュームマネージャ)にコピーではなくスナップショットという命令が明示されているからロジックを分けることができます。これはDeduplicationとは異なります。Decuplicationではコピー(あるいはクローン)する際、ユーザからの特別な命令はありません。通常通りファイルのコピーが命ぜられ、ストレージ側は粛々とファイルの構成要素となっているブロックについて一つ一つハッシュをチェックし、重複判定を行って重複していればデータのコピーは行わず参照カウンタをインクリメントして次のブロックに処理を移します。なのでスナップショットのようにどれだけコピー元のサイズが大きくても一瞬で処理を完了させれるような仕組みではなく、サイズが大きければ大きい程、例えば最終的にデータは複製しないにしろ、コピー処理には時間がかかるのが道理です。
ということでそれぞれの技術には得意不得意があり、ケースバイケースで適切な技術を選ぶ必要があると考えられます。
僕が開発しているovmzfsというツールの現在の仕様は、ZFSのスナップショット/クローンを使用して仮想マシンを高速に作成し、圧縮を使用してテンプレートのサイズ削減を行っています。これは検証環境では作業の高速化とストレージリソースの削減に大きく寄与しますが、今回Deduplicationが出てきたことで実装を少し見直さなければと思っています。現在の仕様では仮想マシンはテンプレートをスナップショット/クローンすることで作成しているため、高速に作成できるものの元のテンプレートと依存関係が発生します。すぐに問題とはなりませんが、より複雑な運用、大規模な環境ではもしかすると問題がでてくる可能性もなきにしもあらずです。まだDeduplicationを含むベストプラクティスを確立するには至っていませんが、最終的には適材適所でZFSのDeduplication、圧縮、スナップショットを採用してユーザからは透過的にストレージを最適に利用するツールにできればと思っています。
ZFSのDeduplication実装について
ZFSのリードデベロッパー、Jeff Bonwick氏は11月2日に投稿した「ZFS Deduplication」のBlogエントリでZFSに重複排除機能を実装したことをアナウンスしました。重複排除はストレージ界隈では熱い注目を集めている機能で、オープンソースであるZFSがそれを搭載したということで多くのエンジニアの好奇心を刺激しています。重複排除技術に関しては最近ではNetAppとEMCが、DataDomainという重複排除機能をウリにしたストレージを販売する会社の買収合戦を繰り広げたことが記憶に新しいところです。
ということで各ストレージベンダーはこの技術を自社製品に実装し、差別化を計ることに躍起になっていると見受けられます。
ほとんどBonwick氏のBlogエントリの訳みたいになってしまいますが、このZFSの重複排除機能について少し私見を交えてまとめておきます。まず、ZFSの重複排除実装について重要な仕様を2つ列挙しておきます。
- 重複判定単位:ブロックレベル
- 重複判定時期:リアルタイム
この2点について以下で論じていきます。
この重複排除技術、何がいいのかというとつまるところ必要なストレージ容量を削減できる、という点です。例えばあるファイルの容量が100Mbyteであったとるすると、そのファイルを2つ格納すれば通常は必要ストレージ容量は200Mybteです。これに重複排除機構を適用すると、これまで別々のディスク領域を確保して格納されていた2つのファイルは同じデータであるとストレージが認識し、実体を一つにまとめることで必要ストレージ容量は100Mybteに圧縮できます。ただしこれは単純な「ファイルレベル」の重複排除であり、他にはブロックレベルの重複排除、バイトレベルの重複排除があります。ファイルレベルの重複排除ではストレージ側が同じファイルであると認識すればディスク上に格納される実体は一つにすることで必要容量をセーブすることができます。しかしファイルレベルの場合たとえ1byteでも違うと別のファイルと見なされるので、一方のファイルを少し編集してしまうと途端に必要ストレージ容量は100Mbyte -> 200Mbyteに膨らんでしまいます。ブロックレベルであればあくまでもブロック単位での重複判定となるため、編集した部分のブロックだけを別途確保すればこと足ります。ただし、ブロックレベルではこの重複判定をファイルレベルとは比較にならない程行う必要がでてくるので、その分処理性能に関してオーバーヘッドが見込まれます。ブロックレベルの重複排除は処理に幾分かオーバーヘッドが見込まれるものの、結果としてファイルレベルの重複排除よりも多くの容量をセーブできます。
そしてZFSの重複排除機能はブロックレベルで実装されています。これはストレージ側で実装する重複排除としてはブロックレベルが最も効率的ということと、ZFSというファイルシステムの設計思想として、より現代的なマルチコアで同時実行性能の高いH/Wや、そのマルチコアをうまく扱うことができるマルチスレッドOSを稼働環境の前提としていることが設計根拠に挙げられます。つまりCPUをより積極的に利用すべき、というスタンスです。
もう一つ、Deduplication機構の実装として注目すべきなのはいつ重複判定を行うのか、です。これはデータをディスクに書き出す前に行うリアルタイム型と、定期的にディスク上のデータをスキャンして一括して重複判定を行うバッチ型があります。ZFSでは前者のリアルタイム型を採用しています。当然リアルタイムに重複判定処理を行うとディスクI/Oのレスポンスに対するインパクトが懸念されます。これがどの程度のインパクトになるかは環境に大きく依存するところなので一概には言えないものの次のように考えることができます。現在のI/Aサーバでは頭でっかち(CPU性能:高)尻つぼみ(Disk I/O性能:低)なバランスとなっています。性能に余裕が見られがちなCPUリソースをより活用し、より精度の高い重複排除を行えばディスクに転送しなければならないI/Oを削減することができ、結果的によりバランスのとれたリソース稼働を実現できる可能性があります。こうなるとディスクの容量削減だけではなく、I/O帯域の削減につながってくるため、環境によってはボトルネックが解消されて全体的な性能が向上する可能性すらあります。なのでリアルタイム型の重複排除は理にかなっている、と考えることができます。
ここまででZFSの重複排除機構について最も重要な仕様については理解することができますが、同時に次のような疑問も湧いてきます。
「これまでも容量を削減する機構として圧縮やスナップショットがあったけどそれとはどう違うのか?」
この疑問について次のエントリでまとめようと思います。
VM ServerをVM Server上で仮想マシンとして動かす
昨今ほとんどの検証環境はリソースの面でも作業効率の面でも仮想化環境を用いるのがリーズナブルだと思います。
しかし!VM自体の検証には残念ながらH/Wが必要です。一番VM好きなエンジニアが自分の業務ではVMの恩恵を受けられないというのは物悲しい話です。僕の愛機はMacbook Airで、一応このAirでもVMware FusionやParallels, VirtualBoxをインストールして各種仮想化技術を利用しています。ただしいかんせんAirはメモリが2Gbyteなのでかなり鬼気迫ったリソース稼働状況を強いられます。(そんな中、Desktop仮想化製品としては唯一メモリオーバコミットができるParallelsの新バージョン(5)が先日リリースされました。購入検討中。動作もしょっぱなから(別途ドライバ等なくても)異様に速いんですよねー)
さておき、今回お話したいのはOracle VM Server環境をいかに限られたリソースで効率的に構築するか、です。実はVMware FusionでゲストOSとしてOracle VM Serverを稼働させることは可能です。メモリが許せばボコボコVM Serverを起動できます。Desktopではそんな構成ですが、ちゃんとしたサーバの検証機だったらどうすればよいか? Oracle VM Server上にゲストOSとしてOracle VM Serverを作成することが可能です。モードは完全仮想化(HVM)で作成します。
*なのでサーバにはIntel VTが必要。
こんな構成です。

*一番上のゲストにはPVMしか利用できません。これは中段のVM ServerがVTサポート無しで構成されるためです。
このかなりイカれた構成にすれば、物理サーバは一台にもかかわらず複数VM Serverで構成されるServer Poolの検証(例えばH/Aクラスタ機能とか)を簡単に行えます。また、共有ストレージがなくても下段のVM ServerでファイルVBDやブロックデバイスVBDを中断のVM Serverに供給すれば、仮想SANを作成することもできます。便利ーー。
さらに、VM ManagerのゲストOSやSolarisのゲストを作成してovmzfsを使用したりすれば完璧なオールインワンの検証環境ができあがります。こんな感じの変態的高密度環境です。

僕は今、Xeon X5560 2.80GHz 4コアx 2ソケット, メモリ24Gbyteのちょっといいマシンで実際にこの環境を構築しています。
構築方法も特別な手順は必要ありません。以下、構築手順の流れです。
- 下段のVM Serverを普通にインストールする(BIOSでVTが有効になっていることを確認)
- インストールした下段のVM Serverにvirt-install等を使ってOracle Enterprise Linuxのゲストを一つ作成。このゲストにVM Managerをインストールします。*別途VM Managerがある場合はスキップ可能
- 下段のVM ServerをVM Managerに登録します。
- VM Serverのisoファイル(インストールイメージ)をVM Managerでインポートします。
- 完全仮想マシン(HVM)としてゲストOSを作成し、インストールメディアとしてVM Serverのisoファイルを選択します これで中段のVM Serverが普通にインストールできます。必要な台数を作成します。
- 新しくVM ManagerでServer Poolを作成し、中段のVM Serverを登録します。
以上です。ちなみにVM Server上でのVM Serverのインストールはめちゃくちゃ速いです。2分くらいでできます。isoがCDじゃなくてファイルなので読み込みが速いんですね。
是非お試しを。
ovmzfsセットアップ手順
資料ではかなり省略して書いてあったのでひとまずここにセットアップ手順を書いておきます。
構成のイメージ

OpenSolarisセットアップ
OpenSolaris 2009.06をインストールします。
SUNWiscsidm, SUNWiscsit, SUNWiscsitgtをインストールし、iscsitgtdを起動する
[root@opensolaris]# pkg install SUNWiscsidm SUNWiscsit SUNWiscsitgt [root@opensolaris]# svcadm enable iscsitgt
VM Server & VM Managerセットアップ
Oracle VM 2.2のVM Serverをインストールします(このあたりはマニュアル、@ITの記事、このブログの記事等を参照ください)
VM Serverのパーティションレイアウトはカスタム設定で以下のようにしておきます。
/boot ext3 200MByte
swap 1280MByte
/ ext3 残り全部
Oracle VM Managerをインストールします。もし、VM Manager用のゲストOSもしくはNativeOSを用意することが難しい場合は、VM Server上にVM Managerをインストールするという荒技も可能です。以下のようにVM ManagerのisoファイルをVM Server上でマウントし、通常通りrunInstaller.shを起動すればインストールできます。
[root@vmserver]# mount -o loop,ro OracleVM-Manager-2.2.iso /mnt [root@vmserver]# sh /mnt/runInstaller.sh
VM ManagerをVM Server上にインストールした場合は、以下の[root@vmmanager]は[root@vmserver]と読みかえてください。
SSH設定
vmmanagerでovmzfsを実行するユーザにsuします。rootでもOKです。
公開鍵を生成します。
[root@vmmanager]# ssh-keygen
生成した公開鍵を以下に対して登録します。
- VM Serverのrootユーザ
- ZFSサーバPrimary Administratorとなっているユーザ(インストール時にユーザを作成していなければroot、作成していればそのユーザ)
[root@vmserver]# mkdir $HOME/.ssh && chmod 700 $HOME/.ssh [root@vmserver]# vi $HOME/.ssh/authorized_keys (vmmanagerのid_rsa.pubの内容をコピーする) [user@opensolaris]$ mkdir $HOME/.ssh && chmod 700 $HOME/.ssh [user@opensolaris]$ vi $HOME/.ssh/authorized_keys (vmmanagerのid_rsa.pubの内容をコピーする)
*OpenSolarisのrootユーザを使用する場合は/etc/ssh/sshd_configのPermitRootLoginをyesにし、svcadm restart sshしておきます。
vmmanagerからそれぞれのホストのsshでログインして、プロンプトなしでログインできることを確認します。
python-ZSIインストール
VM Managerにpython-ZSIをインストールします。python-ZSIはULN(Unbreakable Linux Network)のEnterprise Linux 5 Add-onsのChannelにあります。
[root@vmmanager]# up2date python-ZSI
ULNが使えないという人はこちらからRPMをダウンロードしてrpm -iでインストールしてください。
python-ZSI-2.1-a1.el5.noarch.rpm
ovmzfsセットアップ
VM Managerにovmzfsをインストールします。ovmzfsは一つのpythonスクリプトなのでこのファイルをパスの通っているディレクトリに置けばOKです。
[root@vmmanager]# wget http://nkjmkzk.net/wp-content/uploads/2009/11/ovmzfs-0.81.zip [root@vmmanager]# unzip ovmzfs-0.81.zip [root@vmmanager]# mv ovmzfs /usr/bin/
以下のようにovmzfsを実行します。対話的に初期設定が行われ、必要なモジュールファイルがVM Managerからダウンロードされ、ZFSサーバでレポジトリが初期化されます。
[root@vmmanager]# ovmzfs init
ZFSサーバの初期化が成功すると以下のようなメッセージが出力されます。
>>> >>> >>> New repository has been created >>> >>> >>> Shared Filesystem for /OVS is exported as opensolaris:/rpool/ovmzfs/[POOL NAME]/ovs Please run following command on VM Server. [root@vmserver]# /opt/ovs-agent-2.3/utils/repos.py --new opensolaris:/rpool/ovmzfs/[POOL NAME]/ovs (UUID of this filesystem will be displayed) [root@vmserver]# /opt/ovs-agent-2.3/utils/repos.py --root [UUID] And then, please create Server Pool using VM Manager
このメッセージに沿ってVM Server上でレポジトリを登録します。
VM Serverで共有ディスクを登録します。
[root@vmserver]# /opt/ovs-agent-2.3/utils/repos.py --new opensolaris:rpool/ovmzfs/[POOl NAME]/ovs [ NEW ] 5bcd80df-cb99-496a-8130-8713560f6fb8 => opensolaris:rpool/ovmzfs/[POOL NAME]/ovs [root@vmserver]#/opt/ovs-agent-2.3/utils/repos.py --root 5bcd80df-cb99-496a-8130-8713560f6fb8
次にVM ManagerからServer Poolを作成し、先ほどのVM Serverを登録します。
このとき、Server Pool名はovmzfsの初期設定で入力した値と一致しなければいけないことに注意してください。
無事にVM ManagerでServer Poolが作成できればovmzfsのセットアップは完了です。VM Serverが複数ある場合はVM Managerから追加登録してください。