Capistrano(3.x)でデプロイする
AWS内のステージング環境をセットアップしているとアプリが動くところを早く確認したくなり、過去の案件で使われてたCapistranoの設定を流用してさっさとデプロイしようとしたところ、最近はバージョンが3らしく、書き方も大きく変わっているようです。 Capistrano2.xのまま使おうかとも考えたのですが、プログラム担当で神主の息子でもある御方に「ちゃんと勉強して」と怒られたので3にさせていただきます。 このような記事を参考にしてCapfile、deploy.rbを設定しました。
いつものように設定について解説は網羅しませんが、補足しておきたいことだけ書いておきます。
インターネット越しのデプロイは踏み台サーバを経由して各サーバにSSHする
手元の端末からAWS内の各サーバ一にデプロイする時は、一度踏み台サーバにsshしてそこから各サーバにさらにSSHする方針にします。 専用にVPNはるのも大げさなような気がするし、かといってインターネットから全てのインスタンスに直でSSHできるのもあれなので。
お手元のPC(cap叩く) | | 踏み台サーバ | | 各サーバ
Capistrano2.xのときは踏み台経由でのデプロイがサポートされていたと思うのですが、3では実装されていないようです。 作業する方には各自クライント端末の.ssh/configに以下のようなproxy設定をしてもらうことにします。
Host fumidai.example.com HostName fumidai.example.com User ec2-user Port 12345 Host 172.31.*(VPC内のネットワークアドレスがこれに収まる) User ec2-user ProxyCommand nohup ssh fumidai.example.com exec nc %h %p
こうすると手元の端末から$ssh 172.31.1.1
と実行した場合、fumidai.example.comにsshしてからさらに172.31.1.1にsshすることになります。
もし手元の端末が172.31.なネットワーク環境下にいた場合は正しく動作しないかもしれません。ネットワークがかぶらない前提の設定です。
デプロイ実行時に動的にroleの設定をする
負荷によってec2インスタンスが増減するのでデプロイ時にインスタンスのタグを参照して、条件に該当するipをroleに設定するようにします。
stagingデプロイの際、インスタンスにweb=stagingのタグがあればこのインスタンスのipがrole:webとしてセットされます。
app=stagingがあればrole:appにもセットされます。
インスタンスのipを返すスクリプト自体は:gateway_server
のサーバ上に置いて、デプロイ時にssh越しでそれを叩いています。
lib/capistrano/tasks/aws.cap
# -*- coding: utf-8 -*- # namespace :aws do desc "role設定する" task :set_roles do on fetch(:gateway_server) do ["proxy", "web", "app", "db"].each do |role| ips = capture("ec2_roles.rb #{fetch(:stage)} #{role}).to_s.split(/\s+/) unless ips.empty? role role.to_sym, ips puts role puts ips end end end end end
ec2_roles.rb
require 'aws-sdk' roles = ARGV.shift roles ||= "app" stage = ARGV.shift stage ||= "staging" AWS.config(YAML.load(File.read('config.yml'))) ips = [] AWS::EC2.new.instances.tagged("#{stage}:role:#{role}").tagged_values("1").each{|ec2| ips << ec2.private_ip_address.to_s if ec2.status.to_s == "running" } puts ips