capistrano/capistranoでサーバー管理/初期設定


初期設定

以下の作業は全て管理サーバー上で行います。
前提条件として、この手順の時点では管理されるサーバーに対しては管理サーバーからrootアカウントでSSHのパスワードログインできるようにしておいて下さい。
もしSSHでパスワードログインできない運用中のサーバーに対してcapistranoでの管理を始めたい場合は、一旦テスト用のサーバーなどを用意して一通り内容を理解してからにすることをおすすめします。

プロジェクトディレクトリ作成

まずはプロジェクトのディレクトリを作成します。
サーバー管理なのでmanageとでもしておきましょう。
# mkdir -p /opt/capistrano/manage

capistranoファイル作成

続けて、作成したディレクトリにcapistranoのファイルを作成します。
ver2の時はcapifyというコマンドでしたが、ver3でcap installに変わったようです。
実行する時の末尾のドットを忘れないようにして下さい。
# cd /opt/capistrano/manage
# cap install .
cap installを実行すると以下のディレクトリとファイルが作成されます。
manage
|- Capfile(ファイル)
|- config(ディレクトリ)
|  |- deploy.rb(ファイル)
|  |- deploy(ディレクトリ)
|     |- production.rb(ファイル)
|     |- staging.rb(ファイル)
|- lib(ディレクトリ)
   |- capistrano(ディレクトリ)
      |- tasks(ディレクトリ)

Capfile編集

Capfileを編集して以下の行を好きな所に追加します。
require 'capistrano/console'
これは追って説明しますが、複数のサーバー対して同時にコマンド実行して結果を表示するという便利ツールを使うための設定です。

hostsファイル編集

capistranoを使う場合はhostsファイルが編集できると便利です。
可能であれば/etc/hostsにhostnameとIPの対応を記述しましょう。
例えばこんな感じです。
192.168.0.1 manager
192.168.0.11 web1
192.168.0.12 web2
192.168.0.21 app1
192.168.0.22 app2
192.168.0.31 db1
192.168.0.32 db2
独自にDNSを運用している場合はそちらでも良いです。
今後管理するサーバーが増えたりした時はこちらの記述を忘れないようにしましょう。
hostsを汚したくなかったり、hostsを編集する権限が無い場合はこの手順は飛ばしても構いません。

サーバー管理ファイル作成

サーバーやロールの設定は処理本体を記述するファイルの中に直接書いてしまうことが多いようですが、サーバー管理に使う場合は台数が多くなるので別ファイルに分けておくと便利そうです。
ちなみにロールとは、グループやタグのような物として認識されるcapistranoの機能です。

さて、config/servers.rbを以下の様な形で実際の環境に合わせた内容で作成します。
user = 'root'
pass = 'password'

server 'manager', :roles => [ :manager ], :user => user, :password => pass
server 'web1', :roles => [ :web ], :user => user, :password => pass
server 'web2', :roles => [ :web ], :user => user, :password => pass
server 'app1', :roles => [ :app ], :user => user, :password => pass
server 'app2', :roles => [ :app ], :user => user, :password => pass
server 'db1', :roles => [ :db ], :user => user, :password => pass
server 'db2', :roles => [ :db ], :user => user, :password => pass
ちなみに、上記は立派なrubyのソースコードです。
例えば1~2行目。
user = 'root'
pass = 'password'
ここではuserという変数にrootという文字列型の値を、passという変数にpasswordという文字列型の値を代入しています。
何らかの文字列をシングルクォートで囲うとその文字列は文字列型の値であるという意味になるので、上記の様な処理になります。

そして4行目の処理はこれです。
server 'manager', :roles => [ :manager ], :user => user, :password => pass
ここではserverというメソッド(関数のような物)に、
第一引数に'manager'
第二引数に:roles => [ :manager ]
第三引数に:user => user
第四引数に:password => passという値を与えています。
(一般的なプログラム言語では、引数はカンマで区切ります)

rubyの場合はメソッドの()を省略できるので、あえて()を付けて多少見慣れた形にするとこうなります。
server( 'manager', :roles => [ :manager ], :user => user, :password => pass )
:から始まる文字列はシンボルと言い、連想配列のキーや単なる値などに使える特殊な文字列です。
:roles => [ :manager ]は、連想配列のキーとなるシンボル :roles に、値が :manager というシンボル一つしか入っていない配列を代入しています。
[ ~ ]は配列型の値を定義する処理です。

続けて、 :user には先程変数として作成した user を入れています。(中身はrootという文字列ですね)
そして :password には pass(中身はpasswordという文字列)を入れました。
user や pass は変数なので、このように書いても同じです。
server( 'manager', :roles => [ :manager ], :user => 'root', :password => 'password' )
パスワードがサーバー別に管理されている場合はこのような書き方でも良さそうです。
パスワードをファイルに直接書きたくない場合の対応は追って記載します。

serverメソッドにおいて、連想配列のキーとして使われた :roles、:user、:password といったシンボルはオプションとして特別な意味を持ちます。
それぞれ、そのサーバーのロール、そのサーバーのSSHユーザー、そのサーバーのSSHパスワードといった具合です。
serverメソッドの内部において、:roles の中身にどんな値が入っているかをチェックして動作を決めたりします。
他にもオプションとして使えるシンボルがいくつかありますが、現時点では公式なドキュメントが分かりやすい形にはまとまっていないのでいずれまとめたいと思います。

シンボルへの代入は => を使わず、後ろに : を使った書き方もできます。
server( 'manager', roles: [ :manager ], user: user, password: pass )
文字数が少なく済むのでこちらの形の方が多いかもしれません。
いずれにしても、managerというサーバーを定義していることを表しています。

hostsを編集しなかったりDNS名前解決できない場合は、config/servers.rbを以下の様に作成します。
user = 'root'
pass = 'password'

manager = '192.168.0.1'
web1 = '192.168.0.11'
web2 = '192.168.0.12'
app1 = '192.168.0.21'
app2 = '192.168.0.22'
db1 = '192.168.0.31'
db2 = '192.168.0.32'

server manager, :roles => [ :manager ], :user => user, :password => pass
server web1, :roles => [ :web1, :web ], :user => user, :password => pass
server web2, :roles => [ :web2, :web ], :user => user, :password => pass
server app1, :roles => [ :app1, :app ], :user => user, :password => pass
server app2, :roles => [ :app2, :app ], :user => user, :password => pass
server db1, :roles => [ :db1, :db ], :user => user, :password => pass
server db2, :roles => [ :db2, :db ], :user => user, :password => pass
こちらは4行目の
manager = '192.168.0.1'
でmanagerという変数に対して192.168.0.1というIPを文字列として代入し、serverメソッドの第一引数ではそのIPを使っています。
代入しなくても下記の様な記述で1行にしても構いませんので、お好きな方で良いです。
server '192.168.0.1', :roles => [ :manager ], :user => user, :password => pass
ここで注意が必要なのは、実際にサーバーに対して処理をする時にはserverメソッドの第一引数によって識別されるということです。

もし第一引数がmanagerという文字列だった場合
server 'manager', :roles => [ :manager ], :user => user, :password => pass
この場合はmanagerというサーバーに対して処理を行うと、managerがhostsまたはDNSによってアドレス解決されて192.168.0.1というアドレスに接続して処理されます。
hostsへの記述をしていない場合は名前解決できないので'192.168.0.1'というIPで記述するしかありません。

しかしながら普段はサーバーの識別を名前で行っている場合も多いはずで、IPなんて覚えたくないということもあります。
この問題を解決するため、各サーバーに対してサーバー名と同じになる固有のロールを割り当てておきます。
web1には:web1というロール、web2には:web2というロール、という具合です。
実際の処理で web1 というサーバーに対してだけ処理をしたい場合は、 :web1 というロールに対して処理をするように実行することで web1 サーバーのみに処理を反映することができるようになります。

実際の処理ファイル作成

さて、処理本体を作っていきます。
config/deploy/manage.rbを以下の内容で作成します。
とりあえず一旦動作確認するだけなので内容は簡単です。
load 'config/servers.rb'

task :test_task do
  on roles( :all ) do
    execute "hostname"
  end
end

1行目で先程作成したservers.rbを読み込んでいます。
load 'config/servers.rb'
パスはプロジェクトのトップディレクトリからの相対パスなので、このような記述になっています。

実際の処理はタスクという単位で管理されます。
task :test_task do
  ~
end
taskというメソッドの第一引数に :test_task というシンボルを与えるとtest_taskという名称のタスクを定義したことになります。
更に do ~ end で囲み(ブロックで囲むとか言ったりします。中括弧 { } の場合もあります。)、test_taskというタスクの中身を記述していきます。

中身はこうです。
 on roles( :all ) do
    execute "hostname"
  end
ここではonというメソッドの引数に、rolesメソッドの結果を渡しています。
rolesメソッドの引数は :all となっており、これによりserverメソッドで定義したサーバーがコレクションとして全て返ります。
更にonメソッドから do ~ end のブロックで囲むと、コレクションに対して順番に処理が走ることになります。

実際の処理はこうです。
   execute "hostname"
executeメソッドはサーバー上でコマンドを実行するメソッドですので、サーバー上でhostnameコマンドを実行するという処理になります。

タスクの実行

作成したタスクを実行するのは下記のコマンドです。
実行する場合は必ずプロジェクトのトップディレクトリで実行して下さい。(Capfileが配置してある場所です)
# cap manage test_task
第一引数は処理ファイル名から .rb を抜かした物です。
作成したファイルが manage.rb なので、引数はmanageです。
第二引数はタスク名ですので、test_taskです。

各ノードからのhostnameコマンドの結果がちゃんと表示されたでしょうか?

コンソール

便利ツールとしてのコンソールについて簡単に触れておきます。
コンソールを実行するコマンドは下記の通りです。
# cap manage console
consoleというタスクを実行する形ですね。

プロンプトが出るのでコマンドを実行すると、結果が返ってくるはずです。
注意点としては、途中で入力を求められるようなインタラクティブなコマンドには対応していないことです。
(viやpasswd、ssh-keygenなど)

使い方次第では強力なツールになるはずですので、いろいろ試してみて下さい。




  • 最終更新:2016-01-20 10:18:51

このWIKIを編集するにはパスワード入力が必要です

認証パスワード