Kentaro Kuribayashi's blog

Software Engineering, Management, Books, and Daily Journal.

シンプルなデプロイツールを書いているという話

デプロイツールにcapistranoを使っているのですが、経年劣化により、何をやっているのか意味不明になり、機能追加しようにもどうにもならない感じになってきたので、もっとシンプルなものを作ってみようというわけで、ちょっとやってみています。

設計指針は以下の通り。

  • role/taskという枠組みはcapistranoと同じ
  • というか、このモジュールは、role/taskの管理 + アルファだけを提供する
    • 設定のset/get
    • コマンド実行(run/sudo)
    • リモートでのコマンド実行(remote)
    • (いまはないけどstreamみたいなのも欲しい)

普通、デプロイツールというのは、デプロイ先のディレクトリ構成をいい感じにしてくれたり、VCSとの連携を上手いことやってくれたりするわけですが、このモジュールはそういうことはしません。あくまでも、role/taskだけを管理し、あと上記した必要最小限のユーティリティを提供するだけです。

なんでそういう風にしているかというと、以下のような理由によります。

  • capistranoは便利だけど、汎用的なので裏でいろいろやっていて、よくわからないから面倒。
  • capistrano的な意味でのrole/task + アルファを提供していれば、デプロイツールとして最小限の要求は満たせる。
    • 要件に沿っていろいろカスタマイズする必要が出るだろうので、設定ファイルよりはコードでかけるほうがよくて、そうするとDSLのセットをシンプルに保たないと憶えなければいけないことが多くなってだるいので、複雑なものを提供するのはよくない。
  • デプロイの詳細についてはデプロイツールは関知せず、ツール外部のオブジェクトにより提供される方が、ツールに縛られない柔軟性を確保できる。

というわけで、使い方。

config/deploy.pl:

use strict;
use warnings;
use Cinnamon::DSL;

my $application = 'Cinnamon::App';

set application => $application;
set repository  => "git://repository.example.com/projects/$application";
set deploy_to   => "/home/httpd/apps/$application";

role development => 'development.example.com';
task development => {
    update => sub {
        my ($host, @args) = @_;

        run  'pwd';  # localhostで実行
        sudo 'pwd';  # localhostで実行

        remote {
            run  'pwd'; # SSH先で実行
            sudo 'pwd'; # SSH先で実行
        } $host;
    },

    start => sub {
        my ($host, @args) = @_;
        # ...
    },
};

role production => 'production.example.com';
task production => {
    update => sub {
        my ($host, @args) = @_;

        run  'pwd';
        sudo 'pwd';

        remote {
            run  'pwd';
            sudo 'pwd';
        } $host;
    },

    start => sub {
        my ($host, @args) = @_;
        # ...
    },
};

こういう設定ファイル(config/deploy.pl)があるとして、あとは

$ cinnamon production update

とかするだけです。わかりやすいですね。

config/deploy.plがデフォルトですが、設定ファイルを特に指定したい場合は、引数の最後にそのファイル名を書いておきます。

$ cinnamon production update /path/to/config.pl

あと、上記の設定ファイル(というかコード)に、たとえばset concurrency => 10とか書いてたら、並列に実行できるような仕組みにしたい感じでおります。

ただまあ、capとかもそうだと思うけど、こういう感じで素朴にdeployするみたいなのは、並列実行数を闇雲に増やすこともできなかろうし、ある程度のホスト数で許容できる範囲を超えてしまうだろうと思います。現状においては、その点が致命的というほどには至っていないのですが、もっと大規模になってくると、たとえばTwitterで使われているという、BitTorrentでデプロイするMurderのような仕組みが必要になるだろうなあと思います。

つか、他社のデプロイまわり事例知りたいですね!!1