ようへいの日々精進XP

よかろうもん

インフラ作業でも活用するぞ!キャピキャピ Capistrano は永遠に不滅です (2019 年版)

tl;dr

複数台の EC2 インスタンスに全く同じ作業をやりたくて, みんな大好き Capistrano 3 をセットアップしてみましたのでメモします. 個人的に Capistrano 2 しか使ったことなかったので, だいぶん戸惑いながらもやりたいことは一応出来ました.

俺はこうした

deploy.rb

インフラ関連の作業だと, サーバーにログインして何らかのコマンドを実行することが多いので, 放っておいても execute メソッドが呼ばれまくる以下のような deploy.rb となりました. やりたいことは実にシンプルで, S3 バケット上にアップされている手製の RPM パッケージをサーバー上にダウンロード. ダウンロードした RPM パッケージを yum localinstall だけです.

lock "~> 3.11.0"

namespace 'ec2' do
  desc 'List files.'
  task :ls do
    on roles(:all) do
      execute "ls"
    end
  end
  
  desc 'Get packages.'
  task :get do
    on roles(:all) do
      execute "[ ! -d 'rpms' ] && mkdir rpms || echo 'skip'"
      execute "aws s3 sync s3://some.packages.your.domain/RPMS/ ./rpms/ --region=ap-northeast-1"
    end
  end
  
  desc 'Install packages.'
  task :install, :version do |task, args|
    on roles(:all) do
      within "/home/ec2-user/rpms" do
        execute :sudo, :yum, 'localinstall', '-y', "*#{args[:version]}*"
      end
    end
  end
  
  desc 'List up services.'
  task :services do
    on roles(:all) do
      execute :sudo, :chkconfig, '--list'
    end
  end
  
  desc 'Get service status.'
  task :status, :service do |task, args|
    on roles(:all) do
      execute :sudo, :service, args[:service], 'status'
    end
  end
  
  desc 'Restart service.'
  task :restart, :service do |task, args|
    on roles(:all) do
      execute :sudo, :service, args[:service], 'restart'
    end
  end
end

Capistrano 2 の時代は, 以下の用に run メソッドの後に普通にコマンドをべた書きしていました.

namespace :sample do
  task :taaaaask do
    run 'echo "Hello Servers!!"'
  end
end

最新の Capistrano だと, execute メソッドに続いて, コマンドは symbol で書く必要がありました. (最新でなくても, Capistrano 3 になった時点でこのような書き方になっていたのかもしれません)

namespace :sample do
  task :taaaaask do
    run :echo, 'Hello Servers!!'
  end
end

更に, sudo を絡めたい場合, 以下のように書けば動きました.

  desc 'Restart service.'
  task :restart, :service do |task, args|
    on roles(:all) do
      execute :sudo, :service, args[:service], 'restart'
    end
  end
end

上記のタスクは引数に指定したサービスを再起動するタスクです. 以下のように実行します.

bundle exec cap production restart[oreno-service]

tips

デフォルトタスクの無効化

cap -T でずらずらーっと出力されるデフォルトタスクを無効 (タスク一覧から非表示) にしたいです.

$ bundle exec cap -T
cap deploy                         # Deploy a new release
cap deploy:check                   # Check required files and directories exist
cap deploy:check:directories       # Check shared and release directories exist
cap deploy:check:linked_dirs       # Check directories to be linked exist in shared
cap deploy:check:linked_files      # Check files to be linked exist in shared
cap deploy:check:make_linked_dirs  # Check directories of files to be linked exist in shared
cap deploy:cleanup                 # Clean up old releases
cap deploy:cleanup_rollback        # Remove and archive rolled-back release
cap deploy:finished                # Finished
cap deploy:finishing               # Finish the deployment, clean up server(s)
cap deploy:finishing_rollback      # Finish the rollback, clean up server(s)
cap deploy:log_revision            # Log details of the deploy
cap deploy:published               # Published
cap deploy:publishing              # Publish the release
cap deploy:revert_release          # Revert to previous release timestamp
cap deploy:reverted                # Reverted
cap deploy:reverting               # Revert server(s) to previous release
cap deploy:rollback                # Rollback to previous release
cap deploy:set_current_revision    # Place a REVISION file with the current revision SHA in the current release path
cap deploy:started                 # Started
cap deploy:starting                # Start a deployment, make sure server(s) ready
cap deploy:symlink:linked_dirs     # Symlink linked directories
cap deploy:symlink:linked_files    # Symlink linked files
cap deploy:symlink:release         # Symlink release to current
cap deploy:symlink:shared          # Symlink files and directories from shared to release
cap deploy:updated                 # Updated
cap deploy:updating                # Update server(s) by setting up a new release
cap doctor                         # Display a Capistrano troubleshooting report (all doctor: tasks)
cap doctor:environment             # Display Ruby environment details
cap doctor:gems                    # Display Capistrano gem versions
cap doctor:servers                 # Display the effective servers configuration
cap doctor:variables               # Display the values of all Capistrano variables
cap ec2:get                # Get packages
cap ec2:install[version]   # Install packages
cap ec2:ls                 # List files
cap ec2:restart[service]   # Restart service
cap ec2:services           # List up services
cap ec2:status[service]    # Get service status
cap git:check                      # Check that the repository is reachable
cap git:clone                      # Clone the repo to the cache
cap git:create_release             # Copy repo to releases
cap git:set_current_revision       # Determine the revision that will be deployed
cap git:update                     # Update the repo mirror to reflect the origin state
cap git:wrapper                    # Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt
cap install                        # Install Capistrano, cap install STAGES=staging,production

必要なタスクだけを一覧に表示させたいので, 以下のように対象のタスクを .clear メソッドでクリアします.

Rake::Task['deploy:check'].clear
...
Rake::Task['git:wrapper'].clear
Rake::Task['install'].clear

上記のように, 無効にしたいタスクをズラーっと記述したファイル (今回は disable_task.rb を用意) で, deploy.rb から require_relative した. 以下のような感じになります.

require_relative 'disable_task'

lock "~> 3.11.0"

namespace 'ec2-monitor' do
  desc 'List files.'
  task :ls do
    on roles(:all) do
      execute "ls"
    end
  end
...
end

以下のようにデフォルトのタスクを消し去ることが出来ました.

$ bundle exec cap -T
cap ec2:get               # Get packages
cap ec2:install[version]  # Install packages
cap ec2:ls                # List files
cap ec2:restart[service]  # Restart service
cap ec2:services          # List up services
cap ec2:status[service]   # Get service status

以上

  • 一度に複数のサーバーを設定変更して, それが上手く動いた場合, なんだか偉くなった気持ちになるのは何なんでしょうか