Plan9日記

2014-12-22

AIST Super Green CloudにおけるCloudStack運用話

本エントリはCloudStack Advent Calendar 2014の22日目のエントリとして書きました。

はじめに

今年の7月からApache CloudStackを用いてプライベートクラウドを運用しています。オープンソース版のCloudStackを155台(プロセッサ数3100)の計算機で運用するというのは、それなりの規模だと自負しています。InfiniBand + PCIパススルーでHPC用途でも使える性能を持った仮想クラスタを提供するという点が目玉です。詳細は次の2つのスライドを参照してもらうとして、本エントリでは、現在に至るまで遭遇したCloudStackの問題をまとめてみました。

プライマリストレージローカルディスクセカンダリストレージがS3互換のCephオブジェクトストレージという具合に、一般的な構成とはちょっと違っているのでコーナーケースをいろいろ踏んでいる模様です。通常はプライマリストレージとしてNFSなどの共有ストレージが使われます。CloudStackでは、スケジューラが選んだホストにVMデプロイし、何か問題があると、VMマイグレーションで別ホストに動かすという処理を行うことがあります。共有ストレージの場合はまったく問題ないのですが、ローカルストレージだとマイグレーションできず、そこでジ・エンドです。例えば、以下のリストには挙げてませんが、仮想クラスタを作成するとき、複数のVMを同時並行にデプロイします。この際、タイミングによっては、スケジューラは同じホストを選択することがあります。しかし、PCIパススルーを使う場合はホストに1 VMしか実行できないので、後続のVMリソース不足でデプロイに失敗します。すると、そのVMを次の候補のホストにマイグレーションしようとするのですが、前述のようにプライマリストレージがローカルストレージだとマイグレーションに失敗し、デプロイもエラーになります。(補足:PCIパススルー拡張の有無に関わらず、デプロイに失敗した場合にこの問題は起きえます。)

当初はMLやJIRAにリポートしても反応が薄く(というか無反応)でかなり気持ちが萎えたのですが、年末に近づくにつれパッチも取り込まれ始め安堵しています。まだまだ抱えている問題は山積しているので、来年は開発コミュニティに対してもっとプレゼンスを上げていきたいと考えています。また、運用で得た知見も別途機会を設けて共有したいですね。

運用中に踏んだ地雷リスト

以下に、我々が遭遇した不具合を列挙します。なお、我々はバージョン4.3を使っており、独自に開発したSR-IOV対応パッチを取り込んでいます。以下でたびたび「sriov-43」というgitブランチ名が出てきますが、これはプライベートなgitリポジトリのブランチです。

1. cloudstack-agent jsvc gets too large virtual memory space. (JIRA #7951)

物理メモリの搭載量の大きいマシンで、cloudstack-agent が過剰に仮想メモリを確保するため、インスタンス作成時にQEMUがメモリを確保できず起動に失敗する場合がある。cloudstack-agent のメモリ使用量を制限するパッチを作成した。パッチは本家に報告して取り込まれた。

ホスト起動時は問題ないが、数日経つとVMデプロイに失敗するという現象が発生する。メモリリーク等を疑ったが、結局cloudstack-agentの問題だった。cloudstack-agent(jsvcプロセス)が30GB超のメモリを確保していた。

2. listUsageRecords generates NPEs for expunging instances (JIRA #6472)

アカウンティング情報を取得する API を呼び出す際に、破棄されたリソースがあると NullPointerException が発生する不具合があった。修正パッチが既に本家に取り込まれていたが、この修正に不十分な部分があり、NullPointerException は発生しないものの必要な情報(virtualmachineid)が含まれない状態で結果が返ってきていた。取得情報に virtualmachineid も含める修正パッチを作成し、本家に報告して取り込まれた。

3. Duplicate usage records when listing large number of records (JIRA #2625)/Small page sizes return duplicate results (JIRA #3401)

アカウンティング情報を取得する際の SQL 文が適切ではなく、ページサイズ等の条件によっては内容の重複する結果が返ってくる場合があった。既知のバグでありパッチも存在したので、sriov-43 ブランチにcherry-pick した。

4. Public key content is overridden by template's meta data when you create a instance (JIRA #6869)

インスタンスROOT ボリュームからテンプレートを作成すると、そのインスタンスの下記の情報もテンプレートの属性情報として記録されていた。

そのテンプレートから新しいインスタンスを作成する際、user data 経由でSSH 公開鍵を渡そうとしても、強制的にテンプレート付属の SSH 公開鍵がインスタンスに渡されていた。本家に報告後、開発者(Harikrishna Patnala)により修正パッチが作成されたので、sriov-43ブランチにcherry-pickした。

5. Attaching a data disk created on local storage to a VM is failing (JIRA Migration of a VM with volumes in local storage to another host in the same cluster is failing #6802)/Migration of a VM with volumes in local storage to another host in the same cluster is failing (JIRA #6810)

プライマリストレージローカルディスクを使用する構成での不具合である。特定の物理マシンの host id を指定してインスタンスを作成すると失敗する場合があった。storage poolallocator の処理に不具合があった。既存のバグであり、パッチも存在したので、sriov-43ブランチにcherry-pickした。

6. Negative ref_cnt of template(snapshot/volume)_store_ref results in out-of-range error in Mysql (JIRA #6236)

セカンダリストレージに S3 を使用する構成での不具合である。セカンダリステージングストア上に作成されるテンプレートキャッシュ排他制御ができておらず、タイミングによってキャッシュの参照カウンタが -1になる場合があった。参照カウンタが -1 となったテンプレートはそれ以後使用できなくなる(ゴミとして残る)。本家に workaround する本パッチが報告されていたが、排他制御を行う根本的な対処ではなく、参照カウンタが 0 の時はそれ以上デクリメントしないという処理を追加するパッチであった。ただしこのパッチにもバグがあり、修正すべきメソッドとは別のメソッドに処理が追加されていたため、我々で修正した上でsriov-43ブランチに適用した。

7. [S3] Parallel deployment makes reference count of a cache in nfs secondary staging store negative(-1) (JIRA #7539)

上記のパッチ(CLOUDSTACK-6236)適用後も別の処理で参照カウンタが -1 になる現象が発生したため、根本対策としてキャッシュの処理部分に lock による排他制御を追加するパッチを作成した。本家に報告、パッチの送付を行ったが、未だに放置されている。

8. Can't create proper template from VM on S3 secondary storage environment (JIRA #7412)

セカンダリストレージに S3 を使用する構成での不具合である。インスタンスのボリュームからテンプレートを作成する際にも、セカンダリステージングストア上でボリュームがキャッシュされる不具合があった。同じインスタンスのボリュームから複数回テンプレートを作成すると、2回目以降はプライマリストレージ上のオリジナルのボリュームではなく、セカンダリステージングストア上のキャッシュされた古いボリュームからテンプレートが作成されていた。インスタンスのボリュームからテンプレートを作成する際は、セカンダリステージングストアでキャッシュしないパッチを作成した。パッチは本家に報告して取り込まれた。

9. Fails to attach a volume (is made from a snapshot) to a VM with using local storage as primary storage. (JIRA #8085)

これもプライマリストレージローカルディスクの場合に起きる(マイグレーションを前提としていることに起因する)バグ。スナップショットから作成したボリュームがアタッチできない。バグ報告済み。

クラスタ管理ソフトウェアとの相性

ASGCのもう一つの特徴として、いわゆるスパコン上でクラウドを運用している点が挙げられます。ASGCのハードウェアは、Cray社製のスパコン(PCクラスタ)です。Crayのスパコンには標準のクラスタ管理ソフトウェアとしてACEが搭載されており、ASGCでも使っています。ACEスパコンとして運用することを前提に作られたソフトウェアなので、CloudStackなどのクラウドミドルウェアを動かすことは念頭になく、ホストでcloudstack-agentが動作するまでに結構苦労しました。この手のクラスタ管理ソフトウェアクラウドミドルウェア親和性が高くなると、運用する側としてはとってもうれしいです。

ACEでは、ネットワークブートでディスクイメージを各ホストに展開しますが、/work以外のディレクトリはread onlyになります。一般的なスパコン運用であればこれで問題ないのですが、これではCloudStackは動きません。具体的には、次のような問題があり、地道に問題を潰していきました。ファイル一つの変更でもディスクイメージの作り直しが必要になります。。

  • /etc や /var/lib/libvirt 上のファイルが編集できない。/etc/cloudstack/agent/agent.properties などの cloudstack-agent が書き換える事を前提としているファイルを全て洗い出し、それらのファイルを /work に移しシンボリックリンクを貼る。
  • /etc/{cgconfig.conf,cgrules.conf} など、CloudStack 関連以外のファイルも cloudstack-agent が書き換えるため、/work に移してリンク

謝辞

上記の問題を解決し、日々ASGCの安定運用に尽力しているASGCサポートチームの面々(少数精鋭!)に感謝して、本エントリを閉じます。

2014-12-13

Programming -- Principles and Practice Using C++

C++のお勉強に、Stroustrupの「Programming -- Principles and Practice Using C++」略してPPPを読み始めた。言語の学習は原典というか、作者の本をまず読むことにしているんだけど、「The C++ Programming Language」の方ではなく、こっちを選んだ。ちなみにTC++PL3の翻訳は持っているけど、全然読めてない。。

実行環境はMac OS X 10.10なのでclang。公式ページからstd_lib_facilities.hをダウンロードしておく。

以下、メモ。

2章から7章までプログラムを動かしながら読む。プログラミングの初心者向けの内容なので、特にC++どっぷりという内容ではない。Hello Worldから始まり、数式をパースして四則演算を行うプログラムを作ってみる。この内容で250ページも書くんだからなぁ。。

  • 3.9.2 unsafe conversions
    • narrowingの説明
    • C++11にはbrace-initializationってのがあって、narrowingをerrorにできる。
  • 4.3.1 constant expressions
    • const以外にconstexprってのがある。コンパイル時に定数とわかるものについてはconstexprと書ける。
  • 4.6 vector
  • 5.6 exceptions
    • 例外のさわりを紹介
  • 6. Writing a program
    • user-defined typeの実現としてclassを導入。structは出てこない。
    • expression()で再帰を導入。
  • 7. (6の拡張)
  • 8.
    • scopeとかpass-by-value、pass-by-(const-)reference。当然pointerはまだ出てこない。
    • 関数呼び出し時のスタックの挙動
    • だんだんstd_lib_facilities.hで隠蔽されていたことが明らかになってくる。

2014-12-01

OSv雑感

次のスライドは@syuu1228さんの「OSvの概要と実装」。

  • ライブラリOSが流行っている感じもするので、そのうちまとめておきたい。USENIX ATCのOSvの発表を聞いて、タネンバウム教授がexokernelと何が違うみたいな質問をしてたそうな。
  • ユーザ空間がなくカーネル空間のみという割り切りはすごい。ハイパーバイザが最後の砦になるので、よいという判断カーネルじゃなくてライブラリと考えればそんなものかとも思うが、カーネルアプリが同じメモリプールからmallocするとなると、ちょっとしたオーバランでカーネルをぶっ壊してしまいそう。
  • アプリからPF filterやnet channelにフックを仕込んでパケットを奪って処理することが可能。実装の雰囲気としてはカーネルモジュール
  • ttyないのでエディタを開発するのは難しい。REST APIを利用して外部からファイルを流し込むのがOSv流。
  • Dockerと狙いがかぶってそう。完全なisolationが一つの鍵か?
  • Virtual Appliance的な利用を想定しているようだ。
  • 元々ゲストOS上で動くことしか考えてなかったが、実はベアメタルで動きそうなぐらいレガシーデバイスがサポートされつつある。もう一息でベアメタルで動いてしまったり?
  • Huaweiがaarch64サポートを実装。

2014-11-11

gitから任意のバージョンのLinuxカーネルソースコードをチェックアウトするメモ

何はともあれgit clone。

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

Linuxカーネルでは、3.x.y系列ごとにブランチがあり、リリースバージョンにタグを付けることになっている。なので、ソースコードをチェックアウトする方法は2つ。ブランチ(linux-3.x.y)をチェックアウトする方法と、タグ(v3.x.y)でリリースバージョンをチェックアウトする方法。

まずはブランチから。git branch -aで本家のブランチがずらずらでてくるので、見たいバージョンを探す。

$ git branch -a

あとは任意のバージョンをチェックアウトするだけ。

$ git checkout -b linux-3.10.y origin/linux-3.10.y

続いてタグ。git tag -lでずらずらでてくる。

$ git tag -l

タグを指定して、チェックアウト。

$ git checkout -b v3.10 v3.10

ここではローカルリポジトリにブランチを作っているけど、もちろん「-b xxx」を指定しなくてもOK。

ソースコードリーディングのお供としてctagsをと思ったけど、CentOSのvimだとcscopeがデフォルトっぽいので、cscopeのタグファイルを作っておく。

$ make cscope ARCH=x86

2014-11-08

SimGrid

分散システムのシミュレータに仏INRIAが開発しているSimGridってのがある。メルボルン大のCloudSim(その前にGridSimってのもあった)とは別物。SimGridは大抵のUNIXシステムに対応しているので、OSXでも動くのだが、homebew用のformulaもあったので、サックリ動かすことができた。

ただ、ソースパッケージの中にはサンプルコードもいろいろあるので、ダウンロードしてそっちも眺めてみることを勧める。例えば、examples/msg/sendrecvってのは単純な2プロセス間でのメッセージ送信になる。

$ cmake CMakeLists.txt
$ make

sendrecvという実行ファイルが生成される。以下が実行結果。platform_sendrecv.xmlでホストやネットワークトポロジを定義し、deployment_sendrecv.xmlプロセスをどのホストでデプロイするか定義する。

$ ./sendrecv platform_sendrecv.xml deployment_sendrecv.xml 
[0.000000] [msg_test/INFO] test_all
[Inmos:sender:(1) 0.000000] [msg_test/INFO] sender
[Inmos:sender:(1) 0.000000] [msg_test/INFO] host = Bellevue
[Inmos:sender:(1) 0.000000] [msg_test/INFO] task_la->data = 0.000000e+00
[Bellevue:receiver:(2) 0.000000] [msg_test/INFO] receiver
[Bellevue:receiver:(2) 1.301011] [msg_test/INFO] Task received : latency task
[Bellevue:receiver:(2) 1.301011] [msg_test/INFO] Communic. time 1.301011e+00
[Bellevue:receiver:(2) 1.301011] [msg_test/INFO] --- la 1.301011 ----
[Inmos:sender:(1) 1.301011] [msg_test/INFO] task_bw->data = 1.301011e+00
[Bellevue:receiver:(2) 1085.076238] [msg_test/INFO] Task received : bandwidth task
[Bellevue:receiver:(2) 1085.076238] [msg_test/INFO] Communic. time 1.083775e+03
[Bellevue:receiver:(2) 1085.076238] [msg_test/INFO] --- bw 922700.551985 ----
[1085.076238] [msg_test/INFO] Total simulation time: 1.085076e+03

platform_sendrecv.xmlの定義では、InmosとBellevueの間の遅延は100ミリ秒なのに、実行結果が1.3秒とはこれ以下に? platform_sendrecv.xmlの遅延を半減したり倍増して再実行してみたけど、やっぱり一桁結果が違う。バンド幅は100Mbpsという定義なので、ほぼあっているけど。

(追記)マニュアルによると、デフォルトネットワークモデルLV08ではTCP slow startをモデル化するために、遅延が10.4倍になるとかある。うぅ、なぜそんなモデル化になるのか、よくわからん。