newBike
newBike

Reputation: 15022

How do I push latest code into auto scaling group

I trying to run my production servers with AWS auto scaling framework.

I wonder how can I deploy the new published code into running production servers.

I don't care the down time currently.

I run the web server with nginx and puma

What's the common way to do this task ?

I think to login AWS console find all the servers IP and SSH into it. Update the codebase and restart the puma web server is not a good way to maintain quality product

Upvotes: 4

Views: 2784

Answers (2)

Cyril Duchon-Doris
Cyril Duchon-Doris

Reputation: 14039

I have created a special Capistrano deploy environment. It won't be as powerful as other deployment services you would find out there, but it does the job.

The assumption is that you have a remote machine you can SSH into to launch the deployment command (I suppose your server don't have public IPs, but you still have one bastion host that you can SSH into and where you can run a capistrano task). The machine will get the dns of all other machines, and deploy to them using the Capistrano deployment pipeline (I have added the id_rsa of that deployment machine in the authorized_keys of the other guys).

I am using Amazon tags to filter the instances : make sure your instances of the autoscaling group can be selected easily using tags.

In the code below, I also produce a warning for machines that are not inside the autoscaling group, but still behind the same load-balancer (using tags again)

# config/deploy/remote_production.rb
# [ several lines of capistrano configuration : git repo, branch, etc.]
#
# Deploy to autoscaling machines :
#
# Determine list of instances with aws sdk
require 'aws-sdk'

# Get instances IDs using tags
ec2 = Aws::EC2::Client.new

instances_tagged = ec2.describe_instances(
  dry_run: false,
  filters: [
    {
      name: 'tag:environment',
      values: ['production'],
    },
    {
      name: 'tag:stack',
      values: ['rails'],
    }
  ],
)

dns_tagged = instances_tagged.reservations[0].instances.map(&:private_dns_name)

# Get auto scaling group instance IDs
as = Aws::AutoScaling::Client.new
instances_of_as =  as.describe_auto_scaling_groups(
  auto_scaling_group_names: ['myApp-autoScale-prod'],
  max_records: 1,
).auto_scaling_groups[0].instances

if instances_of_as.empty?
  autoscaling_dns = []
else
  instances_ids = instances_of_as.map(&:instance_id)
  autoscaling_dns = instance_ids.map do |instance_id|
    ec2.instances[instance_id].private_dns_name
  end
end

# Get private DNS names for each machine

dns = dns_tagged | autoscaling_dns

if (extra_instances = (dns - autoscaling_dns).size) != 0
  puts "WARNING : there are #{extra_instances} more instances that just the ones of the autoscaling group !!"
end

# Set the Capistrano servers to deploy to
dns.each do |instance|
  server instance,
  roles: %w{web app db},
  user: 'ubuntu',
  port: 22,
  ssh_options: {
    keys: ['~/.ssh/id_rsa'],
    forward_agent: true,
    auth_methods: %w(publickey)
  }
end

I just have to do

ssh ssh@bastion_host
cd deploy/myApp
cap remote_production deploy

Upvotes: 0

John Rotenstein
John Rotenstein

Reputation: 270224

There are many choices for ways to deploy code on an Amazon EC2 instance. In fact, it is mostly the same as how you would deploy code on any normal computer, but Amazon EC2 has a few techniques that could make this easier.

Option 1: Configure an AMI

When a new Amazon EC2 instance is launched, an Amazon Machine Image (AMI) must be selected. The AMI is a disk image that is copied to the boot disk of the new instance, and the instance then boots using that image.

So, one option for deploying new code is:

  • Build a new AMI (by configuring an instance, then creating the image from that instance)
  • Create a new Auto Scaling Launch Configuration that uses the new AMI
  • Edit the Auto Scaling group to use the new Launch Configuration
  • Launch new instances in the Auto Scaling group (eg increase the minimum quantity of instances)
  • Once the new instances are launched, remove old instances (eg descrease the minimum and await automatic scale-down processes, or force the decrease by lowering the desired-capacity. Older instances will automatically be removed first, based on the Auto Scaling Termination Policy

Option 2: User Data scripts

This is similar to Option 1, but instead of configuring a new AMI, have the instances self-configure via a startup script. A script can be passed via the User Data field and this script will execute when a new instance is launched.

The script can do whatever you wish, eg download and install software, deploy using Puppet/Chef/Ansible, and start/stop the web server.

The User Data script should be stored within the Auto Scaling Launch Configuration (similar to the AMI in Option 1). Then, simply launch new instances (similar to Option 1) and they will automatically configure themselves with the latest version of your software.

Option 3: Use a deployment service

AWS has several systems that can deploy code to Amazon EC2 instances, including:

The first three can deploy the infrastructure as well as the code.

While these systems are more complex than simply providing a script, they allow a more repeatable, resilient architecture (eg handling failures and roll-backs).

Upvotes: 6

Related Questions