Назад | Перейти на главную страницу

Как узнать, является ли машина экземпляром EC2

Я хотел бы запустить несколько скриптов на хостах, которые являются экземплярами EC2, но я не знаю, как быть уверенным, что хост действительно экземпляр EC2.

Я сделал несколько тестов, но этого недостаточно:

Изменен ответ Ханнеса, чтобы избежать сообщений об ошибках и включить пример использования в скрипт:

if [ -f /sys/hypervisor/uuid ] && [ `head -c 3 /sys/hypervisor/uuid` == ec2 ]; then
    echo yes
else
    echo no
fi

Это не работает в экземплярах Windows. Преимущество перед изгибом заключается в том, что он практически мгновенен как на EC2, так и на не EC2.

Обновить: Для новых экземпляров C5 / M5 используйте файл /sys/devices/virtual/dmi/id/product_uuid вместо этого и проверьте EC2 вместо того ec2. (Спасибо Джошу и Саумитре в комментариях за упоминание этого)

Во-первых, я почувствовал необходимость опубликовать новый ответ из-за следующих тонких проблем с существующими ответами, а также после получения вопроса о моем прокомментируйте ответ @ qwertzguy. Вот проблемы с текущими ответами:

  1. В принятый ответ from @MatthieuCerda определенно не работает надежно, по крайней мере, на любых экземплярах VPC, с которыми я проверял. (В моих экземплярах я получаю имя VPC для hostname -d, который используется для внутреннего DNS, а не для чего-либо, содержащего amazonaws.com.)
  2. В получивший наибольшее количество голосов ответ из @qwertzguy не работает на новых экземплярах m5 или c5, у которых нет этого файла. Amazon не документирует это изменение поведения AFAIK, хотя страница документа по этому поводу говорит "... Если / sys / hypervisor / uuid существует ... ". Я спросил службу поддержки AWS, было ли это изменение намеренным, см. ниже †.
  3. В ответ от @Jer не обязательно работает везде, потому что instance-data.ec2.internal Поиск DNS может не работать. На экземпляре Ubuntu EC2 VPC, на котором я только что тестировал, я вижу: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal что может привести к тому, что код, использующий этот метод, ошибочно сделает вывод, что его нет на EC2!
  4. В ответ использовать dmidecode from @tamale может работать, но зависит от вас a.) имея dmidecode доступный на вашем экземпляре, и б.) имеющий root или sudo возможность без пароля из вашего кода.
  5. В ответ на проверку / sys / devices / virtual / dmi / id / bios_version from @spkane опасно вводит в заблуждение! Я проверил один экземпляр Ubuntu 14.04 m5 и получил bios_version из 1.0. Этот файл вообще не документирован в документе Amazon, поэтому я бы не стал на это полагаться.
  6. Первая часть ответ от @ Chris-Montanaro чтобы проверить ненадежный сторонний URL и использовать whois по результату проблематично на нескольких уровнях. Обратите внимание, что URL, предложенный в этом ответе, прямо сейчас является страницей 404! Даже если бы вы нашли работающую стороннюю службу, она была бы сравнительно очень медленно (по сравнению с локальной проверкой файла) и, возможно, столкнется с проблемами ограничения скорости или проблемами сети, или, возможно, ваш экземпляр EC2 даже не имеет внешнего доступа к сети.
  7. Второе предложение в ответ от @ Chris-Montanaro Проверять http://169.254.169.254/ немного лучше, но другой комментатор отмечает, что другие облачные провайдеры делают доступным этот URL-адрес метаданных экземпляра, поэтому вы должны быть осторожны, чтобы избежать ложных срабатываний. Кроме того, он все равно будет намного медленнее, чем локальный файл, я видел, что эта проверка была особенно медленной (несколько секунд для возврата) на сильно загруженных экземплярах. Кроме того, вы должны не забыть пройти -m или --max-time аргумент curl, чтобы он не зависал в течение очень долгого времени, особенно в экземпляре, отличном от EC2, где этот адрес может вести в никуда и зависать (как в ответ @algal).

Кроме того, я не вижу, чтобы кто-нибудь упомянул Задокументированные откат проверки (возможного) файла /sys/devices/virtual/dmi/id/product_uuid.

Кто знал, что определить, работаете ли вы на EC2, может быть так сложно ?! Хорошо, теперь, когда у нас есть (большинство) проблем с перечисленными подходами, вот предлагаемый фрагмент bash, чтобы проверить, работаете ли вы на EC2. Я думаю, что это должно работать практически на любых экземплярах Linux, экземпляры Windows - это упражнение для читателя.

#!/bin/bash

# This first, simple check will work for many older instance types.
if [ -f /sys/hypervisor/uuid ]; then
  # File should be readable by non-root users.
  if [ `head -c 3 /sys/hypervisor/uuid` == "ec2" ]; then
    echo yes
  else
    echo no
  fi

# This check will work on newer m5/c5 instances, but only if you have root!
elif [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
  # If the file exists AND is readable by us, we can rely on it.
  if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "EC2" ]; then
    echo yes
  else
    echo no
  fi

else
  # Fallback check of http://169.254.169.254/. If we wanted to be REALLY
  # authoritative, we could follow Amazon's suggestions for cryptographically
  # verifying their signature, see here:
  #    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
  # but this is almost certainly overkill for this purpose (and the above
  # checks of "EC2" prefixes have a higher false positive potential, anyway).
  if $(curl -s -m 5 http://169.254.169.254/latest/dynamic/instance-identity/document | grep -q availabilityZone) ; then
    echo yes
  else
    echo no
  fi

fi

Очевидно, вы могли бы расширить это, добавив еще больше резервных проверок и включить паранойю по поводу обработки, например. ложное срабатывание от /sys/hypervisor/uuid происходит случайное начало с "ec2" и так далее. Но это достаточно хорошее решение для иллюстративных целей и, вероятно, почти для всех непатологических случаев использования.

[†] Получил это объяснение от службы поддержки AWS об изменении для экземпляров c5 / m5:

Экземпляры C5 и M5 используют новый стек гипервизора и связанные драйверы ядра не создают файлы в sysfs (который смонтирован в / sys) как драйверы Xen используемые другими / более старыми типами экземпляров. Лучший способ определить, работает ли операционная система на экземпляре EC2, - это учесть различные возможности, перечисленные в документация, которую вы связали.

Ищите метаданные по внутреннему доменному имени EC2 вместо IP, которое вернет быстрый отказ DNS, если вы не используете EC2, и позволит избежать конфликтов IP или проблем с маршрутизацией:

curl -s http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"

В некоторых дистрибутивах, на очень простых системах или на очень ранних стадиях установки завиток недоступно. С помощью wget вместо:

wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"

Если цель состоит в том, чтобы определить, является ли это экземпляр EC2 ИЛИ другой тип облачного экземпляра, например Google, тогда dmidecode работает очень хорошо и не требует подключения к сети. Мне нравится этот подход по сравнению с некоторыми другими подходами, потому что путь URL-адреса метаданных отличается для EC2 и GCE.

# From a google compute VM
$ sudo dmidecode -s bios-version
Google

# From an amazon ec2 VM
$ sudo dmidecode -s bios-version
4.2.amazon

Имена хостов могут измениться, запустите whois для вашего общедоступного IP-адреса:

if [[ ! -z $(whois $(curl -s shtuff.it/myip/short) | grep -i amazon) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi

или нажмите URL-адрес метаданных AWS

if [[ ! -z $(curl -s http://169.254.169.254/1.0/) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi

Это также хорошо работает для хостов Linux в ec2 и не требует сети и каких-либо связанных тайм-аутов:

grep -q amazon /sys/devices/virtual/dmi/id/bios_version

Это работает, потому что Amazon определяет эту запись так:

$ cat /sys/devices/virtual/dmi/id/bios_version 4.2.amazon

test -f /sys/hypervisor/uuid -a `head -c 3 /sys/hypervisor/uuid` == ec2 && echo yes

но я не знаю, насколько это переносимо в разных дистрибутивах.

Быстрый ответ:

if [[ -f /sys/devices/virtual/dmi/id/product_uuid ]] && \
    grep -q "^EC2" /sys/devices/virtual/dmi/id/product_uuid
then
    echo "IS EC2"
else
    echo "NOT EC2"
fi

Я использовал один из ответов, размещенных здесь, более года, но он не работает с новыми типами экземпляров c5 (сейчас я работаю над обновлением с c4).

Мне нравится это решение, потому что оно вряд ли сломается в будущем.

В старых типах экземпляров и в более новых этот файл присутствует и начинается с «EC2». Я проверил Ubuntu, работающий на VirtualBox (который мне также нужно поддерживать), и он содержит строку VirtualBox.

Как отмечалось на предыдущем плакате (но это было легко пропустить) - есть документация Amazon о том, как это сделать, - включая мой ответ.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html

На самом деле, есть очень простой способ определить, является ли хост экземпляром EC2: проверьте обратный поиск вашего общедоступного IP-адреса. Реверс EC2 довольно сложно не заметить.

Кроме того, если вы не меняли его, имя хоста должно быть вашим обратным, чтобы его было еще легче обнаружить.

Вы также можете использовать «волшебный IP-адрес», о котором вы говорили, поскольку это действительно стандартный способ получения тегов экземпляра EC2, однако, если вы не находитесь в сети EC2, вам придется подождать таймаута, который обычно не желательно ...

Если этих методов недостаточно, просто выполните whois для своего IP-адреса и проверьте, находитесь ли вы в блоке IP-адресов Amazon EC2.

РЕДАКТИРОВАТЬ: вы можете использовать этот небольшой бит оболочки:

#!/bin/bash
LOCAL_HOSTNAME=$(hostname -d)
if [[ ${LOCAL_HOSTNAME} =~ .*\.amazonaws\.com ]]
then
        echo "This is an EC2 instance"
else
        echo "This is not an EC2 instance, or a reverse-customized one"
fi

Однако будьте осторожны, [[это башизм. Вы также можете использовать Python или Perl uniline, YMMV.

Возможно, вы можете использовать «фактер»:

«Facter - это кроссплатформенная библиотека для получения простых сведений об операционной системе, таких как операционная система, дистрибутив Linux или MAC-адрес».

http://www.puppetlabs.com/puppet/related-projects/facter/

Например, если мы посмотрим на факт ec2 (facter-1.6.12 / lib / facter / ec2.rb):

require 'facter/util/ec2'
require 'open-uri'

def metadata(id = "")
  open("http://169.254.169.254/2008-02-01/meta-data/#{id||=''}").read.
    split("\n").each do |o|
    key = "#{id}#{o.gsub(/\=.*$/, '/')}"
    if key[-1..-1] != '/'
      value = open("http://169.254.169.254/2008-02-01/meta-data/#{key}").read.
        split("\n")
      symbol = "ec2_#{key.gsub(/\-|\//, '_')}".to_sym
      Facter.add(symbol) { setcode { value.join(',') } }
    else
      metadata(key)
    end
  end
end

def userdata()
  begin
    value = open("http://169.254.169.254/2008-02-01/user-data/").read.split
    Facter.add(:ec2_userdata) { setcode { value } }
  rescue OpenURI::HTTPError
  end
end

if (Facter::Util::EC2.has_euca_mac? || Facter::Util::EC2.has_openstack_mac? ||
    Facter::Util::EC2.has_ec2_arp?) && Facter::Util::EC2.can_connect?

  metadata
  userdata
else
  Facter.debug "Not an EC2 host"
end

Если у вас установлен curl, эта команда вернет 0, если вы работаете в EC2, и ненулевое значение, если это не так:

curl --max-time 3 http://169.254.169.254/latest/meta-data/ami-id 2>/dev/null 1>/dev/null`

Он пытается получить метаданные EC2, объявляющие AMI-ID. Если это не удается через 3 секунды, предполагается, что он не работает в EC2.

Немного поздно для этой вечеринки, однако я наткнулся на этот пост, а затем нашел эту документацию AWS:

Для окончательного и криптографически проверенного метода идентификации экземпляра EC2 проверьте документ, удостоверяющий личность экземпляра, включая его подпись. Эти документы доступны на каждом экземпляре EC2 по локальному немаршрутизируемому адресу. http://169.254.169.254/latest/dynamic/instance-identity/

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html

Это, конечно, требует дополнительных затрат на сеть, хотя вы можете установить тайм-аут curl следующим образом:

curl -s --connect-timeout 5 http://169.254.169.254/latest/dynamic/instance-identity/

Это устанавливает тайм-аут на 5 секунд.