Я хотел бы запустить несколько скриптов на хостах, которые являются экземплярами 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. Вот проблемы с текущими ответами:
hostname -d
, который используется для внутреннего DNS, а не для чего-либо, содержащего amazonaws.com.)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!dmidecode
from @tamale может работать, но зависит от вас a.) имея dmidecode
доступный на вашем экземпляре, и б.) имеющий root или sudo
возможность без пароля из вашего кода.bios_version
из 1.0
. Этот файл вообще не документирован в документе Amazon, поэтому я бы не стал на это полагаться.whois
по результату проблематично на нескольких уровнях. Обратите внимание, что URL, предложенный в этом ответе, прямо сейчас является страницей 404! Даже если бы вы нашли работающую стороннюю службу, она была бы сравнительно очень медленно (по сравнению с локальной проверкой файла) и, возможно, столкнется с проблемами ограничения скорости или проблемами сети, или, возможно, ваш экземпляр EC2 даже не имеет внешнего доступа к сети.-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 секунд.