OpenStackの設定と格闘していました

おはようございます。ライトノベル好きのツチノコです。

さて、先日までOpenStackの検証環境を作って検証をしていました(Mitaka Release)。
その時につらかったことの1つが、設定項目に設定するべき値やそもそも項目自体の存在がわからないということでした。
結果としてドキュメントやdaemon起動時の設定値のダンプを見ていろいろと悩んで解決できたのですが、そもそも設定値がどこで定義されているかをmain関数から追いかけてみました。

novaを例にとるとmain関数はcmd/以下にあります。
cmd/api.pyを例に読んでいきます。

37行目にそれっぽい部分があります。

CONF = nova.conf.CONF

nova.conf.CONFはconf/__init__.pyで定義されています。
cfg.CONFはoslo_config.cfg.CONFというグローバル変数で、その下にそれっぽい関数があります。

CONF = cfg.CONF

api.register_opts(CONF)
availability_zone.register_opts(CONF)
base.register_opts(CONF)
cache.register_opts(CONF)
cells.register_opts(CONF)

この関数の実態はconf/api.py#L403にあります。
それで上のほうを見ると、OptGroup(confファイルで[api]などのセクションになる)とOpt(confファイルでauth_stratedy=…_というオプションと値となる)が定義されているところが見つかります。

api_group = cfg.OptGroup('api',
    title='API options',
    help="""
Options under this group are used to define Nova API.
""")

auth_opts = [
    cfg.StrOpt("auth_strategy",
        default="keystone",
        choices=("keystone", "noauth2"),
        deprecated_group="DEFAULT",
        help="""
This determines the strategy to use for authentication: keystone or noauth2.
'noauth2' is designed for testing only, as it does no actual credential
checking. 'noauth2' provides administrative credentials only if 'admin' is
specified as the username.
"""),

まとめ(novaの場合)
・conf/*.py に各オプションの定義があります。
・import nova.conf した段階で各オプションがCONFに登録されます。

他の(いまのところドキュメントが充実していない)プロジェクトもこうやっていけばオプションにたどり着けるはずです。

おまけ
こんな感じで全ファイルをロードしてregister_opts関数を呼べばひょっとしてオプションのリストができるのではということを思いつきました。何事も暴力で解決するのが一番だ。

for 全ファイル
    import モジュール as dummy
    dummy.register_opts(conf)
    print(conf)

結果のnova.txt(348KBあります)の一部です。

[DEFAULT]

(snip...)

[api]

(snip...)

auth_strategy = keystone
# class:      
# deprecated: False
# multi:      False
# required:   False
# help:
# This determines the strategy to use for authentication: keystone or noauth2.
# 'noauth2' is designed for testing only, as it does no actual credential
# checking. 'noauth2' provides administrative credentials only if 'admin' is
# specified as the username.

わーい。

生成に利用したツールは以下の場所にあります。
リポジトリ
プロジェクトごとに生成したテキスト
中間生成されるjsonの例

ドキュメントがあればそちらを参照するのがよいですが、今のところドキュメントが見当たらないdesignate/magnumなども生成できますので、これはこれでよいかなというところです。

今後もいろいろ実験していこうかと思います。

P.S. 発売日が近い本の中でぜったい転職したいんです!! ~バニーガールは賢者を目指す~が気になっています

OpenStack Summit October 2016 – Barcelona 3日目に参加していました

おはようございます。ライトノベル好きのツチノコです。

OpenStack Summit October 2016 – Barcelonaに参加していますので、3日目(10/27)の様子をお伝えします。
3日目はKeynoteがないので、会場の外観です(1日目・2日目と天気がいまいちでようやく晴れのきれいな写真が撮れた)。

ccib

Keynoteがないのでおすすめのセッションです。

Ceph, Now and Later: Our Plan for Open Unified Cloud Storage
Red HatのSage WeilさんによるCephの現状と将来のプランについてです。

重要そうなトピックは3つ。
・(やや古いニュースですが)Ceph Filesystemが安定になりました
Ceph BlockやCeph Objectは”AWESOME”だったけど、Ceph Filesystemも”AWESOME”になったということで会場は盛り上がってました。

・新しい種類のメモリ
そろそろIntel 3D XPointなどのPersistent Memoryのことを考えないといけない時期です。
特性は、Flashと比較してアクセス速度が速いけど容量が小さくて高い。
FlashとHDDの使い分けを考えたように、Persistent Memoryのことも考えましょう。

・新しいBlueStore(=block+newstore) backend
これまでのFileStore backendにかわって新しいbackendになります。Krakenリリースですでにstableとのこと。
どうもErasure Codingでのファイル書き換えなどがこのbackendに依存しているようです。

会場でいろいろ話を聞いていてもみんなCephを使っている感じで、Ceph関連セッションの人の入り方はよかったです。このセッションは本家の発表だけあって満員。
(逆にベンダが製品を押すセッションはがらがら・・・)
OpenStack界隈ではdefaultになりつつありそうです。

こちらもCephを使っているVolkswagenの事例のセッション。
OpenStack and Cars – The OpenStack Journey of the Volkswagen Group

ちょっとサーバ1台あたりの容量を計算してみます。
・Volkswagenの事例では150serversで840TBのCephストレージ。サーバ1台当たりに直して5.6TB/server。
・1日目のDreamHostの事例ではサーバ1台当たり960GB SSDが8本、二重化されてると推定すると3.8TB/server。

Web屋さんの感覚からすると大分大きいですが、社内インフラや各種研究データを抱えようとするとこれくらいが必要なのかもしれません。
1日目KeynoteでもあったようにOpenStackがTechnology Company以外にも適用が進んでいるというのをひしひしと感じます。

おわりに:
3日にわたってOpenStack Summitの様子を少しずつですがご紹介しました。
今回のOpenStack Summitでは、OpenStackはOpenでCollabolativeだというメッセージを強く打ち出していたように思います。
今後もその方針が継続されるとよいですね。

closed

OpenStack Summit October 2016 – Barcelona 2日目に参加していました

おはようございます。ライトノベル好きのツチノコです。

昨日に引き続きOpenStack Summit October 2016 – Barcelonaに参加していますので、とりいそぎ2日目(10/26)の様子をお伝えします。

2日目もKeynoteから始まりました。Jonathan Bryceさん(OpenStack Foundation)によるMulti-Cloudの話です。

keynote

すでにEU内では複数のOpenStackベースのPublic Cloudが立ち上がっています。

特にヨーロッパではEU外へのデータ持ち出しに関する規制が厳しいため、EU内にデータをとどめておきたい事情があります。
これに対応するため、OpenStackが使ってCloudを作るという選択がされることが多いようです。
(例えばtwitterをEU内から見ると、「Twitterのサービスを利用すると、Cookieの使用およびEU外へのデータ転送に同意したことになります。Twitterとそのパートナーは、アナリティクス、カスタマイズおよび広告目的も含めて、世界中でサービスを提供し、Cookieを使用します。 」という通知が表示されます)

こちらは会場の壁にあったヨーロッパのOpenStackで構築されているPublic Cloudのリストです(Keynoteでも同じものを出して説明していた)。

euro_public_cloud

さて自由にコンポーネントを組み合わせるOpenStackで避けて通れない問題が、互換性です。
このOpenStackで動いているApplicationを他のOpenStackに移せるだろうか?Distributionに(もしくは自分たちのDeployに)ロックインされていないだろうか?は常に問題となります。

それに対するデモの様子がこちらです。
OpenStackの各Distribution(Mirantis, SUSE, Ubuntu, Huawei, etc.,etc.,)で同時にwordpressをdeployしてます。
もちろん、と言える状況がすごいのですが、全員がdeploy成功して会場は盛り上がっていました。

interop_demo

今日のおすすめセッションは以下です。

おまけ: なぜか廊下で行われている #vBrownBag の様子です。

vbrownbag

OpenStack Summit October 2016 – Barcelona 1日目に参加していました

おはようございます。ライトノベル好きのツチノコです。

早速ですが現在開催中のOpenStack Summit October 2016 – Barcelonaに参加していますので、とりいそぎ1日目(10/25)の様子をお伝えします。
(10/23-10/28のうち、10/25-10/27のメインのSummitに参加予定です)

初日には毎回恒例のMark CollierさんのKeynoteがあります。

keynote_mark

今回のテーマはWorld Runs on OpenStack(#RunsOnOpenStack)ということで、すでにOpenStackは様々な分野で利用されているということにフォーカスが置かれていました。なんとOpenStackの利用者のうち、80%がTechnology Company以外のとのこと。

その代表のひとりとして呼ばれたCERNのTim Bellさん。
Scienceの分野でもOpenStackは利用されています、というかCERNは世界で見ても大きいデプロイのひとつ・・・(CERNのOpenStackブログ)

keynote_cern_tim

さて、Markさんのお話で発表された重要なニュースですが、OpenStackのロゴが新しくなります。flat-designになります。
こちらは会場で見かけた新ロゴの写真です。

openstack_new_logo

みなさん気になるセッションはすでに動画を見てらっしゃると思いますが、面白かった or 役に立つセッションを紹介しておきます。

  • Deploying OpenStack with Neutron and Ceph: From Concept to Public Cloud (and Hell in the Middle)
    • DreamHostのデプロイ例
    • 当初想定: Storageを重要視してCephを選択、顧客がコア数を要求するのでAMD Processorを選択
    • ベータやってみて: HDD遅いし壊れる、顧客はコア数ではなく周波数を要求
    • 今のデザイン: 全部SSDでComputeとStorageが同居するConvergedに、Intel Processorを選択
  • Monasca: One Year Later
    • Monascaがうまれて1年が経ちましたというProject Update
    • そのうちZabbixやnagiosにとって代わる日が来るんでしょうか
  • Message Routing: A Next-Generation Alternative to RabbitMQ
    • MQのBrokerは遅いしScaleしないからRouterにしよう、という内容
    • BrokerがいったんメッセージをQueueに入れるのに対して、Routerはメッセージの宛先を見てQueueに入れずに送る

ほかにも面白そうなセッションありましたが時間が被ってて聞けなかった・・・・

それではまた、2日目の記事でお会いしましょう。

oslo.messaging で RPC を実装

 こんにちは、インフラ本部の大山裕泰です。
 今日は OpenStack の共通ライブラリ群 oslo に含まれる olso.messaging を使って RPC over MQ 処理を実装してみます。なぜ RPC を MQ を介して行うと良いかについては 過去のエントリ で書きましたので、興味があれば読んでみてください。

oslo って何?

 oslo は OpenStack の各コンポーネント (OpenStack の最も大きなソフトウェアモジュールの単位) で共通で利用するライブラリを集めたプロジェクトになります。
 その昔の OpenStack では設定ファイルやコマンドライン引数の解析、メッセージパッシング、ロギングなどといった処理が各コンポーネント毎に個別に存在しており、開発・メンテナンスコストが掛かる問題がありました。
 そして Grizzly サイクルで共通ライブラリ群を提供する olso プロジェクトが発足し、Havana で設定ファイルとコマンドライン引数の解析を行なう oslo.config と、通知や RPC の仕組みを提供する oslo.messaging がリリースされました。現在では、国際化や並行処理など様々な機能が加わり、本稿執筆時点では 34 のライブラリ が存在します。

 oslo 自体は OpenStack のプロジェクトですが、用途は OpenStack に限定されません。例えば oslo.config は、設定ファイルとコマンドライン引数の解析を行なうライブラリとして広く知られており、NTT Communication などが中心となって開発している SDN Framework Ryu などで採用されています。
 今回紹介する oslo.messaging では、RabbitMQZeroMQ などの MQ システムを介した通知や RPC の仕組みを提供します。

なぜ oslo.messaging なのか?

 oslo.messaging の使い方について見て行く前に、oslo.messaging についての理解を深めるために、なぜこの仕組みを使うのかについて考えてみたいと思います。
 MQ を利用した通知や RPC の仕組みは、もちろん oslo.messaging が登場する以前から存在していました。RabbitMQ を使う場合には Pika という AMQP ライブラリを用いてそれらの処理を行なうことができます。また ZeroMQ を使う場合には、PyZMQ ライブラリを用い、Kafka にも 同様の Python ライブラリ が存在します。

 しかしこれらを用いることによって、ミドルウェアないはプロトコル依存の実装になってしまいます。
 oslo.messaging では、ミドルウェア・プロトコル非依存の通知、RPC の仕組みを提供しており、これによってユーザは様々な MQ システムを選択することができるようになりました。

oslo.messaging の使い方

 以降では oslo.messaging を使って、汎用的な RPC over MQ 処理を行なう方法を紹介します。サンプルとして以下のコードを利用します。

https://github.com/userlocalhost2000/oslo-messaging-examples

 コードの中身を見る前に、システムのアウトラインについて簡単に把握したいと思います。以下は oslo.messaging と他のシステムとの関連、及び内部アーキテクチャについて表した図になります。

 処理のおおまかな流れとしては、左上の “User Application” が “RPCClient” で定義されたインターフェイスを叩き、”Transport” オブジェクトで抽象化された MQ システム (RabbitMQ など) を経由して “Server” に登録された “Endpoint(s)” の処理を実行し結果を取得します。ここでは、oslo.messaging レイヤにおけるクライアント、サーバ側の内部の仕組みについて簡単に解説します。

 クライアント側では RPCClient オブジェクトがユーザアプリケーションに対して、RPC 処理の仕組みを提供します。また Transport オブジェクトが、RabbitMQ や Kafka , ZeroMQ などの各種 MOM を抽象化し、ユーザは RPCClient が提供するインターフェイスを通して MOM 非依存な RPC リクエストをサーバに送ることができます。
 サーバ側では、ユーザからの RPC 要求を処理する Server オブジェクトを生成します。その際、ユーザ側で各 PRC 要求に対応する処理 (Endpoint) を一つ以上実装してやり、それらを Server オブジェクト生成時に指定します。
 また Server 及び Endpoint(s) に対して RPC API の名前空間と互換 version について設定することができます。これらの設定を保持したものが Target オブジェクトになり Server 及び Endpoint にひも付きます。
 Endpoint オブジェクトにおいて Target を省略した場合には、グローバルな名前空間と version1.0 が暗黙的に設定されます。ただし Server オブジェクトにおいては Target オブジェクトを topic 及び server パラメータ付きで指定しなければなりません。
 Target オブジェクトの topic パラメータは、サーバが提供する API を識別するための項目で amqp ドライバにおいては名前付きキューの名前に対応します。クライアントはこの値だけを知っていれば、サーバの場所を意識せずにサーバに対して RPC 要求を送ることができます。
 また Target オブジェクトの server パラメータは、文字通り API を提供するサーバを指定する項目ですが、実際に存在するサーバのホスト名ないしは IP アドレスを指定しなければならないわけではく、サーバを指定する任意の文字列になります。これはクライアントが topic パラメータで指定した API を持つサーバ群のうち、特定のサーバに対してメッセージを送りたい場合に利用されるパラメータになり amqp ドライバにおいては、topic 名で指定した名前付きキューに加えて、”${topic}.${server}” の名前付きキューを生成します (${topic} と ${server} にはそれぞれパラメータの設定値が入ります)。

動かしてみる

 各データ構造の役割と関連がわかったところで、サンプルコードを見ながら実際に動かしてみます。
 まずサンプルコードを動かすために oslo.messaging をインストールします。またここでは Python 2.7.6 を使用しています、尚本稿執筆時点で OpenStack がサポートしている Python のバージョンは 2.7.x と 3.4.x になります [*1](https://wiki.openstack.org/wiki/Python3)。

$ pip install oslo_messaging

 続いて次のサンプルコードを GitHub から取得します。

$ git clone git@github.com:userlocalhost2000/oslo-messaging-examples.git

 サーバ側のコード `src/server.py` について簡単に解説します。以下がその抜粋になります。

     7	URL = 'rabbit://guest:guest@localhost:5672/'
     8	
     9	class TestEndpoint(object):
    10	  target = oslo_messaging.Target(namespace='foo', version='1.2')
    11	
    12	  def hoge(self, ctx, arg):
    13	    print("[TestEndpoint] hoge(%s, %d) is called" % (ctx, arg))
    14	    return arg * 2
    15	
    16	transport = oslo_messaging.get_transport(cfg.CONF, url = URL)
    17	target = oslo_messaging.Target(topic='test01', server='server1')
    18	endpoints = [
    19	  TestEndpoint(),
    20	]
    21	
    22	server = oslo_messaging.get_rpc_server(transport, target, endpoints)

 22 行目の get_rpc_server メソッドの呼び出しで Server オブジェクトを生成します。RPCClient からの RPC 要求に対して endpoints パラメータで指定したオブジェクトにマッチするメソッドを呼び出します。その際、エンドポイントオブジェクトに target メンバが設定されている場合には、namespace と version ネゴシエーションの確認を行います。target メンバが指定されていない場合には、デフォルトの namespace (=None) と version (=1.0) が内部的に設定されます。
 コールバックメソッド `hoge()` のパラメータはそれぞれ、`ctx` がユーザ定義のオブジェクト (ディレクトリ型) を表し、`arg` がユーザ定義の引数を表します。

 次にクライアント側のコード `src/client.py` についても簡単に見て行きます。以下がその抜粋になります。

     6	URL = 'rabbit://guest:guest@localhost:5672/'
     7	
     8	class TestClient(object):
     9	  def __init__(self, transport):
    10	    target = oslo_messaging.Target(topic='test01')
    11	    self.client = oslo_messaging.RPCClient(transport, target)
    12	
    13	  def hoge(self, ctxt, arg):
    14	    cctxt= self.client.prepare(namespace='foo', version='1.1')
    15	    return cctxt.call(ctxt, 'hoge', arg = arg)
    16	
    17	transport = oslo_messaging.get_transport(cfg.CONF, url = URL)
    18	client = TestClient(transport)
    19	
    20	print(client.hoge({}, 10))

 20 行目でユーザ定義の RPCClient ラッパーの hoge を呼び出し、内部的に 15 行目でサーバに対して hoge メソッドの呼び出しを行っています。その際 14 行目の prepare() メソッドの呼び出しで RPCClient オブジェクトが内部で持つ Target オブジェクトの namespace と version パラメータを上書きします。
 version パラメータがサーバ側のエンドポイント hoge() で指定した値と一致していないことに気づいたかもしれません。Server 側のバージョンネゴシエーション処理では、クライアントからの要求 version のメジャーバージョン (上の位) が一致しており、かつマイナーバージョン (下の位) がサーバで設定した値以下であれば、互換性がある要求として当該メソッドを実行し結果を返します。

 それでは、実際にこれらを実行してみます。次のようにターミナルからサーバスクリプト `src/server.py` を実行し、次の別のターミナルを開いてクライアントスクリプト `src/client.py` を実行してみてください。


(左:サーバ、右:クライアント)

 クライアント側からの呼び出しでサーバ側で定義したエンドポイント hoge() が呼び出され、クライアント側で実行結果が受け取られていることが確認できました。