LoginSignup
2
2

More than 5 years have passed since last update.

aws cli + resque + daemon-spawn で EC2 インスタンスを起動・停止

Posted at

概要

  • resque に「起動してね」「停止してね」というキューを積むと EC2 インスタンスを起動・停止する
  • ↑ 用のプロセスは daemon-spawn で常駐化
  • EC2 インスタンスの起動・停止は AWS CLI を利用して実現する

AWS CLI のインストール

$ sudo easy_install pip 
$ sudo pip install awscli 
$ aws configure --profile my_profile
AWS Access Key ID [None]: AKIAYB7....
AWS Secret Access Key []: q-SLuyqi+oV....
Default region name []: ap-northeast-1
Default output format []: ※何も入力せず Enter

※事前に EC2 操作用の IAM を作成して、Access Key/Secret Access Key を払い出しておくこと。

参考:第1回 AWS CLIをインストール:インフラ屋のAWSはじめた日記─GUIを捨てよ

実装

app/workers/instaces_manager.rb
EC2_REGION = Settings.aws_ec2.region
CLI_PROFILE = Settings.aws_ec2.profile

class InstancesManager
  # 処理種別
  RUN_INSTANCES      = 1    # 起動
  TERMINATE_INSTANCE = 100  # 停止

  @queue = Settings.resque.manager.queue

  def self.perform(processing_type, options = {})
    begin
      logger = Logger.new(File.join(Rails.root, Settings.resque.manager.log_file))

      # 処理開始
      start_time = Time.now
      logger.info("[PID:#{$$}]: instances_manager start at: #{start_time}")

      # インスタンス起動・停止
      begin
        case processing_type
          when RUN_INSTANCES      then run_instances(options['count'])
          when TERMINATE_INSTANCE then terminate_instance(options['instance_id'])
        end
        logger.info("[PID:#{$$}]: success: processing_type=#{processing_type}, options=#{options}")
      rescue =>e
        logger.error("[PID:#{$$}]: failure: processing_type=#{processing_type}, options=#{options}")
        logger.error(e)
      end

      # 処理終了
      finished_time = Time.now
      logger.info("[PID:#{$$}]: instances_manager finished: #{start_time}(from) - #{finished_time}(to): #{finished_time - start_time}(processing time)")
    rescue =>e
      logger.error(e)
    end
  end

  def self.run_instances(count)
    image_id            = Settings.aws_ec2.xxx.image_id
    instance_type       = Settings.aws_ec2.xxx.instance_type
    key_name            = Settings.aws_ec2.xxx.key_name
    security_group_name = Settings.aws_ec2.xxx.security_group_name

    command = [
        'aws ec2 run-instances',
        '--image-id', image_id,
        '--count', count,
        '--instance-type', instance_type,
        '--key-name', key_name,
        '--security-groups', security_group_name,
        '--region', EC2_REGION,
        '--profile', CLI_PROFILE
    ].join(' ')
    IO.popen(command){}
  end

  def self.terminate_instance(instance_id)
    command = [
        'aws ec2 terminate-instances',
        '--instance-ids', instance_id,
        '--region', EC2_REGION,
        '--profile', CLI_PROFILE
    ].join(' ')
    IO.popen(command){}
  end
end
bin/instances_manage_worker.rb
#!/usr/bin/env ruby
require File.expand_path('../../config/application', __FILE__)
Rails.application.require_environment!

class InstancesManageDaemon < DaemonSpawn::Base
  def start(args)
    @worker = Resque::Worker.new(Settings.resque.manager.queue)
    @worker.work
  end

  def stop
    # 処理中のjobを完了後、shutdownする
    @worker.try(:shutdown)
  end
end

InstancesManageDaemon.spawn!({
  :working_dir => Rails.root,
  :pid_file => File.join(Rails.root, Settings.resque.manager.pid_file),
  :log_file => File.join(Rails.root, Settings.resque.manager.log_file),
  :sync_log => true,
  :singleton => true
})

インスタンスを起動する

Resque.enqueue(InstancesManager, InstancesManager::RUN_INSTANCES, count: 5)

インスタンスを停止する

Resque.enqueue(InstancesManager, InstancesManager::TERMINATE_INSTANCE, instance_id: my_instance_id)

def my_instance_id
  command = '/usr/bin/curl "http://169.254.169.254/latest/meta-data/instance-id"'
  IO.popen(command){|io| io.gets}
end
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2