Continuing from last time, let's SSH in to the newly created EC2 instance in Capistrano.
First, AWS creates a key pair for the new instance. You can create a key pair from the EC2 menu in the AWS Management Console to the Key Pairs menu in the NETWORK & SECURITY category. In this example, we will use a key pair called "deploy-test" that is used by the deployment instance where Capistrano is running.

Then, upload the private key file of the key pair you want to use (the 'deploy-test.pem' file in this example) to the home directory of the user who will be deploying the deployment environment running Capistrano ('/home/deploy-user/' in this example).1。 You need to grant the appropriate read permissions to the private key you uploaded, so change the file permissions.
$ cd ~
$ chmod 600 deploy-test.pem
$ ls -l *.pem
-rw------- 1 deploy-user deploy-user 1692 Jul 2 10:18 deploy-test.pem
The deployment configuration file 'config/deploy.rb' has been modified as follows.
# config valid only for Capistrano 3.1
lock '3.2.1'
# Loading the AWS SDK for Ruby
require 'aws-sdk'
# Configuring for the AWS SDK
AWS.config({
:access_key_id => '<AWS access="" key="" id="">',
:secret_access_key => '<AWS secret="" access="" key="">',
:region => 'ap-northeast-1',
})
# AMI image_id
# Amazon Linux AMI 2014.03.2 (HVM)
set :ami_image_id, 'ami-29dc9228'
# Number of Instances to Create
set :instance_count, 2
# Instance Type to Create
set :ec2_instance_type, 't2.micro'
# Create Availability Zones
set :availability_zones, [ 'ap-northeast-1a', 'ap-northeast-1c' ]
# Create subnet_id (if necessary)
set :subnet_ids, [ 'subnet-********', 'subnet-********' ]
# Key Pair Name to Use
set :key_pair_name, 'deploy-test'
# Private Key File
set :privert_key_file, 'deploy-test.pem'
# Security group ID to be used
set :security_groups, [ 'sg-********', 'sg-********', 'sg-********', 'sg-********' ]
# Delete Capistrano default tasks
framework_tasks = [:starting, :started, :updating, :updated, :publishing, :published, :finishing, :finished]
framework_tasks.each do |t|
Rake::Task["deploy:#{t}"].clear
end
Rake::Task[:deploy].clear
desc 'Launch an EC2 instance to each availability zone different'
task :launch do
run_locally do
ec2 = AWS::EC2.new
created_instances = []
cnt = 0
while cnt < fetch(:instance_count) do
if cnt.even? then
current_az = fetch(:availability_zones)[0]
current_sn = fetch(:subnet_ids)[0]
else
current_az = fetch(:availability_zones)[1]
current_sn = fetch(:subnet_ids)[1]
end
i = ec2.instances.create(
:image_id => fetch(:ami_image_id),
:monitoring_enabled => false,
:availability_zone => current_az,
:subnet => current_sn,
:key_name => fetch(:key_pair_name),
:security_group_ids => fetch(:security_groups),
:disable_api_termination => true,
:instance_type => fetch(:ec2_instance_type),
:count => 1,
:associate_public_ip_address => true
)
sleep 10 while i.status == :panding
created_instances < i.id
cnt += 1
end
execute "echo -n #{created_instances} > ~/CREATED_INSTANCES"
end
end
Now, let's run the instance launch task.
$ cap test launch
INFO[3c926533] Running /usr/bin/env echo -n ["i-1c0c351a", "i-cfd209d6"] > ~/CREATED_INSTANCES on localhost
DEBUG[3c926533] Command: echo -n ["i-1c0c351a", "i-cfd209d6"] > ~/CREATED_INSTANCES
INFO[3c926533] Finished in 0.036 seconds with exit status 0 (successful).
Once you have confirmed the launch of the created instance in the AWS Management Console, try SSH with ec2-user on the command line.
$ ssh -i ~/deploy-test.pem ec2-user@176.34.61.235
The authenticity of host '176.34.61.235 (176.34.61.235)' can't be established.
ECDSA key fingerprint is **:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '176.34.61.235' (ECDSA) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2014.03-release-notes/
8 package(s) needed for security, out of 18 available
Run "sudo yum update" to apply all updates.
I succeeded safely.
Let's add a follow-up task to SSH access the newly created EC2 instance in Capistrano.
desc 'Check the activation status of new instances'
task :check do
created_instances_list = 'CREATED_INSTANCES'
run_locally do
ec2 = AWS::EC2.new
begin
if test "[ -f ~/#{created_instances_list} ]"
created_instances = capture("cd ~; cat #{created_instances_list}").chomp
ci = created_instances.gsub(/(\[|\s|\])/, '').split(',')
target_instances = ec2.instances.select { |i| i.exists? && i.status == :running && ci.include?( i.id) }.map(&:private_ip_address) #dns_name
if target_instances.length == 0 then
raise "No created instances"
end
pkfn = fetch(:privert_key_file)
target_instances.each { |var|
server var, user: 'ec2-user', roles: %w{web app}, ssh_options: { keys: %W(/home/deploy-user/#{pkfn}), forward_agent: true }
}
end
rescue => e
info e
exit
end
end
end
task :init => :check do
on roles(:web) do
access_log = capture "hostname"
info access_log
end
end
In the newly created "init" task, the "check" task is first executed to check whether the created instance has been launched. The check task retrieves the private IP address from the newly created instance ID and defines the SSH information as the accessed server with the WEB, APP role. At this time, the user is set to log in with a private key for access by the initial Amazon Linux user "ec2-user". If you do not set 'forward_agent' to TRUE, access will stop during the console interaction during the first SSH, so be careful. If the check task is OK, the init task is executed automatically. In this task, the hostname of each server that was logged in with the 'hostname' command is printed out and finished. Now, let's actually run the "init" task.
$ cap test init
DEBUG[8c9dcda9] Running /usr/bin/env [ -f ~/CREATED_INSTANCES ] on localhost
DEBUG[8c9dcda9] Command: [ -f ~/CREATED_INSTANCES ]
DEBUG[8c9dcda9] Finished in 0.003 seconds with exit status 0 (successful).
DEBUG[c1473094] Running /usr/bin/env cd ~; cat CREATED_INSTANCES on localhost
DEBUG[c1473094] Command: cd ~; cat CREATED_INSTANCES
DEBUG[c1473094] [i-1c0c351a, i-cfd209d6]
DEBUG[c1473094] Finished in 0.002 seconds with exit status 0 (successful).
DEBUG[1fe95f86] Running /usr/bin/env hostname on 176.34.62.57
DEBUG[1fe95f86] Command: /usr/bin/env hostname
DEBUG[7d485d1a] Running /usr/bin/env hostname on 176.34.61.235
DEBUG[7d485d1a] Command: /usr/bin/env hostname
DEBUG[7d485d1a] Finished in 0.131 seconds with exit status 0 (successful).
DEBUG[7d485d1a] ip-176-34-61-235
DEBUG[7d485d1a] Finished in 0.131 seconds with exit status 0 (successful).
INFOip-176-34-61-235
DEBUG[1fe95f86] Finished in 0.145 seconds with exit status 0 (successful).
DEBUG[1fe95f86] ip-176-34-62-57
DEBUG[1fe95f86] Finished in 0.145 seconds with exit status 0 (successful).
INFOip-176-34-62-57
I was able to successfully SSH in the new instance I created with Capistnrano. All you have to do is add the deployment settings for each instance to the task.
Next time, I will try to set a task in Capistrano to create a user other than ec2-user for the newly created instance and allow SSH access to that user to be able to SSH access with that user, while setting a password for the default ec2-user user and setting restrictions on SSH access by the default user. It is a security risk that a strongly privileged ec2-user user can access an EC2 instance forever, so creating a maintenance account on the created instance will be like the initial setup of an EC2 deployment.
- In AWS, you can download the private key of a key pair only once when creating a key pair, and you cannot obtain the private key file otherwise, so you need to be careful when handling the private key. ↩