めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

Red Hat Storage 2.0Beta1のSwift API

注意

この記事は、開発版の古いGlusterFSに基づいています。GlusterFS3.3のGA版が公開されていますので、GA版での利用については、こちらの手順を参照してください。

何の話かというと

まだ一般公開はされていませんが、Red Hat Storage 2.0(RHS2.0)Beta1が某社内では利用可能になっています。ここでは、RHS2.0Beta1のSwift APIの利用方法を紹介します。

RHS2.0は、某社が提供予定のSoftware Storage製品で、GlusterFSをコアコンポーネントとしています。RHS2.0に含まれるGlusterFSの機能は、GlusterFS3.3のGA版にバックポートされる予定ですので、この文書の内容は、GlusterFS3.3を利用する際にも活用いただけるはずです。多分。

なお、Swift API部分のRPMは一般公開されていますので、現行のGlusterFS3.3Betaあたりと組み合わせて試していただくことは可能です。(ここにあるものが、RHS2.0Beta1に一番近いGlusterFS3.3Betaと思われます。)

全体構成

基本的な構成は下図になります。(ネットワークアドレスは、筆者のテスト環境のものです。)

GlusterFS Clientとして、GlusterFSのボリュームにアクセス可能なサーバ(swift01)がSwiftのProxyサーバの役割を果たして、クライアントからのアクセスを受け付けます。本家Swiftのアーキテクチャでは、その他に、Account/Object/Containerなどのコンポーネントがありますが、ここでは、GlusterFSがこれらの機能を代替しています。

ユーザ認証については、外部の認証サーバ(Keystone)を利用することもできるはずですが、まだ設定方法などの手順が確認できていません。。。。ここでは、Proxyサーバに同梱の簡易認証機能(TempAuth)を利用します。この図では、Proxyサーバがボトルネックになりそうですが、実際には、Proxyサーバを並列にならべてスケールアウトすることも可能です。

開発元に問い合わせた所、TempAuth以外のユーザ認証については、現在計画中とのことでした。もともとSwiftの代替のためだけに本機能を開発しているわけではないので、単純にKeystoneと連係させるというわけではなく、GlusterFS環境全体に適用できる統合認証機能の実装を計画しているとのことです。

動作概要

Swiftでは、「アカウント」と呼ばれる単位でユーザがグループ化されます。同じアカウントに属するユーザは、共有するアカウント内部に複数のコンテナを作成して、各コンテナの中にオブジェクト(ファイル)を保存します。

GlusterFSを使用する場合は、1つのアカウントに対して、GlusterFSのVolumeを1つ割り当てます。Proxyサーバ上で、該当のボリュームが「/mnt/gluster-object/AUTH_<アカウント名>」にマウントされて、この中にサブディレクトリとしてコンテナが作成されるという、非常にシンプルな仕組みになります。

ボリュームの実体は、バックエンドのGlusterFSサーバが分散処理します。ボリュームの構成はまったくの任意ですので、要件にあわせて、レプリケーション、ストライピング、ファイル単位での分散などを自由に組み合わせることができます。ボリュームの容量の動的な伸縮もGlusterFSの機能で可能です。

なお、Proxyサーバ以外のGlusterFSクライアントで該当のボリュームを同時にマウントして、ボリューム内のファイルを操作することも可能です。ボリューム内にファイルを配置すると、Swift APIからも同じファイルがオブジェクトとして見えるようになります。つまり、Swift API(REST)でアクセスしたいアプリケーションと、FUSE/NFSなどで普通にマウントしてアクセスしたいアプリケーションで自然な形でファイル共有が可能になります。(RHS2.0はHadoop APIもあるので、Swift APIでためたファイルをHadoopでMapReduceするなども可能になります。)

※GlusterFSサーバ自体にProxyの機能を持たせることも可能ですが、今回の構成のようにProxyサーバは外だしすることが推奨です。RHS2.0に含まれるRHEL6は、GlusterFSのI/O処理に特化したチューニングが行われていますので、GlusterFS以外のアプリケーションの同居には適しません。

2012/04/19 追記

一般的には上記の通りなのですが、RHS2.0のGA版では、Swift APIはRHS2.0に同梱されており、GlusterFSサーバ上で直接にProxyを実行することが推奨になるそうです。

利用手順

まずは、「GlusterFSサーバ + GlusterFSクライアント」の環境を構築します。ここでは、RHS2.0Beta1を使用しますが、GlusterFSでがんばる場合は、こちらの手順を参考にしてください。この際、ブリックとして使用するデバイスは、マウントオプションに「user_xattr」が必要になりますので、注意してください。

使用するアカウント名に応じたボリュームは、GlusterFSで先に作成しておきます。ここでは、「vol01」「vol02」の2種類のボリュームを作成します。それぞれ、「vol01」「vol02」という名前のアカウントが使用することになります。

続いて、図のswift01をGlusterFSクライアントとして構成して、先のボリュームをFUSEマウントできることを確認します。確認できたら、一旦、マウントは解除してください。

ここで、いよいよ、Swift APIの導入です。次のコマンドで前提パッケージを入れて、memcachedをスタートしておきます。

# yum install memcached openssl python-setuptools python-paste python-paste-deploy python-configobj python-simplejson python-configobj
# easy_install-2.6 coverage
# yum localinstall http://yum.griddynamics.net/yum/diablo/python-greenlet-0.3.1-4.x86_64.rpm \
 http://yum.griddynamics.net/yum/diablo/python-eventlet-0.9.16-gd1.el6.noarch.rpm \
 http://yum.griddynamics.net/yum/diablo/python-webob-1.0.8-0.noarch.rpm \
 http://kojipkgs.fedoraproject.org/packages/python-netifaces/0.5/1.el6/x86_64/python-netifaces-0.5-1.el6.x86_64.rpm \
 http://kojipkgs.fedoraproject.org/packages/pyxattr/0.5.0/1.el6/x86_64/pyxattr-0.5.0-1.el6.x86_64.rpm
# chkconfig memcached on
# service memcached start

coverageの導入時にextentionモジュールが入らない警告がでますが、これは無視しておきます。続いて、Swift APIの導入です。

# yum install http://download.gluster.com/pub/gluster/glusterfs/3.2/UFO/swift-1.4.5-1.noarch.rpm \
 http://download.gluster.com/pub/gluster/glusterfs/3.2/UFO/swift-plugin-1.0.-1.el6.noarch.rpm

Proxyサーバの設定ファイル「/etc/swift/proxy-server.conf」を編集します。

まず、TempAuthの設定にあたる、「tempauth」エントリを次のように変更します。

[filter:tempauth]
use = egg:swift#tempauth
#user_<account>_<user name> = <password> [.admin]
user_vol01_admin = pas4vol01admin .admin
user_vol01_user01 = pas4vol01user01
user_vol02_admin = pas4vol02adm .admin
user_vol02_user01 = pas4vol02user01

これは、各アカウントのユーザとパスワードを指定します。異なるアカウントでは、同じ名前のユーザが存在しても構いません。最後に「.admin」が付いているものは、該当アカウントの管理者権限は持ちます。

次に、「cache」エントリを変更します。

[filter:cache]
use = egg:swift#memcache
memcache_servers = localhost:11211

これは、認証情報をmemcacheにキャッシュするための設定です。Swiftの認証では、最初にユーザ/パスワードを送って認証すると、対応するトークンが発行されて、それ以降は(トークンの有効期限が切れるまで)該当のトークンを送ると認証されるようになります。アプリケーションから使用する場合など、アプリケーションの起動時にユーザ/パスワードを入力してトークンを取得すると、それ以降は、トークン情報のみでアクセスが継続できます。アプリケーション内部にユーザ/パスワードを保存する必要がありません(その方がセキュリティ的に安全ですね)。

今回は、httpsでのアクセスできるように、SSL証明書も用意します。例によって(?)自己署名でお茶を濁します。

# cd /etc/swift
# openssl req -new -x509 -nodes -out cert.crt -keyout cert.key -days 36500 -subj "/C=JP/ST=Tokyo/CN=Swift API"

「proxy-server.conf」の「DEFAULT」エントリに下記の最後の3行を追加します。

[DEFAULT]
bind_port = 8080
user = root
log_facility = LOG_LOCAL1
bind_port = 443
cert_file = /etc/swift/cert.crt
key_file = /etc/swift/cert.key

次に、GlusterFSサーバとの接続に関する設定です。

まず、GlusterFSサーバの1つにパスワード無しのSSH接続を設定します。

# ssh-keygen
# ssh-copy-id rhs20-01

「/etc/swift/fs.conf」を次のように変更します。

[DEFAULT]
mount_path = /mnt/gluster-object
auth_account = auth
#ip of the fs server.
mount_ip = rhs20-01
#fs server need not be local, remote server can also be used,
#set remote_cluster=yes for using remote server.
remote_cluster = yes

「mount_ip」に、先にSSH接続を設定したGlusterFSサーバを指定して、「remote_cluster」をyesにします。

パスワード無しのSSH接続設定などが気持ち悪い場合は、Swift APIのノード自体もGlusterFSのpeerに加えて、ローカルノード指定でボリュームがマウントできる状態にしても構いません。この場合は、「GlusterFSサーバとの接続に関する設定」は不要になります。

2012/04/19 追記

前述のようにRHS2.0のGA版では、GlusterFSサーバ上で直接にProxyを実行しますので、上記がデフォルトの使い方になります。

以上で準備完了です。次のコマンドでSwift APIを起動します。

# swift-init main start
Starting proxy-server...(/etc/swift/proxy-server.conf)
Starting container-server...(/etc/swift/container-server/1.conf)
Starting account-server...(/etc/swift/account-server/1.conf)
Starting object-server...(/etc/swift/object-server/1.conf)

動作確認

まずは、RESTの口に対して、curlでダイレクトにHTTPパケットを投げて、内部的な動きを確認してみます。

vol01のadminユーザで認証して、トークンを取得します。

# curl -v -H 'X-Storage-User: vol01:admin' -H 'X-Storage-Pass:pas4vol01admin' -k https://swift01:443/auth/v1.0
(中略)
> X-Storage-User: vol01:admin
> X-Storage-Pass:pas4vol01admin
> 
< HTTP/1.1 200 OK
< X-Storage-Url: https://127.0.0.1:443/v1/AUTH_vol01
< X-Storage-Token: AUTH_tk6d17431d170e48b7aa8db543c5539e63
< X-Auth-Token: AUTH_tk6d17431d170e48b7aa8db543c5539e63
< Content-Length: 0
< Date: Fri, 13 Apr 2012 13:19:21 GMT
< 
* Connection #0 to host swift01 left intact
* Closing connection #0

取得したトークンで、コンテナ(container01)を作成します。

# curl -v -X PUT -H 'X-Auth-Token: AUTH_tk6d17431d170e48b7aa8db543c5539e63' https://swift01:443/v1/AUTH_vol01/container01 -k
(中略)
< HTTP/1.1 201 Created
< Content-Length: 18
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 13 Apr 2012 13:32:31 GMT
< 
201 Created

コンテナができていることを確認します。

# curl -v -X GET -H 'X-Auth-Token: AUTH_tk6d17431d170e48b7aa8db543c5539e63' https://swift01:443/v1/AUTH_vol01 -k
(中略)
< HTTP/1.1 200 OK
< X-Account-Container-Count: 0
< X-Account-Object-Count: 0
< X-Bytes-Used: 0
< X-Object-Count: 0
< X-Account-Bytes-Used: 0
< X-Type: Account
< X-Container-Count: 0
< Accept-Ranges: bytes
< Content-Length: 12
< Content-Type: text/plain; charset=utf-8
< Date: Fri, 13 Apr 2012 13:32:40 GMT
< 
container01

そろそろ面倒になってきたので、Swift付属のコマンドを使います。作成したコンテナにvmlinuzでもほり込んでみましょう。

# swift -A https://swift01/auth/v1.0 -U vol01:admin -K pas4vol01admin upload container01 /boot/vmlinuz-2.6.32-220.el6.x86_64 
boot/vmlinuz-2.6.32-220.el6.x86_64
# swift -A https://swift01/auth/v1.0 -U vol01:admin -K pas4vol01admin list container01
boot
boot/vmlinuz-2.6.32-220.el6.x86_64

この時、Proxyサーバ上では、次のようにGlusterFSのボリュームがマウントされて、その中にアップロードしたファイルが保存されていることが分かります。

# df
Filesystem           1K-ブロック    使用   使用可 使用% マウント位置
/dev/vda2              5039616   1777656   3005960  38% /
tmpfs                   510344         0    510344   0% /dev/shm
/dev/vda1               198337     27710    160387  15% /boot
rhs20-01:vol01        10653696    102912  10550784   1% /mnt/gluster-object/AUTH_vol01

# ls /mnt/gluster-object/AUTH_vol01/container01/boot/
vmlinuz-2.6.32-220.el6.x86_64