ConoHaのオブジェクトストレージをPaperclipから使う

清楚かわいいConoHaちゃんが、APIのレビュー記事を書くとクーポンをくれるらしいので、全力で乗っかっていこうと思います。


(画像はこのは通信室より引用)

今回利用してみるのは、ConoHaのオブジェクトストレージです。
これは基本的にOpenStack Swiftを使って実現されており、API仕様OpenStack Swift APIとほぼ同じ内容になっています。

APIが互換であれば、OpenStack Swiftを扱えるシステムからConoHaのオブジェクトストレージも扱うことが出来るはずですね。
そんなわけで、試しにRuby on Railsで画像アップロードをお手軽にできるPaperclipのバックエンドをConoHaのオブジェクトストレージにしてみましょう。

準備

何はともあれ、Paperclipを使うためのサンプルリポジトリを作りましょう。
RailsでPaperclipを使ってファイルをアップロードするの記事を参考に、とりあえずローカルへの画像アップロード機能を作ってみます。

できました。
bootstrap-generatorsでちょっとだけ見た目を整えましたが、ほとんど記事に書いてある通りに進めてます。
簡単ですね。

ちなみに、この時点のソースがGithubのこのコミットになります。

バックエンド差し替え

バックエンドを差し替えるに辺り、PaperclipからOpenStack Swiftを触るためにFogを導入します。
Gemfileに以下の行を追加してbundle installします。

gem 'fog'

ここからが若干厄介なところで、Swiftではディレクトリ(もしくはコンテナ)と呼ばれる単位でオブジェクト格納領域を管理します。
AWS S3で言うところのBucketなのですが、ConoHaのコンソール上からはコンテナを追加する方法はなく、またPaperclipからはコンテナを作ってくれないようなので、コンソールなどから手動で追加する必要があります。

そんなわけで、以下のようにrails consoleから新しいディレクトリを作ってやります。

> service = Fog::Storage.new provider: 'OpenStack', openstack_auth_url: 'https://identity.tyo1.conoha.io/v2.0/tokens', openstack_username: [APIユーザー名], openstack_api_key: [APIパスワード], openstack_tenant: [テナント名]
> service.directories.create key: [任意のディレクトリ名], public: true

1つ目のコマンドがFogのStorageクライアント作成、2つ目のコマンドがディレクトリの作成です。
APIユーザー名とAPIパスワードはConoHa管理画面の「API – APIユーザー」で発行したものを、テナント名は「API – テナント情報」で表示されるものを使います。
ここでテナントIDではなくテナント名を使う必要がある、というところに注意が必要です。
私はテナントIDを指定した結果NotFound地獄に陥りました。
また2つ目のコマンドのpublic: trueも要注意で、これを忘れると画像を参照するのにも認証が必須になってしまい、登録はできたけど表示ができない、みたいな挙動に悩まされることになります。

コンテナさえ作成できてしまえば、あとはapplication.rbあたりでPaperclipにFogの接続情報を渡してやるだけでオッケーです。

config.paperclip_defaults = {
  storage: :fog,
  fog_credentials: {
    provider: 'OpenStack',
    openstack_username: ENV['CONOHA_API_USERNAME'],
    openstack_api_key: ENV['CONOHA_API_PASSWORD'],
    openstack_auth_url: ENV['CONOHA_API_AUTH_URL'],
    openstack_tenant: ENV['CONOHA_API_TENANT']
  },
  fog_directory: ENV['CONOHA_OBJECT_STORAGE_DIRECTORY'],
  fog_host: "#{ENV['CONOHA_OBJECT_STORAGE_ENDPOINT']}/#{ENV['CONOHA_OBJECT_STORAGE_DIRECTORY']}"
}

環境変数から山ほど値を渡していますが、CONOHA_API_AUTH_URL辺りは直書きしてしまってもよいかもしれません。
それぞれ以下のとおり設定しています。
エンドポイントURLについてはConoHa管理画面の「API – エンドポイント」から見られる値を使います。

  • CONOHA_API_USERNAME : APIユーザー名
  • CONOHA_API_PASSWORD : APIパスワード
  • CONOHA_API_AUTH_URL : Identity ServiceのエンドポイントURL
  • CONOHA_API_TENANT : テナント名
  • CONOHA_OBJECT_STORAGE_DIRECTORY : 上記で作成した任意のディレクトリ名
  • CONOHA_OBJECT_STORAGE_ENDPOINT : Object Storage ServiceのエンドポイントURL

ちなみにfog_hostがエンドポイントURLそのままではなくディレクトリ名をくっつけていますが、こうしてやらないと参照URLのパス部分にディレクトリ名が含まれず、画像が表示されなくなってしまうようです。
本当にこれが正しいやり方なのか怪しいですが、少なくとも保存/表示に関してはこれでちゃんと動いています…

ここまでやって動かした結果が以下です。

画像が変わっただけにしか見えませんが、リンク先URLが以下のとおりConoHaのオブジェクトストレージを向いています。
(何度か撮り直したのでconoha_01になってますが…)

paperclip_conoha_03

そういったわけで、無事PaperclipからConoHaのオブジェクトストレージを使うことができました!
なお完成したものがGithubのmaster最新になります。(完成というにはテストないし雑ですが)

S3との比較

さて、PaperclipからはAWS S3をバックエンドに使うのが定番のような気がしますが、今回の方法でわりとサックリConoHaのオブジェクトストレージを使うこともできることがわかりました。
ではどちらを使うべきか?
とりあえず信頼性とかは置いておいて、料金のみで考えてみましょう。

S3の料金は利用従量制で、ストレージに$0.0330 /GBがかかる他、リクエストに1,000 リクエストあたり$0.0037-$0.0047、データ転送(S3→インターネット)に$0.140 /GBがかかります。
なおすべて東京リージョンのスタンダードストレージ、最初の1TBまでの料金で考えています。またデータ転送は最初の1GBは無料です。

一方、ConoHaのオブジェクトストレージの料金は時間従量制で、ストレージ100GBあたり450円となっています。
最小単位で使うと1時間0.7円ですが、使う容量はどんなに少なくてもこの価格です。
またS3のようにリクエスト数やデータ転送での料金は発生しません。
ストレージが100GBを超えた場合、次は200GBまで900円、といったように100GB単位で増やすことになります。

単純にストレージの料金だけで考えるならば、S3は100GBで$3.3≒400円ちょいと、フルに使ってもConoHaを下回っています。
しかしながら、Paperclipのバックエンドとして使うならば画像の配信に使われることになり、結構な読み出しが発生するはずです。
ざっくり、画像サイズを1枚100kBとし、トップページや検索などでのサムネイル表示を想定して、毎月ストレージに保存されている画像容量の10倍のreadが発生するとしましょう。

この場合、ストレージ1GBに対して10GBのデータ転送、また100,000回のGETリクエストが処理されることになり、

$0.0330 + $0.0037 * (100,000 / 1,000) + $0.140 * 10 = $1.803

といった計算になります。(最初の1GB無料分は計算に入れていません)
全体的に多めに見積もっていますが、とはいえ100,000回/月のGETアクセスは日に均すと3,000回ちょっと、トップページに10枚のサムネイルが表示されるとして300PVあれば達成されてしまいます。
この見積もりの精度はともかく、大抵のサービスでは情報を投稿するユーザーより閲覧するユーザーの方が多いことから、ストレージ料金よりもデータ転送料金のほうが比重が大きくなるのは間違いなさそうです。

こう考えると、月の転送量が30GB = $4.2を超える程度の読み出し処理が走るのであれば、ConoHaのオブジェクトストレージを利用したほうが安く上がる可能性が高そうです。
逆に言うと、そこまで成長しない限りは従量で安く上がるS3の利点が活きるので、そこまでユーザー数が見込めない場合はS3、そこそこユーザー数が伸びそうならConoHa、という使い分けが良いのではないでしょうか。

最後はAPIと関係なくなりましたが、PaperclipのバックエンドをConoHaのオブジェクトストレージにする方法でした。
ぶっちゃけOpenStack Swiftであれば同様のはずなので、自鯖に向けるなり他のクラウドサービスを使うなりする際にも同様の設定でいけそうです。
この手の話はググると大体S3ばかりなので、それ以外の選択肢が出来るというのは大きいのではないでしょうか。
以上、ご参考になれば幸いです。

Ruby on Rails 4アプリケーションプログラミング
Ruby on Rails 4アプリケーションプログラミング 山田祥寛

技術評論社 2014-04-28
売り上げランキング : 18593