Статьи

Использование возможностей Ruby SDK на AWS

С момента запуска в начале 2006 года Amazon Web Services (AWS) является доминирующей организацией в облачных вычислениях. Их предложение включает в себя такие услуги, как EC2 для эластичных вычислений, S3 для простого хранения объектов, RDS для реляционных баз данных и многое другое. Компании-разработчики программного обеспечения используют облачную модель, чтобы не только масштабировать приложения по мере роста спроса, но и контролировать расходы, связанные с развертыванием программного обеспечения. В течение прошлого года я все больше и больше использовал AWS в различных проектах разработки. Amazon предоставляет графический интерфейс пользователя, называемый Консоль управления AWS, который обеспечивает полный контроль над всеми его услугами. Консоль управления AWS подходит для решения многих задач, связанных с настройкой и обслуживанием облачной инфраструктуры.

Однако, когда я начал использовать более сложные функции в AWS, мне быстро потребовался более мощный и программный интерфейс, который я мог бы писать в рамках своего рабочего процесса разработки. Для доступа к AWS доступно множество SDK . Интерфейс командной строки предоставляет полностью функциональные возможности для сценариев, но обработка текста ответов сопряжена с большими накладными расходами. Java SDK так же имеет доступ ко всем AWS функции и объектно-ориентированной библиотеки составляет обработка ответов гораздо проще. Но многословность кода — необходимость создавать и создавать отдельный объект запроса для каждого вызова — приводила к тому, что сценарии становились большими, даже для простых случаев использования. Наконец-то я наткнулся на Ruby SDK для AWS и с тех пор не оглядывался назад.

обзор

AWS применяет строгую модель безопасности — идентификатор ключа доступа предоставляет сопоставления с номером вашей учетной записи и секретный ключ доступа, используемый для подписания всех запросов к API. Поэтому первыми шагами по использованию SDK являются настройка ключей доступа. Ruby SDK упрощает процесс, принимая файл YAML в следующем формате:

access_key_id: <access_key>
secret_access_key: <secret_key>

Чтобы завершить настройку, просто вызовите config:

AWS.config(YAML.load(File.read(path_to_config_file)))

Одним из потенциальных «уловок» этой настройки является то, что конфигурация требуется перед каждым вызовом функций AWS. Поэтому, даже если вы зайдете в irb для проверки некоторых функций, не забудьте вызвать AWS.config.

SDK включает в себя множество сервисов — IAM (управление идентификацией и контролем доступа), ELB (поддержка балансировки нагрузки), SES (сервисы электронной почты), VPC (виртуальное частное облако) и другие, — предоставляемые через классы в модуле AWS. Создание объекта для отправки запросов так же просто, как это:

ec2 = AWS::EC2.new

Интерфейс для объектов EC2 является одним из самых интуитивно понятных и приятных в использовании, которые я когда-либо испытывал. Он работает так, как вы могли ожидать, если вы хотите увидеть все запущенные экземпляры, просто выполните:

ec2.instances

Тонкое предостережение для Ruby SDK — это ленивый механизм загрузки. Когда вы запрашиваете коллекцию, такую ​​как экземпляры, все экземпляры фактически не перечисляются при вызове метода. До тех пор, пока вы не выполните итерацию по коллекции, будет сделан фактический запрос на получение информации экземпляра. Это может сэкономить на ненужном сетевом трафике, ограничивая количество требуемых запросов HTTP туда-обратно. Однако это также может привести к непредвиденным задержкам выполнения вашего скрипта, так что будьте осторожны.

Возвращаясь к примеру EC2, мы можем ссылаться на указанные экземпляры в EC2, используя идентификатор экземпляра, предоставленный Amazon:

ec2.instances['i-23ab45cd']

Каждый экземпляр, в свою очередь, представляет собой собственный набор методов, которые мы можем вызывать для получения информации, такой как группа безопасности, идентификатор Amazon Machine Image (AMI), эластичный IP-адрес, время запуска и многое другое. Процесс создания вещей в AWS (например, экземпляры) следует фабричному шаблону, где коллекция объекта действует как фабричная. Чтобы запустить новый экземпляр в EC2, нам просто нужно вызвать метод create:

ec2.instances.create([instance_options])

Примеры

Я собрал несколько примеров написанных мной скриптов для управления AWS и скомпилировал их на своей странице Github . Вот пример сценария для запуска экземпляра EC2 в виртуальном частном облаке. Здесь aws_config.rb выполняет конфигурацию для нас.

  #!/usr/bin/env ruby
  
  require '../config/aws_config'
  require 'aws-sdk'
 
  (private_ip, security_group_id, image_id, subnet_id) = ARGV
  
  # Check for necessary parameters
  unless private_ip && security_group_id && image_id && subnet_id
   puts "Usage #{$0} private_ip security_group_id image_id subnet_id"
   exit 1
 end
 
 # Instantiate EC2 object
 ec2 = AWS::EC2.new
 
 new_inst = ec2.instances.create(
   :image_id => image_id,
   :subnet => ec2.subnets[subnet_id],
   :instance_type => 'm1.large',
   :key_name => your_key_name,
   :private_ip => private_ip,
   :security_group_ids => { security_group_id })
 
 puts "Waiting for new instance with id #{new_inst.id} to become available..."
 
 sleep 1 while new_inst.status == :pending
 new_inst.add_tag('Name', :value => private_ip)
 
 puts '...ready'

Одна стратегия развертывания, которая мне показалась полезной, заключается в группировании экземпляров EC2 по ролям. Роли — это логические группировки, основанные на функциональных возможностях узла, таких как веб-прокси, сервер приложений, база данных, система мониторинга или что-то еще. Добавить роли к экземплярам так же просто, как добавить тег к экземпляру EC2 с помощью ключа «Роль». Вот еще один скрипт, который показывает информацию обо всех запущенных экземплярах в VPC, сгруппированных по ролям.

  #!/usr/bin/env ruby
  
  require File.expand_path(File.dirname(__FILE__) + '/../config/aws_config')
  
  vpc = AWS::EC2.new.vpcs.first
  
  vpc.instances.group_by { |inst| inst.tags['Role'] }.each do |role, instances|
    if role == nil || role.length == 0 then next end 
    puts "#{role}:"
   instances.each do |inst|
     sec_groups = inst.security_groups.collect {|sg| sg.name }.join(', ')
     puts "  Name: #{inst.tags['Name']}"
     puts "  ID: #{inst.id}" 
     puts "  AMI: #{inst.image_id}"
     puts "  Private IP: #{inst.private_ip_address}"
     puts "  Elastic IP: #{inst.public_ip_address}" if inst.public_ip_address
     puts "  Security groups: #{sec_groups}"
     puts
   end 
   puts
 end