さくらのクラウドとGoogle Cloud Platformを使ってHAなダウンロードサービスを構築した話

この記事は、[さくらインターネット Advent Calendar 2015](http://qiita.com/advent-calendar/2015/sakura)の10日目の代理投稿記事です。（さくらの中の人ではありません）

----

さくらのクラウドの良いところはいくつかありますが、なんといってもネットワーク使用料がタダなところです。ネットワークコストとしては、AWSやGCPでの見積もりと比べてとても安く済みます。

# 回線と帯域の注意事項

## サーバの回線

サーバの接続先として、以下の接続先があります。

| 接続先 | 説明 |
| ------------- | -------------------------------------------- |
| 共有セグメント | 共有回線を使用、帯域は100Mbpsのベストエフォート |
| ルータ＋スイッチ | 共有回線を使用、指定した帯域が確保される |

共有セグメントでは、他のユーザーと一緒の帯域を使うため、帯域をうめつくす恐れのあるサービスについては、共有セグメントではなく、ルータ+スイッチを契約しましょう。（警告が来たことはありませんが、来ることもあるようです）

## サーバの帯域

サーバからスイッチに接続する帯域についても、制限があります。

サーバ搭載メモリ量 | 帯域制限値
---- | ----
16GB未満 | 500Mbps
16GB以上 32GB未満 | 1.0Gbps
32GB以上 64GB未満 | 1.5Gbps
64GB以上 | 2.0Gbps

（2015年12月22日時点）

16GB未満は一律500Mbpsのため、1GBのメモリと8GBメモリで帯域の変化はありません。

## その他

ルータ+スイッチで転送量に応じたトラフィック制限がある場合もあるようです。つまり、ずっと帯域を使うのも良くないということですね。

トラフィック制限や帯域については、さくらのクラウドのよくある質問にまとめられています。
http://cloud-news.sakura.ad.jp/faq_top/faq/

# アプリケーション
今回はタイトルの通り、さくらのクラウドとGoogle Cloud Platformを使った可用性の高いダウンロードサーバを構築します。

さくらのクラウドとGoogle Cloud Platformの両方を使うのにはいくつか理由があります。

- さくらのクラウドはネットワーク使用料がかからない
- GCPはCloud SQLやインスタンス制御など、Webアプリケーションのインフラとして必要な物が揃っている(AWS程ではないけど)
- どちらかと言うとGCPのほうが信頼性が高そう(ごめんなさい) [^1]
- GCPは日本にデータセンタがないので、さくらのクラウドのほうがダウンロード速度が速い

[^1]: GCPを無料期間中のまま運用を始めたら残高が切れてすべてのインスタンスが落ちました。
 
# インフラ構成

今回のインフラは以下の様な構成になりました。

![image](https://qiita-image-store.s3.amazonaws.com/0/33754/265f9241-ea75-d688-8af1-55781544f8b4.png)

Google Cloud Storageを使っているのは、「メインとしてファイルを保存する」ためと、「さくらのクラウドが帯域が一杯、又は、ダウンした時にフォールバックする」ためです。

GCP側にはユーザーがアクセスするサーバがあり、そこで認証を行うとダウンロードサーバに転送されます。

# 認証サーバ(管理サーバ)

認証サーバは、nginx + unicorn + Ruby on Railsの至って最近としては普通の構成です。
ただしnginxを普通に使うと、でかいファイルのアップロード時に、Disk Fullになったり、Timeoutすることがあるので、nginx-upload-moduleを導入しています。
[Rails + unicorn で nginx-upload-moduleを使ってみた](http://qiita.com/miyukki/items/e841430fafeb6b85d32e)

GCPとさくらのクラウドのは、両方とも便利そうなライブラリがあるのでこれを使って、管理サーバからファイルのアップロードや、ダウンロードサーバの作成が行えるようにしておきます。
（ちなみにどちらも不具合修正や機能追加でPRを出しました）

- https://github.com/GoogleCloudPlatform/gcloud-ruby
- https://github.com/fog/fog-sakuracloud

# ダウンロードサーバ

認証サーバとダウンロードサーバの間で、データベースなどのやり取りはありません。
認証サーバとダウンロードサーバは、予め同一のハッシュのためのソルトを持っていて、有効期限付きのハッシュを含めたパラメータをユーザーに渡し、リダイレクトさせます。

ダウンロードサーバはできるだけ複雑にしたくなかったので、Apache + PHPの1ファイルで済ませています。

特徴的な点として、`X-Sendfile`ヘッダを利用することにより、PHPがファイルを送信するのではなく、Apacheが直接ファイルを送信します。これにより、PHPの処理によるオーバーヘッドを少なくすることができます。

```php:index.php
<?php
  /*
   * 認証処理(略)
   */

  /*
   * ファイルを送る
   */
  header("X-Sendfile: $filepath");
  header("Content-Type: application/octet-stream");
  header("Content-Disposition: attachment; filename=\"$file\"");
```

そして、これを構築したものをアーカイブとして保存しておくことで、何時でもダウンロードサーバの台数を増やすことが可能です。

ダウンロードサーバからファイルを配置するのは、管理サーバからダウンロードサーバにSSHで入り、Google Cloud Storageのファイルをwgetしています。

## 自動制御

管理サーバからは、さくらのクラウドのAPIを利用することで、ダウンロードサーバを自動制御することができます。

前述のとおり、さくらのクラウドのAPIを操作するのにfog-sakuracloudを使っています。

### アーカイブからインスタンスを生成する
これにより、ダウンロードサーバをどんどん増やすことができます。

```rb
  SAKURA_CLOUD_ZONE = 'tk1a'
  SCLOUD_SERVER_PLAN_ID = 1001
  SCLOUD_VOLUME_PLAN_ID = 4
  SCLOUD_SWITCH_ID = 1126000xxxx
  SCLOUD_ARCHIVE_ID = 11270094xxxx
  compute = Fog::Compute::SakuraCloud.new(
    api_zone: SAKURA_CLOUD_ZONE,
    sakuracloud_api_token: sconfig['api']['access_token'],
    sakuracloud_api_token_secret: sconfig['api']['access_token_secret'],
  )
  server = compute.servers.create({
    name: self.name,
    serverplan: SCLOUD_SERVER_PLAN_ID,
    volume: {
      diskplan: SCLOUD_VOLUME_PLAN_ID,
      sourcearchive: SCLOUD_ARCHIVE_ID,
    },
    switch => SCLOUD_SWITCH_ID
    boot: true,
  })
```

### ルータ+スイッチの帯域を変更する
これにより、ピークの時だけ帯域を変更することができます。以下の例では1000Mbpsに変更しています。

```rb
  SAKURA_CLOUD_ZONE = 'tk1a'
  SCLOUD_ROUTER_ID = 1126000xxxx
  network = Fog::Network::SakuraCloud.new(
    api_zone: SAKURA_CLOUD_ZONE,
    sakuracloud_api_token: sconfig['api']['access_token'],
    sakuracloud_api_token_secret: sconfig['api']['access_token_secret'],
  )
  network.routers.get(SCLOUD_ROUTER_ID).change_bandwidth(1000)
```

ただし、これには注意が必要で、帯域の変更は料金体系が変更になります。短時間で変更しても1つのルータ+スイッチの最小課金時間は1時間となるため、たとえ5分だけ1000Mbpsにしても1時間の扱いとなるはずです(教えて！中の人！)。

また、これにより20日以上連続して利用した場合に20日の価格になるといった料金体系もなくなるはずです。

# まとめ
さくらのクラウドは、日本内にDCがあるため早く、共有回線のためコスパが安い。Google Cloud Platformは安定していてWebアプリケーションの開発に適したクラウド。両方のメリットを使って案件を遂行することができました。

受託案件のため、実装の詳しい内容に触れることは出来ませんでしたが、さくらのクラウドを使用してみて、たしかに安定していてGCPにも劣らないクラウドサービスであることが分かったので、これからも継続的に使っていきたいと思います。