SwiftFSでConoHaオブジェクトストレージをマウントする

この記事は、[ConoHa Advent Calendar2015](http://qiita.com/advent-calendar/2015/conoha)の1日目の記事です。

こんにちは、ひろのぶ(@hironobu_s)です( ´ ω ` )
勢いでカレンダー作った本人です。

<blockquote class="twitter-tweet" data-cards="hidden" lang="ja"><p lang="ja" dir="ltr">つくった。さみしいからみんな登録してね。 / ConoHa Advent Calendar 2015 <a href="https://t.co/Y8bu8NRtmC">https://t.co/Y8bu8NRtmC</a></p>&mdash; Hironobu Saitoh (@hironobu_s) <a href="https://twitter.com/hironobu_s/status/664020019806781441">2015, 11月 10</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

なーんにも考えてなかったのですが、イベントなどで「オブジェクトストレージをもっと簡単に使えたら良いのだけど」と聞かれることが多いのを思い出したので、今回はそれをネタにしてみます。

## ConoHaオブジェクトストレージ

オブジェクトストレージはREST APIを使ってアクセスするタイプのストレージです。おおざっぱに言って「アクセス速度は遅いが、大容量のデータを安価に格納できて、HTTPSが通ればどこからでもアクセス可能」という特徴があります。詳しくは[Software Design2015年10月号](http://gihyo.jp/dev/serial/01/conoha/0003)に書いたのでそちらをご覧下さい。

ConoHaにはOpenStack Swiftベースのオブジェクトストレージが用意されていて、これを使うと100GB/450円から上限無しで容量を増やせるストレージが手に入ります。

ちなみに[GMOアプリクラウド(あんず側)](http://cloud.gmo.jp/spec/objectstorage/)にも同じものが用意されていますし、この記事の内容もきっと使えるはずです(アカウントがなかったので試せなかった)


# オブジェクトストレージをマウントする

オブジェクトストレージはREST API経由でアクセスするので、そのままではファイルシステムとしては使えません。サーバーなどからアクセスするには、REST APIを叩くクライアントツールなどが必要です。

そこでSwiftFSというツールを作成しました。これはOpenStack Swiftベースのオブジェクトストレージをファイルシステムとしてマウントするものです。これにより、あたかもローカルストレージのように使うことができるようになります。

[SwiftFS - GitHub](https://github.com/hironobu-s/swiftfs/)

同じアプローチのもので[cloudfuse](https://github.com/redbo/cloudfuse)がありますが、複数ノードからマウントすると同期が取れなくなる(キャッシュが入っているため？)ことと、C++実装なので自分でいじれなかった(私がC++知らない)ので、FUSEの勉強がてら自分で作ってみることにしました。


## SwiftFS

SwiftFSはGoで実装されたファイルシステムです。[GitHub Release](https://github.com/hironobu-s/swiftfs/releases)から実行ファイルをダウンロードするだけで使えます。現状ではLinux(amd64)環境のみで動作します。

**インストール**

```shell
curl -sL https://github.com/hironobu-s/swiftfs/releases/download/current/swiftfs.amd64.gz | zcat > swiftfs && chmod +x swiftfs
```

## 使ってみる

ConoHaで使ってみましょう。まず[コントロールパネル](https://manage.conoha.jp/API/)にアクセスしてAPIの情報を確認します。必要なのは「テナント名」「Identity Serviceのエンドポイント」「APIユーザー名」「APIパスワード」です。

<img width="890" alt="ConoHaコントロールパネル.png" src="https://qiita-image-store.s3.amazonaws.com/0/44152/11079cab-2342-76ae-4b19-34fb91a5801a.png">

それらを、README.mdの[「認証情報の設定」](https://github.com/hironobu-s/swiftfs/blob/master/README.md#認証情報の設定)に従って設定を行います。環境変数で設定しても良いですし、コマンドライン引数で渡してもOKです。

**コマンドライン引数で渡す**

一応可能ですが、長くなるのでなかなかしんどいです。

```shell
./swiftfs --os-username [APIユーザー名] --os-tenant-name [テナント名] --os-password [APIパスワード] --os-auth-url [Identity Serviceエンドポイント] コンテナ名 マウントポイント
```

**環境変数で渡す**

こちらがおすすめです。このOS_で始まる環境変数は[OpenStack系ツールでよく使われる](http://docs.openstack.org/cli-reference/content/cli_openrc.html)もので、オープンスタッカー(?)の皆さんにはおなじみですね。下記の内容を括弧内を埋めて、そのままターミナルにペーストします。

```shell
export OS_USERNAME=[APIユーザー名]
export OS_TENANT_NAME=[APIテナント名]
export OS_PASSWORD=[APIパスワード]
export OS_AUTH_URL=[Identity Serviceエンドポイント]
```

その後、swiftfsを実行します

```shell
$ swiftfs [コンテナ名] [マウントポイント]
```

-cオプションをつけると、コンテナが存在しない場合に自動的に作成してくれます。初回起動時はこちらが便利でしょう。

```shell
$ swiftfs -c [コンテナ名] [マウントポイント]
```

こんな感じでマウントされます(一番下)。あとは普通にcpやmvやmkdirなど、おなじみのコマンドが使えます。

```shell
$  df -h
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/dev--vg-root   47G  9.1G   35G  21% /
none                      4.0K     0  4.0K   0% /sys/fs/cgroup
udev                      2.0G  4.0K  2.0G   1% /dev
tmpfs                     394M  3.2M  391M   1% /run
none                      5.0M     0  5.0M   0% /run/lock
none                      2.0G  168K  2.0G   1% /run/shm
none                      100M     0  100M   0% /run/user
/dev/sda1                 236M   38M  186M  17% /boot
.host:/                   233G  131G  102G  57% /mnt/hgfs
swiftfs                   100G  247M  100G   1% /home/hiro/mnt
```

たとえば、swiftfsのソースツリーをマウント先にコピーしてみます。lsすると以下のようになりました。

```
$ ls -l mnt/
合計 0
-rw-r--r-- 1 hiro hiro  400 11月 30 23:24 Makefile
-rw-r--r-- 1 hiro hiro 2.4K 11月 30 23:24 README.en.md
-rw-r--r-- 1 hiro hiro 2.9K 11月 30 23:24 README.md
drwxr-xr-x 0 hiro hiro 4.0K 11月 30 23:24 app/
drwxr-xr-x 0 hiro hiro 4.0K 11月 30 23:24 config/
drwxr-xr-x 0 hiro hiro 4.0K 11月 30 23:24 fs/
drwxr-xr-x 0 hiro hiro 4.0K 11月 30 23:24 openstack/
-rw-r--r-- 1 hiro hiro   85 11月 30 23:24 swiftfs.go
-rw-r--r-- 1 hiro hiro   13 11月 30 23:24 swiftfs_test.go
```

これらはオブジェクトストレージにも同期されていて、以下のようにオブジェクトが配置されます。一見ファイルパスに見えますが、スラッシュを含むものも全てオブジェクトです。また、appやfsなどディレクトリに相当するものは、Content-typeがapplication/directoryのオブジェクトです。

```
# openstack object list swiftfs-container
+------------------------------+
| Name                         |
+------------------------------+
| Makefile                     |
| README.en.md                 |
| README.md                    |
| app                          |
| app/app.go                   |
| config                       |
| config/config.go             |
| config/config_test.go        |
| config/debug-transport.go    |
| config/logformat.go          |
| fs                           |
| fs/filesystem.go             |
| fs/filesystem_test.go        |
| fs/objectfile.go             |
| fs/objectfile_test.go        |
| fs/swiftfs-testrun           |
| openstack                    |
| openstack/objectlist.go      |
| openstack/objectlist_test.go |
| openstack/swift.go           |
| openstack/swift_test.go      |
| swiftfs.go                   |
| swiftfs_test.go              |
| test.php                     |
+------------------------------+
```

## 使ってみると

さすがにNFSなどとは比較にならないほど低速で、大量のファイルにアクセスするケースや、アクセス速度が求められるケースには全く向きません・・・。やはりオブジェクトストレージの特性を考えると、、大容量を生かして大きめのファイルをガンガン放り込むような用途が良いでしょう。容量が足りなくなっても、コントロールパネルから無制限にサイズを増やせますしね。

あと、ConoHaはVPSのストレージサイズが50GBなので、「50GBじゃぁ足りないけどバックアップやログを溜め込むのに追加SSD買うのはちょっと高い」という場合にも良さそうです。~~事業者的にはSSD買ってもらえると良い売り上げになるのですが・・・~~

他には「運用中サーバーでディスク容量が足りない」なんで場合でも、SwiftFSを使えば実行ファイル一つダウンロードするだけで大容量の外部ストレージを追加でき、ストレージを圧迫しているログファイルやバックアップファイルなどを待避できます。この辺はGoのメリットですね。

ちょっと変わった使い方として、オブジェクトストレージには[バージョン管理](http://docs.openstack.org/developer/swift/overview_object_versioning.html)という仕組みがあるので、これを使うと自動的に履歴を保存してくれるファイルシステムが作れます。定期バックアップなど作るときに、オブジェクトストレージ側で面倒見てくれます。(詳しくは[こちら](http://gihyo.jp/dev/serial/01/conoha/0003?page=2)の「オブジェクトのバージョン管理」を参照)

というわけで、ファイルシステムからオブジェクトストレージを扱えのはなかなか面白いです。

SwiftFSはまだ低機能で怪しい挙動をすることもありますが、せっかく作ったので時間を見つけて改良していこうと思います。