如何将最新代码推送到自动缩放组

时间:2015-08-04 10:20:52

标签: ruby-on-rails amazon-web-services autoscaling

我尝试使用AWS自动扩展框架运行我的生产服务器。

我想知道如何将新发布的代码部署到正在运行的生产服务器中。

我现在不关心down time

我使用nginxpuma

运行网络服务器

执行此任务的常用方法是什么?

我认为登录AWS控制台会找到所有服务器IP和SSH。更新代码库并重启puma web服务器并不是维护优质产品的好方法

2 个答案:

答案 0 :(得分:4)

在Amazon EC2实例上部署代码的方法有很多选择。实际上,它与在任何普通计算机上部署代码的方式大致相同,但Amazon EC2有一些技术可以使这更容易。

选项1:配置AMI

启动新的Amazon EC2实例时,必须选择Amazon Machine Image(AMI)。 AMI是一个磁盘映像,复制到新实例的引导磁盘,然后该实例使用该映像启动。

因此,部署新代码的一个选项是:

  • 构建新的AMI(通过配置实例,然后从该实例创建图像)
  • 创建使用新AMI的新Auto Scaling启动配置
  • 编辑Auto Scaling组以使用新的启动配置
  • 在Auto Scaling组中启动新实例(例如,增加minimum实例数量)
  • 启动新实例后,删除旧实例(例如,减少minimum并等待自动缩小进程,或通过降低desired-capacity强制减少。旧实例将自动删除,基于Auto Scaling Termination Policy

选项2:用户数据脚本

这与选项1类似,但不是配置新的AMI,而是通过启动脚本自我配置实例。脚本可以通过User Data field传递,该脚本将在启动新实例时执行。

脚本可以执行任何操作,例如下载和安装软件,使用Puppet / Chef / Ansible进行部署,以及启动/停止Web服务器。

用户数据脚本应存储在Auto Scaling启动配置中(类似于选项1中的AMI)。然后,只需启动新实例(类似于选项1),他们将自动配置最新版本的软件。

选项3:使用部署服务

AWS有几个系统可以将代码部署到Amazon EC2实例,包括:

前三个可以部署基础架构和代码。

虽然这些系统比简单地提供脚本更复杂,但它们允许更具可重复性和弹性的架构(例如处理故障和回滚)。

答案 1 :(得分:0)

我创建了一个特殊的Capistrano部署环境。它不会像你在那里找到的其他部署服务一样强大,但它可以完成这项任务。

假设您有一台可以通过SSH连接的远程计算机来启动部署命令(我想您的服务器没有公共IP,但您仍然有一个堡垒主机可以通过SSH连接到您的位置可以运行capistrano任务)。该机器将获取所有其他机器的dns,并使用Capistrano部署管道部署到它们(我已将该部署机器的id_rsa添加到其他人的authorized_keys中)。

我使用Amazon标签过滤实例:确保可以使用标签轻松选择自动缩放组的实例。

在下面的代码中,我还为不在自动缩放组内但仍在同一负载均衡器后面的机器发出警告(再次使用标签)

# 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

我只需要做

ssh ssh@bastion_host
cd deploy/myApp
cap remote_production deploy