UbuntuでさくらのBASE Storageを試す

さくらのBASE Storageという、Amazon S3互換のインターフェイスを備えたオブジェクトストレージのベータサービスが開始されました。さっそくUbuntuから利用してみましょう。

サービスアカウントを開設する

BASE Storageには専用のサービスアカウントが必要です。既にさくらのVPSさくらのクラウドを利用している人であっても、まずは新規にサービスアカウントを作りましょう。
ログイン画面からさくらインターネット会員IDでログインし、任意の名前でアカウントを作成します。

ネームスペースを作成する

作成したサービスアカウントでBASE Storageサービスへログインすると、まずはネームスペースの作成画面に遷移します。

ネームスペース名が、S3でいうバケット名に相当します。現時点ではネームスペースは1つしか作成できないようです。

ネームスペース作成時、このようにエラーが出る場合があります。これはネームスペース名に英大文字を含めた時のエラーですが、メッセージからそれを察するのは難しいですね。
ちなみにネームスペース名はサービス全体でユニークでなければならないため、既に他のユーザーに使用されている名前を指定した時も同じエラーが表示されます……されました。昨日は。
こちらのエラーは、今日になって「Duplicate」と表示されるようになったので、このあたりは日々改善されていくと思います。

ネームスペースの作成が成功すると、このような画面に遷移します。「アクセストークン」の欄に表示されている「ユーザ名」がS3のAccess Key、「トークン」がSecret Access Keyに相当します。また下部に「https://(ネームスペース名).b.storage.sakura.ad.jp/」というURLが表示されているところからわかると思いますが、「http(s)://b.storage.sakura.ad.jp」がエンドポイントになります。
ネームスペース名とトークンを控えたら、サーバー側の準備は完了です。

s3fsをインストールする

次に、ストレージをマウントするサーバーを用意しましょう。今回はさくらのクラウドと、Amazon EC2の東京リージョン、それぞれにサーバーを用意してみましたが、インターネットに接続されていればどこでも構いません。
OSはUbuntu 13.10を使用しました。EC2を使っている場合は、このへんから起動すると便利です。
s3fsはDebianパッケージが存在しないので*1、ソースからビルドします。
面倒な解説は省略しますが、以下の手順でビルドできるはずです。

$ sudo apt-get install build-essential libfuse-dev libcurl4-openssl-dev libxml2-dev mime-support
$ wget http://s3fs.googlecode.com/files/s3fs-1.74.tar.gz
$ tar zxvf s3fs-1.74.tar.gz
$ cd s3fs-1.74
$ ./configure
$ make
$ sudo make install

passwd-s3fsファイルを用意する

s3fsでS3バケットをマウントするには、Access KeyとSecret Access Keyが必要です。キーを設定する方法はいくつかあるのですが、一番簡単なのがホームディレクトリの.passwd-s3fsというファイルにコロンで区切って書いておく方法です。

$ echo 'ユーザ名:アクセストークン' > ~/.passwd-s3fs
$ chmod 600 ~/.passwd-s3fs

他にも/etc/passwd-s3fsに置く、passwd_fileオプションで任意のファイルを指定する、環境変数に設定する、などの手段がありますが今回は省略します。

マウントする

s3fsコマンドをsudoで実行して、S3バケットをマウントします。

$ sudo mkdir /mnt/s3
$ sudo s3fs (ネームスペース名) /mnt/s3 -o url=http://b.storage.sakura.ad.jp -o allow_other,default_acl=public-read

s3fsはデフォルトでhttp://s3.amazonaws.comにアクセスしようとします。urlオプションで、接続先を明示的に指定してください。
またマウントした以外のユーザーでのアクセスを許可するため、allow_other、パーミッションを指定するためdefault_acl=public-readを指定しています。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      7.8G  960M  6.4G  13% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
udev            285M  8.0K  285M   1% /dev
tmpfs            59M  188K   59M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            295M     0  295M   0% /run/shm
none            100M     0  100M   0% /run/user
s3fs            256T     0  256T   0% /mnt/s3

このように、dfコマンドから256TBの領域が見えていれば、マウントは成功しています。
ベータ期間中は無料で容量無制限ということなので、色々とデータを置いてみましょう。ベンチマークを取ったわけではないですが、体感ではS3よりだいぶ早く感じます。

SSLを使う

urlオプションにhttpを指定していたことから、はてな? と思われた方もいると思います。
スキーマhttpsに変更してみると、以下のようなエラーが出ます*2

s3fs_init(2595): init
s3fs_check_service(2894): check services.
    CheckBucket(2228): check a bucket.
LocateBundle(597): s3fs: /etc/pki/tls/certs/ca-bundle.crt is not readable

どうやらデフォルトではRHEL/CentOSのCA証明書のパスを見に行ってしまうようです。ソースコードcurl.cppを見てみます。

  ///////////////////////////////////////////
  // from curl's (7.21.2) acinclude.m4 file
  ///////////////////////////////////////////
  // dnl CURL_CHECK_CA_BUNDLE
  // dnl -------------------------------------------------
  // dnl Check if a default ca-bundle should be used
  // dnl
  // dnl regarding the paths this will scan:
  // dnl /etc/ssl/certs/ca-certificates.crt Debian systems
  // dnl /etc/pki/tls/certs/ca-bundle.crt Redhat and Mandriva
  // dnl /usr/share/ssl/certs/ca-bundle.crt old(er) Redhat
  // dnl /usr/local/share/certs/ca-root.crt FreeBSD
  // dnl /etc/ssl/cert.pem OpenBSD
  // dnl /etc/ssl/certs/ (ca path) SUSE
  ifstream BF("/etc/pki/tls/certs/ca-bundle.crt");
  if(BF.good()){
     BF.close();
     S3fsCurl::curl_ca_bundle.assign("/etc/pki/tls/certs/ca-bundle.crt");
  }else{
    DPRN("%s: /etc/pki/tls/certs/ca-bundle.crt is not readable", program_name.c_str());
    return false;
  }
  return true;

なるほど、見に行くファイルがハードコードされているんですね。ここをコメント通りに書き換えてコンパイルしてもいいのですが、この直前に以下のようなコードがあります。

  char *CURL_CA_BUNDLE;

  if(0 == S3fsCurl::curl_ca_bundle.size()){
    CURL_CA_BUNDLE = getenv("CURL_CA_BUNDLE");
    printf("hoge: %s\n", CURL_CA_BUNDLE);
    if(CURL_CA_BUNDLE != NULL)  {
      // check for existance and readability of the file
      ifstream BF(CURL_CA_BUNDLE);
      if(!BF.good()){
        DPRN("%s: file specified by CURL_CA_BUNDLE environment variable is not readable", program_name.c_str());
        return false;
      }
      BF.close();
      S3fsCurl::curl_ca_bundle.assign(CURL_CA_BUNDLE);
      return true;
    }
  }

環境変数CURL_CA_BUNDLEに証明書のパスを格納しておけばよさそうです。というわけで、環境変数を設定してみます*3

$ export CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"

これでhttpsでマウントしようとすると……

s3fs_init(2595): init
s3fs_check_service(2894): check services.
    CheckBucket(2229): check a bucket.
    RequestPerform(1618): ### retrying...
    RemakeHandle(1289): Retry request. [type=5][url=https://0vdet9e.b.storage.sakura.ad.jp/][path=/]
RequestPerform(1574): curlCode: 60  msg: Peer certificate cannot be authenticated with given CA certificates

証明書は読んでくれたようですが、うまく検証できません。ナンデ? というところで今日はここまで。

*1:s3fs自体はGNU GPLv2ですが、OpenSSLにリンクする都合上、バイナリの再配布ができません。

*2:これはs3fsに-fオプションをつけて、フロントエンドモードで実行させて確認しています。

*3:Ubuntuのデフォルトではsudo時に環境変数が引き継がれないため、必要であればsudoersにkeep_envを設定してください。