BitTorrentを利用した高速デプロイツール Murder を使ってみる

## 概要

[Murder](https://github.com/lg/murder/)とは
TwitterがBitTorrentを利用して高速にデプロイするのに使っているツール。

http://www.publickey1.jp/blog/10/twitterbittorrent.html
の説明が一番わかりやすい。というか日本語ではこれしか無い。

### 特徴

* Capistranoの拡張のように動く(?)
  * Capistrano(ruby)とPythonスクリプトで構成されており、Capistranoの`deploy_via:`として動く
  * Capistranoを使ったことがあればその延長で使えるかも
* BitTorrent等のライブラリの配布は自動
  * BitTorrentは同梱されており、必要なスクリプトやライブラリは、すべてのサーバへCapistranoで自動配布される
* コマンド一発でデプロイ
  * Capistranoを使って、tracker,seeder等必要なプロセスの初期化から実際のデプロイと後片付けを行える

使って見た感想としては、とにかくすばらしく速い！
複数サーバーへデプロイするのに時間がかかっている全ての人のおすすめしたい。
が、まだまだ荒削りなツールなのでみんなで手を加えて育てていきたいところ。



## 構成

サーバーの種類は4種類になる。

* Capistrano ノード
  * Capistranoを実行する実行元のノード

* tracker ノード
 * torrentのトラッカーノードで全てのノードがこのサーバーに情報を集約するようだ  

* seeder ノード
  * 配布元のファイルを持っているサーバー

* peers  
  * 配布されるサーバー

### 補足
ドキュメントには、tracker seeder peersの3種類しか載っていないが、Capistranoとtrackerとseederを同じサーバーにすると、正常に動かない。同じサーバーを想定していないようだ。

## インストール

環境の準備はansibleを使った。
別に何でも良いけど、手動だと全部のノードの設定変更が辛いかもしれない。

### Capistrano ノード

capistranoとmurderをgemで入れる

```YAML:roles/murder/capistrano/main.yml
- name: install capistrano
  gem: name=capistrano user_install=no state=latest

- name: install murder
  gem: name=murder user_install=no state=latest
```
 
### tracker, seeder ノード

screenでtrackerスクリプトを常駐するようなので、screenを入れる。

```YAML:roles/murder/{tracker,seeder}/main.yml
- name: install screen
  yum: name=screen state=latest
```

### peers ノード 
 
pythonが入っていれば他は特になにも要らないが、sshでsftpを有効化されている必要がある。

```YAML:roles/murder/peers/main.yml
- name: enable sftp
  lineinfile: dest=/etc/ssh/sshd_config regexp="^Subsystem\s+sftp\s+/usr/libexec/openssh/sftp-server" insertafter="^#Subsystem" line="Subsystem sftp /usr/libexec/openssh/sftp-server"
````


## 実行方法

### Capfileを準備

Capfileに必要なサーバー情報等を記載する

```rb:Capfile
require 'rubygems'
require 'murder'

set :user, "root"    # sshでログインするユーザー

ssh_options[:auth_methods] = ["publickey"] # 公開鍵認証を行う
ssh_options[:keys] = ["private.pem"]            # 認証に使う公開鍵を指定


set :remote_murder_path, '/usr/local/murder'   # 各ノードのmurderのサポートファイルを設置するpathを指定

role :peer, 'host1', 'host2', 'host3', 'host4', 'host5', host6', host7'    # trackerとseederになるhostが先頭にくるように書いた方がよさそう。
role :seeder, 'host1'
role :tracker, 'host1'
```

### 1. trackerを起動する

```bash:
cap murder:start_tracker
```


### 2.  デプロイするディレクトリ等をseederに配置

```bash:
scp -r ./files host1:~/files
```

### 3. torrentファイルの作成

```bash:
cap murder:create_torrent tag="Deploy1" files_path="~/files"
```

### 4. seederの起動

```bash:
cap murder:start_seeding tag="Deploy1"
```

### 5. デプロイする

```bash:
cap murder:peer tag="Deploy1" destination_path="/tmp"
```
これでpeersにデプロイが実行される。
destination_path=で指定したディレクトに展開される。

### 6. seeder と trackerを停止

```bash:
cap murder:stop_seeding tag="Deploy1"
cap murder:stop_tracker
```



## 実験結果

デプロイ対象のファイル:
 88,125ファイル 計3.4GB
を試しにデプロイしてみる。

### 1台にデプロイ (scpを使用)

```bash:
real    10m13.282s
user    2m52.746s
sys     0m50.861s
```
1台のサーバーへ、単純なscpでデプロイすると10分程度

### Murderを使った場合

Murderを使う場合、以下の手順に分かれるのでそれぞれの時間をtimeコマンドで計測
1. デプロイの前にtorrentファイル(tar.gz)を作る
2. torrentファイルの配布とtar.gz展開

また、配布するサーバー台数でどの程度時間が違うのかを見るために、5台の場合と25台の場合で試してみた。

#### torrentファイル作成
```bash:
time cap murder:create_torrent tag="Deploy1" files_path="~/builds"
real    5m57.046s
user    0m0.311s
sys     0m0.032s
```
torrentファイルの作成時間はファイル数やファイルサイズに依存するが、今回のテストで用意したファイルでは6分程度

#### 5台のサーバーにデプロイ
```bash:
time cap murder:peer tag="Deploy1" destination_path="/tmp"
real    8m33.886s
user    0m0.633s
sys     0m0.056s
```
上記コマンドで、peerのノードへtorrentファイルの配布とtar.gzの展開が行われる
5台だと8分程度

#### 25台のサーバーにデプロイ
```bash:
time cap murder:peer tag="Deploy1" destination_path="/tmp"
real    10m43.146s
user    0m1.651s
sys     0m0.125s
```
25台にふやしても10分程度

という結果に。  
1台にscpする時間で、25台にデプロイできた (torrentファイルの作成時間を除く)

## ハマリポイント

* trackerとseederにはscreenが必要
* capistranoとseederサーバーは一緒にすると動かない
* 全てのサーバーはhostコマンドでIPアドレスが引けないと行けない(ソース修正で回避可能 TBD後で書く)
* capistranoのDSLがよく分からないｗ


## その他

<del>だれかCapistranoじゃなくてAnsibleの拡張にしてください・・・・</del>
Ansible playbook化しました。->  http://yamasaki0.hatenablog.com/entry/2013/10/16/003149 , http://qiita.com/yamasaki-masahide/items/69d2873e0fbc2c05cf56