web-dev-qa-db-fra.com

Comment savoir si une machine est une instance EC2

Je voudrais exécuter des scripts sur des hôtes qui sont des instances EC2 mais je ne sais pas comment être sûr que l'hôte est vraiment une instance EC2.

J'ai fait quelques tests, mais ce n'est pas suffisant:

  • Testez que binaire ec2_userdata est disponible (mais ce ne sera pas toujours vrai)
  • Testez la disponibilité de " http://169.254.169.254/latest/meta-data " (mais cela sera-t-il toujours vrai? Et quelle est cette "IP magique"?)
46
Kelindil

Eh bien, en fait, il existe un moyen très simple de détecter si l'hôte est une instance EC2: vérifiez la recherche inversée de votre adresse IP publique. Les revers EC2 sont assez difficiles à manquer.

De plus, si vous ne l'avez pas modifié, le nom d'hôte devrait être votre inverse, ce qui le rend encore plus facile à repérer.

Vous pouvez également utiliser l '"IP magique" dont vous avez parlé, car c'est en effet la manière standard d'obtenir des balises d'instance EC2, cependant, si vous n'êtes pas sur un réseau EC2, vous devrez attendre un délai d'attente, ce qui n'est généralement pas le cas. souhaitable...

Si ces méthodes ne suffisent pas, faites simplement un whois de votre IP et vérifiez si vous êtes à l'intérieur et le bloc IP Amazon EC2.

EDIT: Vous pouvez utiliser ce petit bit Shell:

#!/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

Attention cependant, [[est un bashisme. Vous pouvez également utiliser un Python ou Perl uniline, YMMV.

3
Matthieu Cerda

Changement de la réponse de Hannes pour éviter les messages d'erreur et inclure un exemple d'utilisation dans le script:

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

Cela ne fonctionne pas dans les instances Windows. L'avantage par rapport à la boucle est qu'elle est presque instantanée sur EC2 et non EC2.

pdate: Pour les nouvelles instances C5/M5, utilisez le fichier /sys/devices/virtual/dmi/id/product_uuid à la place et vérifiez EC2 au lieu de ec2. (Merci à Josh et Saumitra dans les commentaires pour avoir mentionné cela)

44
qwertzguy

Tout d'abord, j'ai ressenti le besoin de poster une nouvelle réponse en raison des problèmes subtils suivants avec les réponses existantes, et après avoir reçu une question sur mon commentaire sur la réponse de @ qwertzguy . Voici les problèmes avec les réponses actuelles:

  1. Le réponse acceptée de @MatthieuCerda ne fonctionne certainement pas de manière fiable, du moins pas sur les instances VPC sur lesquelles j'ai vérifié. (Sur mes instances, j'obtiens un nom de VPC pour hostname -d, Qui est utilisé pour le DNS interne, rien avec "amazonaws.com" dedans.)
  2. La réponse la plus votée de @qwertzguy ne fonctionne pas sur les nouvelles instances m5 ou c5 , qui n'ont pas ce fichier. Amazon néglige de documenter ce changement de comportement AFAIK, bien que le page doc sur ce sujet indique "... If /sys/hyperviseur/uuid existe ... ". J'ai demandé au support AWS si ce changement était intentionnel, voir ci-dessous †.
  3. La réponse de @Jer ne fonctionne pas nécessairement partout car la recherche DNS instance-data.ec2.internal Peut ne pas fonctionner. Sur une instance Ubuntu EC2 VPC sur laquelle je viens de tester, je vois: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve Host: instance-data.ec2.internal ce qui ferait que le code s'appuyant sur cette méthode conclurait à tort qu'il n'est pas sur EC2!
  4. La réponse à utiliser dmidecode de @tamale peut fonctionner, mais dépend de vous a.) Ayant dmidecode disponible sur votre instance, et b.) Ayant root ou Sudo capacité sans mot de passe à partir de votre code.
  5. La réponse à vérifier/sys/devices/virtual/dmi/id/bios_version de @spkane est dangereusement trompeuse! J'ai vérifié une instance d'Ubuntu 14.04 m5 et obtenu un bios_version De 1.0. Ce fichier n'est pas du tout documenté sur le document d'Amazon , donc je ne m'y fierais vraiment pas.
  6. La première partie du réponse de @ Chris-Montanaro pour vérifier une URL tierce non fiable et utiliser whois sur le résultat est problématique à plusieurs niveaux. Notez que l'URL suggérée dans cette réponse est une page 404 en ce moment! Même si vous avez trouvé un service tiers qui a fonctionné, il serait relativement très lent (par rapport à la vérification locale d'un fichier) et éventuellement des problèmes de limitation de débit ou des problèmes de réseau, ou peut-être que votre instance EC2 n'a même pas accès au réseau extérieur.
  7. La deuxième suggestion dans le réponse de @ Chris-Montanaro à vérifier http://169.254.169.254/ est un peu mieux, mais un autre commentateur note que d'autres fournisseurs de cloud font cela URL de métadonnées d'instance disponibles, vous devez donc faire attention à éviter les faux positifs. De plus, il sera toujours beaucoup plus lent qu'un fichier local, j'ai vu cette vérification être particulièrement lente (plusieurs secondes pour revenir) sur les instances lourdement chargées. En outre, vous devez vous rappeler de passer un argument -m Ou --max-time Pour boucler pour éviter qu'il ne se bloque pendant très longtemps, en particulier sur une instance non EC2 où cette adresse peut conduire à nulle part et se bloquer (comme dans @ réponse algal ).

De plus, je ne vois pas que quelqu'un ait mentionné documenté par Amazon repli de la vérification du fichier (possible) /sys/devices/virtual/dmi/id/product_uuid.

Qui savait que déterminer si vous utilisez EC2 pouvait être si compliqué?! OK, maintenant que nous avons (la plupart) des problèmes avec les approches répertoriées, voici un extrait de bash suggéré pour vérifier si vous exécutez sur EC2. Je pense que cela devrait fonctionner généralement sur presque toutes les instances Linux, les instances Windows sont un exercice pour le lecteur.

#!/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

De toute évidence, vous pouvez étendre cela avec encore plus de contrôles de secours, et inclure la paranoïa sur la gestion, par exemple. un faux positif de /sys/hypervisor/uuid se produisant pour commencer par "ec2" par hasard et ainsi de suite. Mais c'est une bonne solution à des fins d'illustration et probablement presque tous les cas d'utilisation non pathologiques.

[†] Récupéré cette explication du support AWS concernant la modification des instances c5/m5:

Les instances C5 et M5 utilisent un nouvelle pile d'hyperviseur et les pilotes de noyau associés ne créent pas de fichiers dans sysfs (qui est monté sur/sys) comme les pilotes Xen tilisés par l'autre/ancien) les types d'instances le font . La meilleure façon de détecter si le système d'exploitation s'exécute sur une instance EC2 est de prendre en compte les différentes possibilités répertoriées dans la documentation que vous avez liée .

26
Josh Kupershmidt

Recherchez les métadonnées par le nom de domaine interne EC2 au lieu d'IP, ce qui retournera un échec DNS rapide si vous n'êtes pas sur EC2, et évite les conflits IP ou les problèmes de routage:

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

Sur certaines distributions, les systèmes très basiques ou très tôt aux étapes d'installation curl n'est pas disponible. En utilisant wget à la place:

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

Si le but est de dire s'il s'agit d'une instance EC2 OR un autre type d'instance cloud, comme google, alors dmidecode fonctionne très bien et aucun réseau n'est requis. J'aime ça vs certaines des autres approches, car le chemin de l'URL des métadonnées est différent pour EC2 et 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
14
tamale

Les noms d'hôtes sont susceptibles de changer, exécutez un whois contre votre IP publique:

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

ou appuyez sur l'URL des métadonnées AWS

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

Cela fonctionne également bien pour les hôtes Linux dans ec2 et ne nécessite pas le réseau et les délais d'attente associés:

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

Cela fonctionne, car Amazon définit cette entrée comme suit:

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

5
spkane

Réponse rapide:

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

J'utilisais l'une des réponses publiées ici depuis plus d'un an - mais cela ne fonctionne pas sur les nouveaux types d'instances "c5" (je travaille actuellement sur la mise à niveau à partir de "c4").

J'aime cette solution car elle semble la moins susceptible de se casser à l'avenir.

Sur les types d'instances plus anciens et les plus récents, ce fichier est présent et commence par "EC2". J'ai vérifié sur Ubuntu fonctionnant sur VirtualBox (que je dois également prendre en charge) et il contient la chaîne "VirtualBox".

Comme l'a noté une affiche précédente (mais c'était facile à manquer) - il existe une documentation Amazon sur les façons de le faire - qui comprend ma réponse.

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

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

mais je ne sais pas comment c'est portable à travers les distributions.

3
Hannes

Vous pouvez peut-être utiliser "facter":

"Facter est une bibliothèque multiplateforme permettant de récupérer des faits simples sur le système d'exploitation, comme le système d'exploitation, la distribution Linux ou l'adresse MAC."

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

Par exemple, si nous regardons le fait 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
2
jmprusi

Si vous avez installé curl, cette commande retournera 0 si vous exécutez dans EC2 et non nulle si vous n'êtes pas:

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

Il essaie d'extraire les métadonnées EC2 déclarant l'AMI-ID. Si cela ne réussit pas après 3 secondes, il suppose qu'il ne fonctionne pas dans EC2.

1
algal

Un peu tard pour cette fête, cependant je suis tombé sur ce post et j'ai trouvé cette documentation AWS:

Pour une méthode définitive et cryptographiquement vérifiée d'identification d'une instance EC2, vérifiez le document d'identité d'instance, y compris sa signature. Ces documents sont disponibles sur chaque instance EC2 à l'adresse locale non routable http://169.254.169.254/latest/dynamic/instance-identity/

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

Bien sûr, cela nécessite la surcharge du réseau, bien que vous puissiez définir le délai d'expiration de la boucle comme suit:

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

Cela définit le délai d'attente à 5 secondes.

0
Brooks