ようへいの日々精進XP

よかろうもん

駆け出しインフラエンジニヤが capistrano を使って感動したのでメモ(1)

はじめに

今更ながら capistrano に感動したのでインフラエンジヤなりの視点で触ってみて使い方をまとめてみる。


capistrano とは

以下は自分が抱く capistrano へのイメージ。

  • 複数のノードに対して並列してコマンドを実行出来る!(うれしポイント)
  • コマンドを task という単位で纏めて自動化出来る!(うれしポイント)
  • Ruby 製のデプロイツール!(やや、うれしポイント*1

これだけ「うれしポイント」があれば複数台のサーバーにログインして色々とやんなきゃいけないインフラエンジヤが使わない理由が無いでしょ!ということで早速使ってみよー。

ちなみに今までは以下のようなイメージ。

f:id:inokara:20140125105024p:plain

メンテナンス作業等に capistrano を常用するようになってからのイメージ。

f:id:inokara:20140125105034p:plain

ということで、本来の capistrano の利用目的とは逸れてしまうかもしれないが、インフラエンジニヤが capistrano を使うことで日頃の運用をちょっとでも楽に出来そうなので使い方について纏めてみることにする。


参考


環境を整える

Mac で boxen を使ってインストール

Mac 環境において boxen を使って環境を構築している場合には /Users/${USER}/our-boxen/modules/people/manifests/${GITHUB_USER}.pp に以下を追加する。

  ruby::gem { "capistrano for 2.0.0-p247":
    gem     => 'capistrano',
    version => '2.15.4',
    ruby    => '2.0.0-p247'
  }
  ruby::gem { "capistrano_colors for 2.0.0-p247":
    gem     => 'capistrano_colors',
    ruby    => '2.0.0-p247'
  }

追加したら ./script/boxen --no-fde でインストールする。(※手元の環境(OS X Mavericks)ではインストール後に rbenvRuby のバージョンを指定しなければ capistrano を利用することが出来なかった...あれ?)

Ubuntu では

手元の Ubuntu 環境では以下のように gem でインストールした。

sudo gem install capistrano --no-ri --no-rdoc -V -v '2.15.4'
sudo gem install capistrano_colors --no-ri --no-rdoc -V

Docker を使ってアクセス先のノードを準備する

以下のように Dockerfile を書いて capistrano を使ってアクセスする為のノードを何個か用意しておく。

#
FROM inokappa/wheezy-7.2-basic
#
MAINTAINER YOHEI KAWAHARA inokappa
#
RUN apt-get update
RUN apt-get -y install puppet openssh-server
#
RUN mkdir -p /var/run/sshd
RUN useradd -d /home/sandbox -m -s /bin/bash sandbox
RUN echo sandbox:sandbox | chpasswd
RUN echo 'sandbox ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

使ってみる

初期化

適当にディレクトリをこさえてから capify コマンドを実行して capistrano を使う環境を準備する。

mkdir ${capistrano_dir}
cd ${capistrano_dir}
capify .

以下のように出力される。

[add] writing './Capfile'
[add] making directory './config'
[add] writing './config/deploy.rb'
[done] capified!

これで準備は完了。

cap -T

cap -T を実行すると capistrano でデフォルトで登録されているタスクの一覧が出力される。

cap deploy                # Deploys your project.
cap deploy:check          # Test deployment dependencies.
cap deploy:cleanup        # Clean up old releases.
cap deploy:cold           # Deploys and starts a `cold' application.
cap deploy:create_symlink # Updates the symlink to the most recently deployed version.
cap deploy:migrate        # Run the migrate rake task.
cap deploy:migrations     # Deploy and run pending migrations.
cap deploy:pending        # Displays the commits since your last deploy.
cap deploy:pending:diff   # Displays the `diff' since your last deploy.
cap deploy:restart        # Blank task exists as a hook into which to install your own environ...
cap deploy:rollback       # Rolls back to a previous version and restarts.
cap deploy:rollback:code  # Rolls back to the previously deployed version.
cap deploy:setup          # Prepares one or more servers for deployment.
cap deploy:start          # Blank task exists as a hook into which to install your own environ...
cap deploy:stop           # Blank task exists as a hook into which to install your own environ...
cap deploy:symlink        # Deprecated API.
cap deploy:update         # Copies your project and updates the symlink.
cap deploy:update_code    # Copies your project to the remote servers.
cap deploy:upload         # Copy files to the currently deployed version.
cap deploy:web:disable    # Present a maintenance page to visitors.
cap deploy:web:enable     # Makes the application web-accessible again.
cap invoke                # Invoke a single command on the remote servers.
cap shell                 # Begin an interactive Capistrano session.

もちろん、タスク自体は自分で追加することも出来るが、まずは一番下の cap shell を使ってみる。

cap shell を使ってノードにログイン

以下のようにして cap shell に続いて HOSTS= オプションの後にノードのホスト名、又は IP アドレス、そして、USER= の後にノードを作成した際に設定したユーザー(sandbox)を続ける。

cap shell HOSTS=xxx.xxx.xxx.1 USER=sandbox

実行すると以下のように表示されるので適当にコマンド(pwd)を叩いてみる。password には USER= で指定したユーザーのパスワードを入力する。

f:id:inokara:20140125101049p:plain

おお。ノード上でコマンドが実行されて結果が出力された...ん、でも、これだと普通に SSH でログインしたのと変わらぬ。

さらに cap shell を使って複数のノードにログイン

前述の通り、capistrano の旨みは複数のノードに対して並列してコマンドを投げることが出来る!だったので複数のノードに対して cap shell を実行してみる。HOSTS= オプションの後にノードを 2 つ並べて書いてみる。

cap shell HOSTS="xxx.xxx.xxx.1","xxx.xxx.xxx.2" USER=sandbox

おお。二つのノードで pwd コマンドの結果が出力された!こりゃ便利。

f:id:inokara:20140125101109p:plain

cap shell でアクセスしといて uptime なんか適当な間隔で叩いておくといい感じですな。


タスクを追加する

cap shell で複数ノードに対して一度にコマンドを実行する喜びをひと通り感じたところで、cap shell だと一つのコマンドしか実行出来ない*2なあと思ったあなたは鋭い。実行させたいコマンドをひと通り並べたタスクを追加することでその疑問を一気に解決。

config/deploy.rb を修正する

${capistrano_home}/config/deploy.rb を以下のように修正する。

require "capistrano_colors"

desc "test"
namespace :deploy do
  task :hoge do
    run "pwd"
    run "echo \"Hello Servers!\""
  end
end

修正したら以下のように実行する。

cap deploy:hoge HOSTS="xxx.xxx.xxx.1","xxx.xxx.xxx.2" USER=sandbox

以下のように出力される。

f:id:inokara:20140125101123p:plain

おお、それぞれのコマンドがノードで実行されている!

接続先のノードも deploy.rb に書いてみる

二つ、三つくらいのノードであれば HOSTS= に繋げてかけるが、それ以上だとコマンドラインに並べる妙技は崩壊してしまう*3。ということで、コマンドを実行させたいノードを role に書く。

require "capistrano_colors"

role :ahoaho, "xxx.xxx.xxx.1","xxx.xxx.xxx.2"

desc "test"
namespace :deploy do
  task :hoge do
    run "pwd"
    run "echo \"Hello Servers!!\""
  end
end

これを実行すると...

cap deploy:hoge USER=sandbox

以下のように出力される。

f:id:inokara:20140125101123p:plain

また、異なる role を複数記載することが出来る。さらに task に対して role を関連付けることも出来る。

require "capistrano_colors"

role :ahoaho, "xxx.xxx.xxx.1","xxx.xxx.xxx.2"
role :unko, "xxx.xxx.xxx.3","xxx.xxx.xxx.4"

desc "test"
namespace :deploy do
  desc "test hoge"
  task :hoge , roles: => :ahoaho do
    run "pwd"
    run "echo \"Hello Servers!!\""
  end

  desc "test huga"
  task :huga , roles: => :unko do
    run "uptime"
  end
end

上記の場合には roleahoaho には hogeroleunko には huga を実行される。


ということで

  • capistrano のほんの触り部分しか書けていないがこれだけでもインフラエンジニヤは感動
  • 次回は 複数の EC2 インスタンスノードにアクセスして chef-solopuppet apply 等を組み合わせてノードをデプロイ方法を書いてみたい

*1:Ruby をよく解っていないので

*2:&& などでコマンドを繋げば出来なくもない

*3:めんどくさいとも言う