読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

AWS, chef, Cinnamon等を使った無停止デプロイ(PrePAN carton 1.0化の裏側)

 最近PrePAN uses carton 1.0 now! - $shibayu36->blog;でも書いたとおり、PrePANのcarton 1.0化を進めていました。

 通常であれば変更点をアプリケーションサーバにデプロイし、サーバを再起動すれば良いのですが、cartonを0.9から1.0に上げるというまあまあ大きな変更を加えるため、事前に動作確認を行い、無停止でデプロイしたいと考えました。そこでAWSを使って無停止デプロイを試してみたのでそれについて書こうと思います。

PrePANのサーバ構成やデプロイ手順の検討

 無停止デプロイの説明の前にPrePANのサーバ構成を紹介しておきます。
 現状はELB 1つに対し、EC2が2台ぶら下がっているという状態で運用しています。そしてEC2に対してはそれぞれapp-1, app-2という名前でタグがついています。
f:id:shiba_yu36:20130910215814j:plain

 開発メモ#2 : AWS でのホスト / クラウドネイティブなデプロイ - naoyaのはてなダイアリーなどではElasticIPを使って無停止デプロイをしていますが、今回はELBを使っているため、全てセットアップされ動作確認されたEC2インスタンスをELBに追加した後、古いインスタンスをELBから外せばきちんとcarton 1.0での動作を確認しつつ、無停止でデプロイ出来そうです。
 なので最終的に以下の様な手順でやっていくことにしました。

  1. AWSでEC2インスタンスを新規に一台作りchefを適用し、PrePANをデプロイ
  2. セキュリティグループを調整し、直接動作確認
  3. 出来たインスタンスからサーバを複製
  4. ELBにインスタンスを追加、必要ないものを外す

 

AWSでEC2インスタンスを新規に一台作りchefを適用

新サーバ作成

 まずcarton 1.0で動かすサーバを新規で一台作ります。これまでのサーバのAMIから複製しても良かったのですが、chefのrecipeをいろいろ調整したので、一回まっさらにするためとりあえず新規で作りました。

 AWSのQuick Launch Wizardを使って作成します。Amazon Linux AMI 2013.03.1を選択して立ち上げるだけ。立ちあげたサーバにはapp-3というNameタグを付けておきます。
f:id:shiba_yu36:20130913173227p:plain:h300

chefの適用

 このサーバに対し、https://github.com/CPAN-API/prepan-cookbooksのchef recipeを適用します。
 まずec2ssh的なものでsshの設定を作っておきます。

$ ec2ssh update --aws_key prepan --path ~/.ssh/config

 次にchefのセットアップ。

$bundle exec knife solo prepare ec2-user@app-3.us-west-1 -i ~/.ssh/prepan.pem

 これで出来たnodeファイルを編集してアプリケーションサーバ用のrecipeを適用出来るようにします。app-3.us-west-1.json

 最後にchef適用します。ぼーっと待ってると全部成功してアプリケーションサーバ用のセットアップが完了します(PrePANのデプロイ自体はされていない)。

$ bundle exec knife solo cook ec2-user@app-3.us-west-1 -i ~/.ssh/prepan.pem

PrePANのデプロイ

 次にデプロイツールのCinnamonを使って、PrePANをデプロイ。production-standbyというroleを作り、app-3のサーバにデプロイします。
 deploy.plで適当にrole作っておきます。

role "production-standby" => [qw(app-3.us-west-1], {
    deploy_to          => '/var/www/prepan',
    branch             => 'origin/master',
    service_web_dir    => '/service/web',
    service_worker_dir => '/service/worker',
    perl_dir           => '/usr/local/perl-prepan',
    daemontools_prefix => 'production',
};

 初期設定とデプロイ。

$ cinnamon production-standby deploy:setup:dir deploy:config deploy:update deploy:setup:db
$ cinnamon production-standby web:start worker:start

 ここまででPrePANのデプロイまで完了できているはずです。現在のサーバ状況はこんな感じ。
f:id:shiba_yu36:20130913181641j:plain

セキュリティグループを調整し、直接動作確認

 次に一台立ち上がったサーバの動作確認をする。セキュリティグループをいじって直接アプリケーションサーバにアクセスすれば良いです。
 セキュリティグループは設定画面でアクセスできるポートを増やせます。
f:id:shiba_yu36:20130913175520p:plain:h300

 あとはpublic DNSとサーバのポートを直接指定して確認してみれば良いです。
f:id:shiba_yu36:20130913181723j:plain:h300

出来たインスタンスからサーバを複製

 さてここまでで動くことが確認されたサーバが作成できました。PrePANはアプリケーションサーバ2台構成なので、続いて出来たサーバからサーバを複製してみます。

 一度サーバをshutdownして、AMIを作成します。EC2のinstanceの設定からapp-3を右クリックし、stopしてからCreate Image(EBS AMI)を実行します。適当に名前付けてAMIを作ります。
f:id:shiba_yu36:20130913180556p:plain:h300

 作ったAMIから新しいサーバを作ります。AMIの管理画面から作ったイメージを選択してLaunchボタン押すだけ。以下のような画面が出るので適当に作ります。Nameはapp-4としておきます。
f:id:shiba_yu36:20130913180956p:plain:h300

 これで複製完了。簡単です。
f:id:shiba_yu36:20130913181754j:plain

ELBにインスタンスを追加、必要ないものを外す

 これであとはELBに追加するだけです。
 ELBの設定画面でポチポチapp-3とapp-4を選択して追加。少し待っていると、StatusがIn Serviceという状態になります。その後適当に本番にアクセスしてみます(PrePANだったらhttp://prepan.org)
 大丈夫そうだったら管理画面からapp-1, app-2を外し、要らなくなったサーバは止めます。

 これで無事にcarton 1.0で動いているサーバに無停止で移行することが出来ました。
f:id:shiba_yu36:20130913182455j:plain

まとめ

 今回はPrePANのcarton 1.0化で無停止に確認、反映を行った手順について書いていきました。AWSとかインフラ周りの運用するのほぼ初めてに近いので、間違ったこと書いていたら指摘してください。

その他雑感

 僕自身は仕事では基本的にWebアプリを作るということをしていて、サーバの運用などはしていません。ただ今回のようなことをやってみて、自分の専門の周辺知識を身につけることはやはり大切だなと感じました。今回の無停止デプロイをひと通りやってみると、これまでアプリケーションの学習だけでは見えてこなかった部分が少しだけわかったような気がします。例えば

  • 無停止にするためにはcapistranoのデプロイのtaskをこのようにしておけば良い
  • 無停止にするためにアプリケーションサーバはこのように立てておいたほうが良い

みたいなことです。

 今回いろいろやってみると仕事で他の職種の人とうまく連携するために、自分で他の職種がやっていることを試してみるみたいなことは必要だなあと感じました。終わり。