2020年8月25日火曜日

Capistrano 3.14 を試してみた

概要

執筆時点では最新の Capistrano3.14 を試してみました
タスクの作成方法から実行までの簡単な流れをまとめています

環境

  • macOS 10.15.6
  • Ruby 2.7.1p83
    • capistrano 3.14.1

インストール

  • bundle init
  • vim Gemfile
gem "capistrano"
  • bundle config path vendor
  • bundle install

初期化

まずは capistrano が動作する環境を作成します

  • bundle exec cap install
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

必要最低限の config ファイルや Capfile と呼ばれる capistrano の管理ファイルが作成されます
またステージ (環境) は STAGES 変数にセットすると必要なファイルを自動で作成してくれます

  • bundle exec cap install STAGES=local,sandbox,qa,production

として実行すると config/deploy/local.rb や sandbox.rb, qa.rb なども作成してくれます
なおこの時点で自動である程度のタスクを作成してくれているので

  • bundle exec cap -T

と実行すると実行可能なタスクの一覧が表示されます
例えば doctor:environment タスクを実行すると capistrano の実行環境が確認できます

  • bundle exec cap production doctor:environment

デプロイ対象のサーバを定義する

今回はロールベースでデプロイ対象のサーバを定義します

  • vim config/deploy/production.rb
role :local_mac, %w{192.168.100.1}, my_property: :hello

とりあえず実行しているローカルの Mac をデプロイ対象のサーバにしています
「ロール名」「対象のサーバ」「プロパティ」という順番で定義します
他にも server という単位でデプロイ対象のサーバを定義できますが基本は 1 台ずつしか定義できないのでロールベースのほうがよく使うかなと思います

独自タスク定義

ではタスクを定義してみます
タスクは rake ファイル形式で記述する必要があるので .rake で作成します
とりあえず今回はテストなので role で定義したプロパティの値と実行中のホスト名でも表示してみたいと思います

  • vim lib/capistrano/tasks/test_tasks.rake
namespace :test do
  desc 'Show the hostname'
  task :echo do
    on roles(:local_mac) do |host|
      info "Host => #{host.hostname}"
      info "Properties => #{host.properties.fetch(:my_property)}"
    end
  end
end

この時点でタスクは capistrano に登録されているので cap -T で確認するとタスクの一覧に表示されるのが確認できると思います

  • bundle exec cap -T | grep echo
cap test:echo                      # Show the hostname

ちなみに roles + on でロールに含まれているサーバ分ループすることができます
引数の host は Capistrano::Configuration::Server クラスのオブジェクトで SSHKit::Host というクラスを継承しているため .username.password などで属性の参照ができます

ssh して実行してみる

実は上記のタスクは単純に config/deploy/production.rb で定義した値を参照しているだけなので実際に ssh はしていません
本来は対象のサーバに ssh してコマンドを実行します
その場合は (execute)[https://github.com/capistrano/sshkit#the-command-map] というリソースを使います
新たに execute するタスクを追加してみます

  • vim lib/capistrano/tasks/test_tasks.rake
namespace :test do
  desc 'Show the hostname'
  task :echo do
    on roles(:local_mac) do |host|
      info "Host => #{host.hostname}"
      info "Properties => #{host.properties.fetch(:my_property)}"
    end
  end

  desc 'Show macOS version'
  task :vers do
    on roles(:local_mac) do |host|
      execute :sw_vers
    end
  end
end

これで試しに test:vers タスクを実行してみると ssh できないというエラーになると思います

  • bundle exec cap production test:vers

Errno::ECONNREFUSED: Connection refused - connect(2) for 192.168.100.1:22
これは単純に実行しているローカルの Mac で sshd が有効になっていないだけです
ちゃんと sshd を有効にしてあげれば成功するのでこちらを参考に mac の sshd を有効にして再度動作確認してみましょう

cap console

便利なので紹介しておきます
'capistrano/console' という gem を使うことで実現できます
簡単に言うと任意のコマンドを role や server で定義したサーバに一括で ssh 経由で実行することができます
Capfile に一行追加しましょう

  • vim Capfile
require "capistrano/console"

そして cap production console とするとインタラクティブモードになり今回 role で指定したローカルの Mac に ssh してコマンドを実行することができます

  • bundle exec cap production console
capistrano console - enter command to execute on production
production> hostname
00:00 console
      01 hostname
username@192.168.100.1's password:
      01 mac01
    ✔ 01 192.168.100.1 6.271s

これが嬉しいのは例えば role に 100 台のサーバを登録したら 100 台のサーバに対して一斉に同じコマンドを実行したりすることができるようになります
ちなみに有効にするとちゃんと cap -T のタスクの一覧にも表示されます

最後に

最新版の Capistrano3.14 に触ってみました
基本はタスクを追加するだけなので表示に簡単にタスクはかけるかなと思います
バージョン管理の機能があるので切り戻しも簡単にできるかなと思います
ただ冪等性はなく基本は execute でコマンドをリモートで実行していくだけなので chef や ansible のような便利なリソースはないのでゴリゴリ自分でデプロイコードを書いていく必要はあります
一応 capistrano はプラグインの機能があるので Capistrano::Dockerbuild
のようにプラグインとして作成してリソースとして使用することはできるかなと思います

参考サイト

0 件のコメント:

コメントを投稿