Oracle Sun Technology Updateに行ってきました
昨日、8/19に目黒雅叙園にてOracle Sun Technology Updateが開催されました。3Track x 3でセッションが開催され、各セッションは大きく分けてJavaとSolarisを扱う内容でした。その中でも最新情報の提供を行うようなセッションと、DTraceチュートリアルのような具体的な技術話とかなり幅広い内容が提供されたように思います。
僕はSolaris Trackに一日中入り浸っていましたので簡単にレポートしたいと思います。
B-1 Solaris開発環境のご紹介

大曽根 明さん
Mr.Solarisの異名をとる大曽根さんはOracle Solaris Operating Systemについてこれまでを振り返り、今後のロードマップを紹介しました。
次に新しいH/Wサポートメニュー「Premier Support for Systems」についても紹介しました。Premier Support for SystemsはH/Wの保守プログラムでありながら、同時にOracle Solaris, Oracle Enterprise Linux, Oracle VMが使いたい放題になることを説明。
また、ZFS, Containerについて概要を紹介し、特にZFSについては「非クラスター型で現在最強のファイルシステムだろう」と指摘。そしてSun Studioを使ったデモを披露する等幅広い内容をカバー。
B-2 開発環境でのSolaris ZFS

野崎 宏明さん
先のセッションで「最強」とされたZFSについて、こちらの@IT記事でもわかりやすい解説をされてる野崎さんからプレゼン。End-to-Endの整合性チェック機構、CoW等ZFSの根幹を成す内部アーキテクチャについて説明。
B-3 DTrace活用術
ZFSと並ぶSolarisの代表的な機構であるDTraceについて藤田さん、本間さんからプレゼン。

藤田 勇治さん
藤田さんはDTraceが何であるのか、どういった情報がとれて、どのように活用できるのかという全体象を事例を交えて紹介。端的で軽快なトークでDTraceのメリットを限られた時間ながら非常にわかり易く説明されていました。カーネルを特別なビルドオプション付きでコンパイルしたりする必要がない、特別な起動オプションもいらない、その場でほしい情報を動的に出力させることができる、ということがズドンと理解できる濃密な時間でした。

本間 大輔さん
本間さんはDTraceのHow toを紹介。「こういう情報をとりたいときは・・」という切り口で実際のスクリプトを見せて解説しながら出力結果を確認していくという実践的なセッション。持ち時間は30分足らずであるにもかかわらずDTraceのサンプルスクリプトを含む実用的な資料を120枚作成するというパッション。事実、この資料はこれからDTraceを使ってみたい!という人にはバイブルでしょう。必見です。バイブルのダウンロードはこちら。
DTrace活用術
特別企画トークライブ:「2020年に向けてITエンジニアはどうやって生き残るか?」

ウルシステムズ(株)の漆原様、(株)Preferred Infrastureの太田様、クックパッド(株)大野様によるパネルディスカッション。モデレータは弊社の伊藤さん。
はっきり言って、かなり面白いディスカッションでした。何が面白かったかというと、みなさんそれぞれ強い信念をお持ちで、その信念が名言となって出てくるとことです。僕が特に印象に残った名言を下記に挙げさせていただきました。
- 製品や技術にコミットするかどうかは開発者に会って決める。信頼できるヤツならいける。(漆原様)
- めちゃ難しいプロジェクトを社員に任せる。できたら、目一杯給料を払ってあげる。それを繰り返す。(漆原様)
- 今日欲しいと言われたものは明日提供できなければそこに感動はない。(大野様)
- やりたいことをやる。やりたくないことはやらない。やりたいことを宣言する。(大野様)
それぞれ深い思考や経験を元にしたパワフルな持論です。共感する部分や「なるほど〜」な気付きもあり、非常に有益な時間だったと思います。
個人的には今後SunのテクノロジーとOracleのテクノロジーの合体技をより具体的に訴求するようなセミナーをやりたいなと思っています。Solaris, ASM, ZFS、このあたりがキーワードになるでしょう。楽しくなりそうです。
ACFSのスナップショットで日次バックアップ & 差分レプリケーション
ACFSにはスナップショット機能が実装されています。
例えば、/u01/acfsにACFSファイルシステムがマウントされている場合下記のようにしてスナップショットを取得することができます。
[root@guest]# acfsutil snap create `date +%Y%m%d` /u01/acfs
スナップショットは/u01/acfs/.ACFS/snaps/YYYYmmdd以下に作成されます。これは通常のディレクトリ/ファイルとしてlsやcatなどで中身を確認することができます。バックアップの中身がすぐに確認できちゃう、というのは便利ですよね。
ただ、これだけだとあくまでもスナップショットによる論理バックアップです。ファイルシステムの改ざんやミスオペレーション時の復旧は可能ですが、RAID損傷等の物理的な障害時には機能しないバックアップです。物理的な障害時にもバックアップできるように異なるH/W間でレプリケーションさせておくことが考えられます。現時点での最新リリースGrid Infrastructure 11.2.0.1にはレプリケーション機能は実装されていません。
ACFSはGrid Infrastructureに含まれます
ということで伝統的なrsyncを使ってACFSスナップショットからリモートホストへ差分レプリケーションを実現するワンライナーを紹介しておきます。
[root@guest]# rsync -ave ssh --delete --exclude='.ACFS' --exclude='lost+found' /u01/acfs/.ACFS/snaps/`date +%Y%m%d`/ [バックアップサーバのユーザ名]@[バックアップサーバのIP]:[ディレクトリ]
これで先ほど取得したスナップショットの内容をリモートホストに複製(レプリケート)することができます。初回実行時にはまだリモートホスト側にデータがまったく存在しないのでフルレプリケーションになりますが、次回からはレプリケート済みのデータと今回転送するデータとの差分のみが転送されます。また、リモート側には存在するがもうオリジナルには存在しないデータはリモート側から削除されます。つまりオリジナルの最新スナップショットとリモートの複製は一日毎に同期することになります。
なので先ほどのACFSスナップショットのコマンドとrsyncのレプリケーションコマンドをcronに登録しておけば日次でスナップショットを取得して論理障害に備えつつ、リモートホストにバックアップを複製して物理障害に備えることができます。
Oracle VMをCisco UCS + Palo(M81KR)で検証しました
8/6のOracle VM Forumで発表させていただきましたが、Oracle VMとCisco UCSを組み合わせて検証しました。検証の焦点はCisco UCSに装着したCNA, 「Palo」ことM81KRを認識できるかということと、その性能です。
M81KRはmezzanine cardですが一枚のM81KRで最大128個の仮想NICを作成できるところがポイントです。さらにOS側には特段SR-IOV対応等は必要ありません。OSはM81KRで作成された仮想NICを普通のPCIデバイスとして認識します。
Cisco UCS M81KR 仮想インターフェイス カード
結論から言うとまず認識に関してはまったく問題ありませんでした。
Oracle VM Serverでlspciコマンドを実行し、認識しているPCIデバイスを確認するとM81KRで作成した仮想NICは下記のように表示されます。
[root@vmserver]# lspci 0c:00.0 Ethernet controller: Cisco Systems Inc 10G Ethernet NIC (rev a2) 0d:00.0 Ethernet controller: Cisco Systems Inc 10G Ethernet NIC (rev a2) 0e:00.0 Ethernet controller: Cisco Systems Inc 10G Ethernet NIC (rev a2) 0f:00.0 Ethernet controller: Cisco Systems Inc 10G Ethernet NIC (rev a2) 10:00.0 Ethernet controller: Cisco Systems Inc 10G Ethernet NIC (rev a2)
lspciの出力は、デバイスから得られるPCI IDと、/usr/share/hwdata/pci.idsに格納されているPCI IDを照合してデバイス名を表示しています。したがってlspciでデバイス名が得られたからといってドライバがこのデバイスを認識しているかどうか(つまりNICとして使用可能な状態かどうか)は別問題です。
M81KRが作成する仮想NICを利用するにはenicというドライバが必要になります。これはまだ多くのLinuxディストリビューションには含まれていないため、別途Ciscoさんのサイトからダウンロードしてインストールする必要があります。RHEL5.x, OEL5.xであればRPMが用意されています。しかし今回僕も初めて気がつきましたが、Oracle VM Server 2.2.1はこのenicドライバを標準でインストールしてあります。なのでM81KRで作成した仮想NICはOracle VM Serverからは別途ドライバをインストールせずともNICとして正しく認識され、ethX, xenbrXが自動的に作成されます。
一方、この仮想NICを有効活用するにはPCI Passthroughが効果的でしょう。その場合はこのデバイスに対するドライバが必要となるのはゲストOS(仮想マシン)の方です。Passthrough設定を行うとVM Server(つまりdom0)からはそのNICは見えなくなります(ただし依然としてlspciの出力には現れます)。したがってPassthroughした先のゲストOSでこのNICを利用するにはゲストOS側にenicドライバをインストールする必要があります。
RHEL5.x, OEL5.xではenicドライバはバンドルされていませんが、RHEL6.x, OEL6.xでは標準でバンドルされるようです。
2010年8月時点ではOracle VM ServerでのPCI Passthroughは公式サポートされていません。チャレンジャーな方は下記に手順を紹介しますのでトライしてみてください。
Oracle VM Serverで上記の仮想NICをPassthroughするにはまずUCSの該当ブレードでVT-d(I/O Virtualization)がEnabledとなっていることを確認します。
次にOracle VM Serverのgrub.confを編集してI/O Virtualizationを有効にしてOSを再起動します。
title Oracle VM Server-ovs (xen-64-3.4.0 2.6.18-128.2.1.4.25.el5ovs)
root (hd0,0)
kernel /xen-64bit.gz dom0_mem=547M iommu=pv
module /vmlinuz-2.6.18-128.2.1.4.25.el5xen ro root=UUID=f1b13de3-adb2-4b5a-a6e9-a8beda1b4f73
module /initrd-2.6.18-128.2.1.4.25.el5xen.img
OSが起動したら下記のコマンドでI/O Virtualizationが有効化されていることを確認します。
[root@vmserver]# xm dmesg | grep 'I/O virtualisation' (XEN) I/O virtualisation enabled (XEN) I/O virtualisation for PV guests enabled
次にmodprobe.confに下記の記述を追加し、再起動を行います。これはdom0からPCIデバイスを隠蔽するための設定です。(0000:0c:00.0はdom0用に残しておきます)
install enic /sbin/modprobe pciback ; /sbin/modprobe --first-time --ignore-install enic options pciback hide=(0000:0d:00.0)(0000:0e:00.0)(0000:0f:00.0)(0000:10:00.0)
ifconfig -a等でインターフェースを確認してみるとと、先ほどまでこれらの仮想NICにひもづいて作成されていたethXやxenbrXがなくなるはずです。
その代わりにPCIデバイスはPassthrough用にプールされています。xmコマンドで確認可能です。
[root@vmserver]# xm pci-list-assignable-device 0000:0d:00.0 0000:0e:00.0 0000:0f:00.0 0000:10:00.0
ここにリストされているPCIデバイスはゲストOSにPassthrough可能になっています。仮想マシンの設定ファイルを編集してPCIデバイスを割り当てます。ここではPVHVMを使用しています。
単なるHVMでももちろん可能ですが、PVMの場合はPVMのgrub.confにも少し設定が必要です。
ネットワークの内部構成は下図のようになります。
.png)
[root@vmserver]# vi /OVS/running_pool/oel55-phvm-01/vm.cfg
acpi = 1
apic = 1
builder = 'hvm'
device_model = '/usr/lib/xen/bin/qemu-dm'
disk = ['file:/OVS/running_pool/oel55-phvm-01/System.img,hda,w']
kernel = '/usr/lib/xen/boot/hvmloader'
keymap = 'en-us'
memory = 1000
name = 'oel55-phvm-01'
on_crash = 'restart'
on_reboot = 'restart'
pae = 1
serial = 'pty'
timer_mode = '2'
uuid = '313105b6-15ac-d7ea-de41-0ef0a90d302a'
vcpus = 4
vif = ['bridge=xenbr0,mac=00:16:3E:42:C7:A9,type=netfront'] #これはPVドライバを利用したインターフェース
vif_other_config = []
pci = ['0000:0d:00.0'] #PCI Passthroughの設定
vnc = 1
vncconsole = 1
vnclisten = '0.0.0.0'
vncpasswd = ''
vncunused = 1
これでゲストOSを起動します。まだゲストOSにenicドライバをインストールしていない場合はインストールします。
ドライバ:http://tools.cisco.com/support/downloads/go/ImageList.x?relVer=1.3%281e%29&mdfid=283004074&sftType=Unified+Computing+System+%28UCS%29+Tools+and+Drivers+Bundle&optPlat=Linux&nodecount=2&edesignator=null&modelName=Cisco+UCS+B200+M2+Blade+Server&treeMdfId=282558030&treeName=Unified+Computing&modifmdfid=&imname=&hybrid=Y&imst=N&lr=Y
*アカウントが必要です
[root@guest]# rpm -ivh kmod-enic-1.3.1c-rhel5u5.x86_64.rpm
そしてlspciコマンドで仮想NICをPCIデバイスとして認識できているか確認します。
[root@guest]# lspci | grep Cisco 00:03.0 Ethernet controller: Cisco Systems Inc VIC Ethernet NIC (rev a2)
ドライバをロードしてネットワークインターフェースが認識されることを確認します。
[root@guest]# ls /sys/class/net
eth0 lo sit0
[root@guest]# modprobe enic
[root@guest]# ls /sys/class/net
eth0 eth1 lo sit0
あとはいつも通りネットワークインターフェースを設定するだけです。
性能値についてはOracle社のポリシー上公開できないのですが、かなりの値が期待できると思っていただいて間違いないでしょう。また、スピードが速い、というだけでなくdom0へのCPUインパクトが激減(というかほぼゼロ)になるのが素晴らしいところです。
iSCSI Initiatorのタイムアウト設定
Linux環境のiscsi-initiator-utilsを用いた際に重要となるタイムアウト関連の設定について。
信頼性の高いシステムでは当然iSCSIストレージへの接続も冗長化するという要件があります。汎用的な実装だとdevice-mapper-multipathを使ってストレージネットワークの障害に対しての冗長構成でとることができます。また、OracleのASMを使ったStorage GRID構成では複数ストレージをストライピング&ミラーリングし、例えストレージが筐体ごとパワーダウンしてもオンラインで処理を継続することができます。このStorage GRID構成で重要なのがiSCSI Initiatorのタイムアウト設定です。
iSCSIストレージへの接続性に不具合が発生した場合、iSCSI Initiatorが死活監視によってそれを検出します。最終的にはiSCSI InitiatorがiSCSI Targetへの接続障害という判定を行い、それをI/Oエラーという形でOSに報告します。ASMはその報告をもってストレージの切り離しを行い、残るストレージで処理を再開、継続します。障害が起こってからiSCSI InitiatorがI/Oエラーを報告するまでの間は全てのI/Oが一旦保留されます。本番環境ではこの保留される時間を制御したいという要件が出てくるでしょう。
下記のような障害パターンで上記の保留期間を制御するためのiSCSI Initiator設定を紹介します。
- クライアント側のNIC故障
- iSCSIネットワーク断(ケーブル劣化、スイッチ故障)
- iSCSIストレージのパワーダウン、コントローラ故障
ちなみにiSCSI InitiatorはOracle Enterprise Linux 5.4にバンドルされるiscsi-initiator-utils-6.2.0で動作を確認しています。前後のバージョンでもデフォルト値は変更されている可能性はありますが、挙動に大きな違いはないと思います。
重要なパラメータは下記の3つです。
- node.conn[0].timeo.noop_out_interval(デフォルト5秒)
pingによるコネクションの死活監視間隔
- node.conn[0].timeo.noop_out_timeout (デフォルト5秒)
pingによるコネクションの死活監視がコネクションエラーと判定するまでの待ち時間
- node.session.timeo.replacement_timeout(デフォルト120秒)
コネクションエラーが発生してからI/Oエラーを返すまでの待ち時間。この時間までに死活監視がコネクション復帰を報告すればI/Oエラーは返らない。
デフォルト設定で障害が発生した場合、下記のような流れとなります。
- 死活監視のpingが発行される(タイミングによって障害発生から1〜5秒経過)
- pingがタイムアウトする(+5秒経過)
- 継続して死活監視のpingが発行され、最終的にpingが成功しないとOSにI/Oエラーが返る(+120秒経過)
- ASMがI/Oエラーを検出して障害ストレージを切り離し、残りのストレージで処理を再開する(即時)
経過時間をまとめると、(1〜5)+ 5 + 120 = 126〜130秒程の時間が切り替えまでに必要となります。
これを例えば障害試験等で確実に15秒程で切り替えを発動させたい場合は次のように設定すれば実現できます。
- node.conn[0].timeo.noop_out_interval = 1
- node.conn[0].timeo.noop_out_timeout = 5
- node.session.timeo.replacement_timeout = 10
この場合経過時間は(〜1)+ 5 + 10 = 15〜16秒となります。
このiSCSI Initiatorのパラメータ設定は下記のiscsiadmコマンドで設定できます。ただし、ログイン済みのセッションについては反映されません。反映させるには一旦ログアウトし、再度ログインしてセッションを再確立させる必要があります。
[root@~]# iscsiadm -m node -p [ターゲットのIP] -o update -n [パラメータ名] -v [設定値]
また、/etc/iscsi/iscsid.confを編集しておくことで新たに登録されるiSCSIターゲットについてのデフォルト値を変更することができます。これは既に登録されているiSCSIターゲットには反映されないので注意してください。
オレ流クラウドの定義
先日、ようやくぴったりと自分の感覚にフィットするクラウドの定義を思いつきました。超端的に一文で表現。
「ガチガチに作り込んだ最強システムをみんなで使える形にしたもの」
ガチガチに作り込んだ、ってどんな?ということになります。
イメージし易いのはやはり比較的大規模なWebサービスを提供されている企業の自前システムでしょう。自前でSEを抱えてシステムを構築・運用されているところはいかに安く、安定して、スケーラブルで使い易いシステムを構築するかに創意工夫を凝らされています。そういうシステムの裏側を紹介する勉強会等はえてして面白いですよね。
素早くサーバを追加&システムに組み込むためにPXEブートを駆使したディスクレス構成を組んでみたり、Cobbler等を使って高速なOSインストール環境を整えてみたり、PuppetやFuncを使って多数のサーバを一斉に操作するフレームワークを確立してみたりと、その筋の作り込みはめちゃ楽しいものです。しかしこういったシステムは一朝一夕で出来上がるものではなく、いろんな調査、検証や失敗経験から学んだ成果であり継続的なブラッシュアップがなされて完成度を高めていくものでしょう。
ある程度形になるまでは相当な努力と時間が必要ですが、軌道に乗れば自分たちにとって非常に都合のよい最適化された最強システムになっていきます。
こういったシステムはSIerが案件単位で構築することは現実的ではないでしょう。厳しい納期、各ステークホルダーの私利私欲による提案が交錯し、真に最適な姿を突き詰めるのは至難の業です。そこにはいくつもの妥協という大人の選択があります。
案件単位で個別にシステムを作っていく事はSIerにとっては飯の種かもしれませんが、エンドユーザは毎回システム毎にH/WやS/Wの購入を余儀なくされ、同じように設計、構築、テストという作業を発注することになります。しかもその結果構築されるシステムはWebサービス事業者が長年ブラッシュアップしているシステムと比較して、完成度で見劣りする可能性が多いにあり、また、費用も都度相当なものになることでしょう。国が大手SIerに発注しているシステム、とんでもない金額ですよね。「あんなの、あのイケイケの会社にお願いして作ってもらえば100分の1くらいの費用で済むんじゃないの?」と、納税者としてはクレームしたくもなります。
そう考えると、理想は「最強のオレオレ・システム」を汎用的に使えるようにすることではないかと思います。
これまでの調査・検証と経験、優秀なエンジニアの知見の粋を集めたオレオレ・システムの、、、
- 高速プロビジョニングの仕組みをシェアする
- H/W障害時に高速にFailoverすることが検証済みである冗長構成をシェアする
- ワンタッチで様々なオーダーが完了する運用フレームワークをシェアする
これができればIT業界はもっと政治的な要素がなくなり、純粋な技術的要素が強まるのではないかと思いを巡らせています。
実現するためのテクノロジーは問いません。高速プロビジョニングを仮想マシン+CoWで実装する手法もあるでしょうし、前述のネットワークブートでベアメタルにOSを起動させる手法もあるでしょう。Real Application Clustersで耐障害性を確保するような高度な冗長構成もあるでしょうし、システムコンフィグレーションはシンプルに留め、人間的Failoverなシステムもあるでしょう。各手法によって一長一短あると思いますが重要なのは最終的に如何にサービスレベルが高く、運用が楽ちんで低コストなシステムが構築できるかだと思います。これがガチガチに作り込んだ最強システム。これに汎用性を持たせて第3者に開放できる状態にしたシステムが「クラウド」である、と考えました。
ZFSでtpgtを使って接続先ポートを限定する
ZFSはご存知の通りzvolを作成してiSCSIでエクスポートすることができます。
とある環境でZFSサーバは複数のネットワークセグメントに接続されており、当然それぞれのセグメントでIPアドレスが割り振られているとします(多くの環境ではそのようになっているでしょう)。そのときzfs set shareiscsi=on [ZVOL]としてzvolをエクスポートすると、すべてのセグメントでzvolがエクスポートされてしまいます。

iSCSIセグメントからDiscoveryしにいったiSCSIクライアントにも1zvolにつき複数のターゲットが見えてしまいます。これは多くの環境で望ましくない挙動でしょう。本来はzvolがエクスポートされるのはiSCSIのストレージセグメントだけに留めておきたいはずです。
zvolがエクスポートされるセグメントを設定するにはtpgt (Target Port Group Tag)が有効です。tpgtを使えば下図のようにzvolをエクスポートするセグメントを限定できます。

設定手順です。
まずtpgtを作成します。tpgtの名前には1〜65535の任意の数字を割り当てます。
[root@~]# iscsitadm create tpgt 1
作成したtpgtにzvolをエクスポートしたいIPアドレスを追加します。
[root@~]# iscsitadm modify tpgt -i 10.2.0.1 1
zvolのアクセス制御リストとして作成したtpgtを設定します。
[root@~]# iscsitadm modify target -p 1 [TARGET]
これでtpgt 1に参加している10.2.0.1だけがzvolのエクスポート対象となります。
phpからASMを管理するためのパッチ
$conn = oci_connect('user', 'password', 'node/service', '', OCI_SYSDBA);
[root@~]# tar xvfj php-5.3.2.tar.bz2 [root@~]# cd php-5.3.2/ext/oci8/ [root@~]# patch < /PATH/TO/php-sysasm.patch [root@~]# cd ../../ [root@~]# ./configure --with-oci8 [root@~]# make [root@~]# make install
ASMインスタンスへの接続は下記のようにOCI_SYSASMフラグを指定して接続します。
$conn = oci_connect('user', 'password', 'node/service', '', OCI_SYSASM);
Xenでメモリをオーバーコミットする(Transcendent Memoryセットアップ編)
概要
- 管理者は多かれ少なかれメモリをある程度オーバープロビジョニングする
- 結果、性能は確保されるものの定常的に使われていないメモリが出てくる
- これを特にサーバ仮想化環境で見ると相当量のメモリが「未使用」となり、「もし、メモリ割り当てを最適化できればあと数VM収容できるのに」となる。実際、メモリは現在唯一VMの収容数を絶対的に制限するハードリミットとなっている
- この最適化を行うのがTranscendent Memory(以後tmem)。使われていないメモリをかき集めてtmem poolとして再配布可能とする
- ゲストOSはtmemを有効にしてビルドされたカーネルで起動することによって、従来のpage cacheに格納していたページをtmemを使って読み書きするようになる
環境
- Xen: 4.0.0
- ゲストOS: Oracle Enterprise Linux 5.4 x86_64
セットアップ手順
dom0にログインし、Xen(4.0.0)でtmemを有効にする。grub.confを編集してカーネル行に「tmem」を追加しdom0を再起動する
[root@vmserver]# vi /etc/grub.conf
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Xen 4.0.0 (2.6.32.11-1.2.97.xendom0.fc12.x86_64)
root (hd0,0)
kernel /xen-4.0.gz dom0_mem=1024M loglvl=all guest_loglvl=all tmem
module /vmlinuz-2.6.32.11-1.2.97.xendom0.fc12.x86_64 ro root=/dev/mapper/vg_x4-lv_root
module /initramfs-2.6.32.11-1.2.97.xendom0.fc12.x86_64.img
[root@vmserver]# init 6
次にゲストOSにログインしtmemを有効にする。tmemはまだカーネルのメインラインにはマージされていないのでディストリビューションが公開しているカーネルSRPMにtmemパッチ当て、カーネルを再構築する。
tmemパッチ入手先:http://oss.oracle.com/projects/tmem/files/
カーネルSRPM入手先:http://public-yum.oracle.com/repo/EnterpriseLinux/EL5/5/base/x86_64/
公開されているtmemパッチはvanillaカーネル用なのでディストリビューション付属のカーネルに当てるといくつかHunk, Failがでるが手作業で直せるレベルなので手で直す。
[root@guest]# rpm -ivh kernel-2.6.18-194.3.1.0.1.el5.src.rpm [root@guest]# cd /usr/src/redhat/SPECS [root@guest]# rpmbuild -bp kernel-2.6.spec [root@guest]# cd /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.x86_64 [root@guest]# patch -p1 < /var/opt/tmem-linux-2.6.18-xen-855-090408.patch
*4つ程Failするので手作業で直す
[root@guest]# cp configs/kernel-2.6.18-x86_64-xen.config .config
任意だが、わかり易いようにカーネル名を変更しておく
[root@guest]# vi .config CONFIG_LOCALVERSION="-tmem"
[root@guest]# vi Makefile EXTRAVERSION = -194.3.1.0.1.el5xen
ビルドする
[root@guest]# make -j8
*tmemについて有効化するか訊かれるので全て「Y」として有効化する
カーネルモジュールをインストールする
[root@guest]# make modules_install
カーネルをインストールする
[root@guest]# make install
initial ramdiskを作成する
[root@guest]# mkinitrd -v -f initrd-2.6.18-194.3.1.0.1.el5xen-tmem.img 2.6.18-194.3.1.0.1.el5xen-tmem
initial ramdiskをインストールする
[root@guest]# cp initrd-2.6.18-194.3.1.0.1.el5xen-tmem.img /boot/
新しいカーネルで起動するようにgrub.confを編集する
[root@guest]# vi /etc/grub.conf default=0 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu title Enterprise Linux (2.6.18-194.3.1.0.1.el5xen-tmem) root (hd0,0) kernel /vmlinuz-2.6.18-194.3.1.0.1.el5xen-tmem ro root=/dev/VolGroup00/root rhgb quiet initrd /initrd-2.6.18-194.3.1.0.1.el5xen-tmem.img title Enterprise Linux (2.6.18-164.el5xen) root (hd0,0) kernel /vmlinuz-2.6.18-164.el5xen ro root=/dev/VolGroup00/root rhgb quiet initrd /initrd-2.6.18-164.el5xen.img
再起動し、新しいカーネルで起動する
[root@guest]# init 6
Demo
Reference
- http://lists.xensource.com/archives/html/xen-devel/2009-01/msg00253.html
- http://oss.oracle.com/projects/tmem/
- http://oss.oracle.com/projects/tmem/dist/files/linux-precache-preswap.README.html
- http://oss.oracle.com/projects/tmem/dist/documentation/api/tmemspec-v001.pdf
- http://oss.oracle.com/projects/tmem/dist/documentation/presentations/TranscendentMemoryXenSummit2010.pdf
Xenでメモリをオーバーコミットする(Self-Ballooningセットアップ編)
概要
- self-ballooningはゲストOS自らメモリをある条件に基づいて動的に返却する/獲得ことによって実質的にメモリをオーバーコミットするための仕組み
- xenballoondはゲストOSで動くbashベースのデーモン。これがself-ballooningを制御する
- xenballoondはdom0へのメモリ情報提供を担うことも計画されている
- xenballoondは/proc/meminfoのCommitted_ASの値をベースに最低限必要なメモリ容量を判別する
環境
- Xen: 3.4.0(Oracle VM Server 2.2.1)及び4.0.0(Fedora 12)で確認
- ゲストOS: Oracle Enterprise Linux 5.4 x86_64
セットアップ方法
Xen側には特殊な設定は必要ありません。すべてゲストOSでの作業です。
まず、ゲストOS上でxen-4.0.0.tar.gzをxen.orgからダウンロードし展開します。これはxenのtarボールの中に必要なスクリプトがあるからです。(恐らくXen 3.3以降であれば必要なツールが含まれているはず)
[root@guest]# tar xvfz xen-4.0.0.tar.gz
展開されたディレクトリ中から3つのファイルをそれぞれインストール(コピー)する
[root@guest]# cp xen-4.0.0/tools/xenballoon/xenballon.conf /etc/sysconfig/ [root@guest]# cp xen-4.0.0/tools/xenballoon/xenballond /usr/bin/ [root@guest]# cp xen-4.0.0/tools/xenballoon/xenballond.init /etc/init.d/xenballoond
bashファイルを実行可能なようにパーミッションを変更する
[root@guest]# chmod 755 /usr/sbin/xenballoond [root@guest]# chmod 755 /etc/init.d/xenballoond
必要に応じて設定ファイルを編集する
[root@guest]# vi /etc/sysconfig/xenballoon.conf
*特にXENBALLOON_SELF=falseはtrueに変更する必要がある
xenballoondデーモンを起動する
[root@guest]# service xenballoond start
検証結果
- self-ballooning有効化によって動的にメモリ容量が縮小されるか? => yes
- self-ballooning有効化によって動的にメモリ容量が拡張されるか? => yes(ただしユーザプロセスがメモリを予約した場合。page cacheでは拡張は発動しない)
使用したツール
mem_allocate.c(メモリを確保し、60秒後に解放するツール。適当に作った。)
#include
#include
#include
int main(int argc, char **argv) {
char *str;
int i;
if (argc == 2) {
sscanf(argv[1], "%d", &i);
printf("Allocating %d Bytes for 60 seconds...\n", i);
str = (char *)malloc(i);
memset(str, 1, i);
sleep(60);
free(str);
} else {
printf("This program needs exactly 1 argument.\nYou can set the bulk of RAM to allocate with integer.\n");
}
return 0;
}
Demo
Reference
- xen-4.0.0/tools/xenballoon/xenballoond.README
- http://blog.xen.org/index.php/2008/08/27/xen-33-feature-memory-overcommit/
- http://www.xen.org/files/xensummitboston08/MemoryOvercommit-XenSummit2008.pdf
Xenでメモリをオーバーコミットする(概要編)
サーバ仮想化環境ではいろいろなリソースをオーバーコミットしてリソース稼働率を高めることができます。「オーバーコミット」は、本来的には物理リソース以上のリソースをさもあるかのようにみせかけて擬似的に割り当てることですが、サーバ仮想化環境で言う場合のオーバーコミットとは実際的には「リソースを共有すること」と考える方が正しい解釈であり、意義のある活用方法だと思います。
.png)
XenはCPUに関しては上図のようなオーバーコミットを古くからサポートしています。なので物理的なCPU数が仮想マシン収容数についてハードリミットとなることはありません。同様にネットワーク帯域やディスク帯域は共有することが基本的な考え方なのでこれらについても仮想マシン収容数のハードリミットになることはありません。しかしXenはメモリのオーバーコミットはサポートしないとしていました。したがって物理メモリは唯一仮想マシン収容数を制限するハードリミットということになります。
現在I/Aサーバ用サーバ仮想化技術において、メモリのオーバーコミットには大別すると下記のような実装方法があります。
- SWAPディスク
- ディスクをメモリに模倣して仮想マシンに割り当てる
- しかし実際はディスクなので堪え難い性能劣化が発生する
- 重複排除
- 複数の仮想マシン間で重複するメモリを検出して一つにまとめる
- 同一メモリページが多いと想定される環境(同一構成の仮想マシンを多数起動するような環境)では効果を期待できる
- 重複判定処理にはオーバーヘッドが予想される。加えて、必ずしも重複排除できる可能性が高くない。
- メモリ動的増減(Self-Ballooning)
- 仮想マシンが必要に応じて能動的にメモリを獲得、解放する
- オーバーサイジングされている環境ではかなりの効果を期待できる
- しかし動的なメモリの獲得・解放は必ずしも十分高速でない
実はXenはバージョン3.3からSelf-Ballooningを用いたメモリの実質的なオーバーコミットが利用可能となっています。(ゲストOS側にSelf-Ballooning用ツールをインストールし、デーモンを起動する必要があります。)厳密にはこれはオーバーコミットというよりメモリを「増減」させる機構ですが、結果的には各仮想マシンのドメイン定義ファイルで設定されているメモリ量の総和が物理メモリを超えることができ、オーバーコミットと同様の効果をもたらします。
Self-Ballooningを有効にするとゲストOSは下記のようなことが可能になります。
- 不要なメモリ領域(完全な空き、またはpage cacheに費やされている領域)を識別して能動的にメモリをXenに返却する *厳密には/proc/meminfoのCommitted_ASをベースに解放範囲を特定します
- メモリ確保が必要になった場合、Xenにメモリ割り当て要求を発行して能動的にメモリ領域を獲得する
xm mem-setコマンド等でdom0側からゲストOSのメモリ容量を調整することはよく行われていると思いますが、Self-BallooningではゲストOSが能動的にメモリ増減を行うというところが特徴的です。
ちなみに少し話しはそれますが、Xen 4.0.0においてman xmdomain.cfgをみると下記のように「Xenではメモリオーバコミットはできない」と明記されています。
Xen does not support overcommit of memory, so the total memory of all guests (+ 64 MB needed for Xen) must be less than or equal to the
physical RAM in the machine.
しかし、実際にはSelf-Ballooningによるオーバーコミットは可能です。Xen 4.0.0のtarボールに含まれるxenballoonのREADMEは下記のようにメモリオーバーコミットが可能であると記載されています。
Xenballoond runs in guest domains and both implements selfballooning and provides metrics to dom0 for (future) directed ballooning. Both capabilities provide a foundation for basic “memory overcommit” functionality.
このあたりは個々の開発者でオーバーコミットに対する定義に違いがあることも一因かもしれませんが、どちらかというとXenのmanがあまりきちんとアップデートされていないことが問題な気がします。
さておき、つまるところXenではSelf-Ballooningを用いたメモリオーバーコミットが可能なわけですが、Self-Ballooningには前述の通り「メモリの獲得・解放が高速でない」という問題があります。そして、この問題を解決する手段としてPVM用に「Transcendent Memory」という新機能がXen 4.0.0から組み込まれています。Transcendent Memoryをごく簡単に言うと「物理メモリを複数の仮想マシン間で共有する仕組み」です。
.png)
その実装はXenが余っているメモリを「Transcendenet Memory Pool」というプールにまとめ、そのプールを複数の仮想マシンがクラスタファイルシステムのようなイメージで共有するという仕組みです。ファイルシステムと違うところは仮想マシンは別仮想マシンがTranscendent Memory Poolに保存したデータを閲覧することは当然できないということです。
*別途メモリのデータを共有できるタイプのPoolも実装が予定されています。
また、Transcendent Memoryにはいくつかの用途が考案されていますが現在実装されているのはpage cacheとして利用するという形です。Transcendent Memoryを有効にするには、Xen側で起動オプションを設定しておくことと、ゲストOS側のカーネルがTranscendent Memoryを有効にしてビルドされている必要があります。構築手順について詳しくは別のポストで解説しようと思います。
*ちなみにXen 4.0.0ではPage Sharingという重複排除タイプのオーバーコミット機能も組み込まれています。こちらはHVMのみの対応です。
そしてTranscendent MemoryはSelf-Ballooningと併用することで威力を発揮します。つまりこうなります。
- Self-Ballooningによって仮想マシンは不必要なメモリを能動的に解放する
- 元々空き領域であったメモリやSelf-Ballooningによって解放されたメモリをXenが掻き集めて「Transcendent Memory Pool」を構成する
- 各ゲストOSは自身に最低限必要なメモリ(カーネルやアプリケーションによって予約されている領域)だけを自身の専有メモリとして保持し、その他必要となるメモリ(page cache)についてはTranscendent Memory Poolを利用する
ゲストOSが全てのメモリを専有する従来の形と比べて下記のようなメリットがあります。
まず、Self-Ballooningを有効にすることで多くの仮想マシンはメモリを解放し始めます。これによってよりサーバとして空きメモリが拡大し、より多くの仮想マシンを起動できるようになります。しかしこれだけだと各仮想マシンはメモリ不足によって、あるいはメモリを動的に獲得する処理が遅延することによって性能が劣化する可能性があります。この問題を解決するためにサーバ全体としてある程度の空きメモリを用意しておき、それを遅延なく必要に応じて割り当ててあげる仕組みがTranscendent Memoryです。サーバ全体としてメモリプールを持つことでゲストOSが個別にすべてのメモリを保持する形態よりも少ないメモリで効率的なキャッシングが可能になります。
もちろん環境によって効果に差異はあると思いますが、特にpage cacheを活用するファイルサーバ、アプリケーションサーバではこの二つを組み合わせることによって集約密度を上げながら性能劣化を抑えられる可能性があります。逆にpage cacheを活用しない傾向が強いデータベースサーバではTranscendent Memoryはそれほど効果がないでしょう。ただしSelf-Ballooningで不要なメモリを綺麗に削ぎ落として他の仮想マシンやTranscendent Memory Poolで利用できるようにすることは意義があると思います。
このSelf-BallooningとTranscendent Memoryついて具体的な構築手順を別ポストにて解説しようと思います。