詳細検索

Things to keep in mind when deploying AWS EC2 instances in Capistrano

Avatar
by maeno
6 min read

Things to keep in mind when deploying AWS EC2 instances in Capistrano
Translated from 日本語 • View original

The newly created EC2 instance in the previous deployment configuration file did not have a key pair, security group, etc., so I couldn't SSH the created instance as it was... 1orz

After that, I modified various deployment settings and was able to log in to the EC2 instance I created by SSH, so I wrote about the process as a memorandum. Well, when creating an AWS EC2 instance in Capistrano... Rather, what to keep in mind when creating an EC2 instance with the "AWS SDK for Ruby"... It may be close.

First, let's take a look at the task part of the instance launch from the previous 'config/deploy.rb'.

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), 
        :availability_zone => current_az,
        :subnet => current_sn, 
        :instance_type => fetch(:ec2_instance_type), 
        :count => 1
      )
      sleep 10 while i.status == :panding
      created_instances < i.id
      cnt += 1
    end
    execute "echo -n #{created_instances} > ~/CREATED_INSTANCES"

end
end

Since you only have the AvailabilityZone and Subnet settings for the instance you want to create, you will not be able to access it. At a minimum, you need to set up a security group to secure an external access route and set up a key pair to allow authenticated users to log in. After that, I think the minimum setting is to make it possible to automatically assign PublicIP (PublicDNS) and access it from the Internet.

So let's fix it right away. First, add the required settings as variables.

# Key Pair Name to Import
set :key_pair_name, 'mykeypair'

# Security group ID to be used
set :security_groups, [ 'sg-********', 'sg-********', 'sg-********' ]

# Kernel ID
set :kernel_id_name, 'aki-********'

Key pairs and security groups must be created in advance in the AWS console. A quick fix is to use the key pair and security group of the instance Capistrano is running as the deployment environment. Set the kernel ID as needed. Even if you don't have it, there won't be any problems. Then, change the method part of the EC2 class as follows.

      i = ec2.instances.create(
        :image_id => fetch(:ami_image_id),
        :block_device_mappings => [{
          :device_name => '/dev/sda1',
          :ebs => {
            :volume_size => 50,
            :delete_on_termination => true
          }
        }],
        :monitoring_enabled => false,
        :availability_zone => current_az,
        :subnet => current_sn,
        :key_name => fetch(:key_pair_name),
        :security_group_ids => fetch(:security_groups),
        :kernel_id => fetch(:kernel_id_name),
        :disable_api_termination => true,
        :instance_type => fetch(:ec2_instance_type),
        :count => 1,
        :associate_public_ip_address => true
      )

The newly added method options are as follows:

  • ':block_device_mappings' is the setting for EBS (ELASTIC BLOCK STORE). If you need to add more to the fixed instance storage capacity, add it. In this example, we're adding a 50 GB storage volume2.
  • ':monitoring_enabled' to start monitoring CloudWatch after the instance is launched.
  • :key_name … This is a required setting. Specify the key pair name3. Here we are calling the variables we defined earlier.
  • ':security_group_ids' is a required setting. Describe the security group IDs that have already been defined in an array format4. Here we are calling the variables we defined earlier.
  • ':kernel_id' if you want to use the kernel ID. If you try to create multiple instances from an HMV-enabled AMI with the same kernel ID, you will get an error, so do not specify it in that case.
  • Set the ':d isable_api_termination' to TRUE if you want to allow you to terminate the instance using the EC2 API.
  • ':associate_public_ip_address' is an important setting. If you want the created instance to be auto-assigned a PublicIP address, set it to TRUE5.

Now, with the modified deployment settings, let's run the instance launch task.

$ cap test launch
INFO[6866d5d4] Running /usr/bin/env echo -n ["i-70f0cf76", "i-f718c1ee"] > ~/CREATED_INSTANCES on localhost
DEBUG[6866d5d4] Command: echo -n ["i-70f0cf76", "i-f718c1ee"] > ~/CREATED_INSTANCES
INFO[6866d5d4] Finished in 0.034 seconds with exit status 0 (successful).
  • By the way, if you want to debug Capistrano tasks, it is useful to remember that if you run the task with the option 'cap test launch debug' or 'cap test launch --trace', it will trace the processing in detail.

Check it out in the AWS Management Console.

スクリーンショット1スクリーンショット2

Key pairs, security groups, and even PublicIP were launched as expected EC2 instances. Now, let's check that you can SSH from the console.

$ ssh default-user@176.34.61.218
The authenticity of host '176.34.61.218 (176.34.61.218)' can't be established.
RSA key fingerprint is **:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '176.34.61.218' (RSA) to the list of known hosts.
default-user@176.34.61.218's password:
Last login: Tue May 20 06:47:06 2014 from ******. ******. ******. *****.ne.jp
[default-user@ip-176-34-61-218 ~]$

I put it in. However, in this example, I created an instance from an AMI that had already created a user called "default-user" that can be SSH access, so I was able to log in easily, but if I created an instance from an official AWS AMI like in the previous example, it would take a little more work. Now, let's modify the task of creating an instance in "t2.micro" using the official AMI of "Amazon Linux AMI 2014.03.2 (HVM)" as before. Remove the EBS configuration and kernel ID specifications that cause errors when launching an instance from an HVM-enabled AMI.

      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
      )

Now, let's do it.

$ cap test launch
INFO[520beb79] Running /usr/bin/env echo -n ["i-abd4ebad", "i-580fd641"] > ~/CREATED_INSTANCES on localhost
DEBUG[520beb79] Command: echo -n ["i-abd4ebad", "i-580fd641"] > ~/CREATED_INSTANCES
INFO[520beb79] Finished in 0.035 seconds with exit status 0 (successful).

After checking the PrivertIP from the instance ID created in the AWS Management Console, SSH with the default user "ec2-user" of the Amazon Linux AMI from the console.

$ ssh ec2-user@176.34.61.153
The authenticity of host '176.34.61.153 (176.34.61.153)' 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.153' (ECDSA) to the list of known hosts.
Permission denied (publickey).

Of course, although I was able to connect, I couldn't access it because of public key authentication. You cannot connect without attaching the private key with the option 'ssh -i' and authenticating it. This means that in order to perform the following tasks in Capistrano on the instance you created, you need to prepare the private key to be used for instance creation on the deployment server where Capistrano is running. Then, the first SSH to the new instance should use the private key to log in. This is the end of this section. Next time, we will summarize the steps to SSH to a new instance via Capistrano as a task immediately after the instance launch.

Reference Sites


  1. The SDK documentation states a note (hereinafter ":key_name (String) — The name of the key pair to use. Note: Launching public images without a key pair ID will leave them inaccessible.") 

  2. If you use EBS volumes, HVM-enabled AMIs will no longer be available. Therefore, you need to change the instance type to "t1.micro" instead of "t2.micro", which is dedicated to HMV. 

  3. I haven't tried the behavior, but it looks like you can import key pairs as well. In that case, would the description look like ':key_pair => ec2.key_pairs.import(fetch(:key_pair_name), File.read('~/.ssh/identity.pub')),'? (Unverified)

  4. If you do not specify a security group, only the default group is set and can only be accessed from the same VPC network. 

  5. The default setting is FALSE, so if you don't put this setting, PublicDNS will not be enabled. 

Related Articles