Como saber se uma máquina é uma instância do EC2

39

Eu gostaria de executar alguns scripts em hosts que são instâncias do EC2, mas não sei como ter certeza de que o host é realmente uma instância do EC2.

Eu fiz alguns testes, mas isso não é suficiente:

  • Teste que o binário ec2_userdata está disponível (mas isso nem sempre será verdade)
  • Teste a disponibilidade de " link " (mas isso será sempre verdade? e o que é esse "IP mágico"? )
por Kelindil 04.01.2013 / 10:12

10 respostas

3

Bem, na verdade, existe uma maneira muito simples de detectar se o host é uma instância do EC2: verifique a pesquisa inversa do seu IP público. Os reversos do EC2 são muito difíceis de perder.

Além disso, se você não modificá-lo, o nome do host deve ser o seu reverso, facilitando ainda mais sua identificação.

Você também pode usar o "IP mágico" de que falou, já que é a maneira padrão de obter tags de Instância do EC2, no entanto, se você não estiver em uma rede EC2, terá que esperar por um tempo limite, geralmente não é desejável ...

Se esses métodos não forem suficientes, basta fazer um whois do seu IP e verificar se você está dentro e no bloco de IP do Amazon EC2.

EDIT: Você pode usar este pequeno bit de 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

Cuidado, porém, [[é um bashismo. Você também pode usar um Python ou Perl uniline, YMMV.

    
por 04.01.2013 / 10:20
37

Alterou a resposta de Hannes para evitar mensagens de erro e incluiu o uso de exemplo no script:

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

Isso não funciona em instâncias do Windows. A vantagem sobre o enrolar é que ele é quase instantâneo tanto no EC2 quanto no não-EC2.

    
por 22.06.2015 / 20:36
16

Procure os metadados pelo nome de domínio interno do EC2 em vez de IP, que retornará uma falha rápida de DNS se você não estiver no EC2 e evita conflitos de IP ou problemas de roteamento:

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

Em algumas distros, sistemas muito básicos, ou muito cedo nos estágios curl não estão disponíveis. Usando wget em vez disso:

wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"
    
por 13.02.2014 / 19:41
15

Se o objetivo for informar se é uma instância do EC2 OU outro tipo de instância da nuvem, como o google, então dmidecode funciona muito bem e não é necessária nenhuma rede. Eu gosto disso contra algumas das outras abordagens porque o caminho do URL de metadados é diferente para EC2 e 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
    
por 05.05.2016 / 18:02
11

Primeiro, senti a necessidade de postar uma nova resposta por causa dos seguintes problemas sutis com as respostas existentes, e depois de receber uma pergunta sobre o meu comente na resposta do @qwertzguy . Aqui estão os problemas com as respostas atuais:

  1. A resposta aceita do @MatthieuCerda definitivamente não funciona de maneira confiável, pelo menos em instâncias de VPC que eu verifiquei. (Nas minhas instâncias, recebo um nome de VPC para hostname -d , que é usado para DNS interno, e não qualquer coisa com "amazonaws.com".)
  2. A resposta mais votada de @qwertzguy não funciona em novas instâncias m5 ou c5 , que não possuem este arquivo. A Amazon deixa de documentar essa mudança de comportamento AFAIK, embora a página do documento sobre esse assunto diga "... Se / sys / hypervisor / uuid existir ...". Perguntei ao suporte da AWS se essa mudança era intencional, veja abaixo †.
  3. A resposta de @Jer não funciona necessariamente em todos os lugares porque a pesquisa instance-data.ec2.internal DNS pode não funcionar. Em uma instância do Ubuntu EC2 VPC que acabei de testar, vejo: %código% o que faria com que o código baseado neste método concluísse falsamente que não está no EC2!
  4. A resposta para usar $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal do @tamale pode funcionar, mas depende de você a.) ter dmidecode disponível em sua instância eb) com capacidade root ou dmidecode password-less de dentro de seu código.
  5. A resposta para verificar / sys / devices / virtual / dmi / id / bios_version de @spkane é perigosamente enganosa! Eu verifiquei uma instância do Ubuntu 14.04 m5 e obtive um sudo de bios_version . Este arquivo não está documentado em todos os no documento da Amazon , então eu realmente não confiaria isso.
  6. A primeira parte da resposta de @ Chris-Montanaro para verificar um URL de terceiros não confiável e usar 1.0 no resultado é problemático em vários níveis. Observe que o URL sugerido nessa resposta é uma página 404 agora mesmo! Mesmo que você tenha encontrado um serviço de terceiros que funcionasse, ele seria comparativamente muito lento (em comparação à verificação de um arquivo localmente) e possivelmente teria problemas de limitação de taxa ou problemas de rede ou possivelmente A instância do EC2 nem sequer tem acesso à rede externa.
  7. A segunda sugestão na resposta de @ Chris-Montanaro para verificar é um pouco melhor, mas outro comentarista observa que outros provedores de nuvem disponibilizam esse URL de metadados de instância, portanto, é necessário ter cuidado para evitar falsos positivos. Além disso, ainda será muito mais lento do que um arquivo local. Eu vi essa verificação ser especialmente lenta (alguns segundos para retornar) em instâncias altamente carregadas. Além disso, lembre-se de passar um argumento whois ou -m para enrolar para evitar que fique pendurado por um tempo muito longo, especialmente em uma instância não-EC2 em que esse endereço pode levar a lugar nenhum e travar (como em @ resposta do algal ).

Além disso, não vejo que alguém tenha mencionado o registro documentado da Amazon verificando o (possível) arquivo --max-time .

Quem sabia que determinar se você está usando o EC2 pode ser tão complicado ?! OK, agora que temos (a maioria) dos problemas com as abordagens listadas listadas, aqui está um snippet bash sugerido para verificar se você está executando no EC2. Eu acho que isso deve funcionar geralmente em quase todas as instâncias do Linux, as instâncias do Windows são um exercício para o leitor.

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

Obviamente, você poderia expandir isso com ainda mais verificações de fallback e incluir paranoia sobre como manipular, e. um falso positivo de /sys/devices/virtual/dmi/id/product_uuid acontecendo para começar com "ec2" por acaso e assim por diante. Mas esta é uma solução suficientemente boa para fins de ilustração e, provavelmente, quase todos os casos de uso não patológicos.

[†] Recebemos de volta esta explicação do suporte da AWS sobre a alteração das instâncias c5 / m5:

The C5 and M5 instances use a new hypervisor stack and the associated kernel drivers do not create files in sysfs (which is mounted at /sys) as the Xen drivers used by the other/older instance types do. The best way to detect whether the operating system is running on an EC2 instance is to account for the different possibilities listed in the documentation you linked.

    
por 20.03.2018 / 15:46
5

Os nomes de host provavelmente mudam, execute um whois em seu IP público:

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 pressione o URL de metadados da AWS

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

Isso também funciona bem para hosts Linux em ec2 e não requer a rede e nenhum tempo limite relacionado:

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

Isso funciona, porque a Amazon define essa entrada da seguinte forma:

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

    
por 10.02.2017 / 20:04
3
test -f /sys/hypervisor/uuid -a 'head -c 3 /sys/hypervisor/uuid' == ec2 && echo yes

mas não sei quão portátil isso é nas distribuições.

    
por 04.06.2015 / 05:18
2

Talvez você possa usar "facter":

"O Facter é uma biblioteca multi-plataforma para recuperar fatos simples do sistema operacional, como sistema operacional, distribuição do Linux ou endereço MAC."

link

Por exemplo, se dermos uma olhada no fato do 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
    
por 04.01.2013 / 17:06
1

Se você tiver o curl instalado, este comando retornará 0 se você estiver executando no EC2 e diferente de zero se não estiver:

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

Ele tenta extrair os metadados do EC2 que declaram o ID da AMI. Se isso não ocorrer após 3 segundos, ele pressupõe que não está sendo executado no EC2.

    
por 18.05.2017 / 21:11