如何知道一台机器是否是 EC2 实例

如何知道一台机器是否是 EC2 实例

我想在 EC2 实例主机上运行一些脚本,但我不知道如何确保主机真的EC2 实例。

我已经做了一些测试,但这还不够:

  • 测试二进制 ec2_userdata 是否可用(但这并不总是正确的)
  • 测试“的可用性http://169.254.169.254/latest/meta-data“(但这总是正确的吗?这个“神奇的 IP” 又是什么?)

答案1

首先,我觉得有必要发布一个新的答案,因为现有答案存在以下细微问题,并且在收到有关我的评论@qwertzguy 的回答。目前答案存在以下问题:

  1. 接受的答案@MatthieuCerda 的答案肯定不可靠,至少在我检查过的任何 VPC 实例上都不是。(在我的实例上,我获得了一个 VPC 名称hostname -d,用于内部 DNS,而不是任何带有“amazonaws.com”的东西。)
  2. 得票最高的答案来自@qwertzguy不适用于新的 m5 或 c5 实例,没有这个文件。据我所知,亚马逊忽略了记录这种行为变化,尽管文档页面关于这个问题确实说过“......如果/sys/hypervisor/uuid 存在...”。我询问 AWS 支持,这种更改是否是故意的,见下文†。
  3. 来自@Jer 的回答不一定在所有地方都有效,因为instance-data.ec2.internalDNS 查找可能不起作用。在我刚刚测试过的 Ubuntu EC2 VPC 实例上,我看到: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal 这会导致依赖此方法的代码错误地得出结论,它不在 EC2 上!
  4. 回答使用dmidecode来自@tamale 可能会起作用,但依赖于 a.)dmidecode在您的实例上可用,以及 b.)sudo在您的代码中具有 root 或无密码能力。
  5. 回答检查 /sys/devices/virtual/dmi/id/bios_version@spkane 的警告具有误导性!我检查了一个 Ubuntu 14.04 m5 实例,得到了bios_version1.0该文件根本没有记录在亚马逊的文档中,所以我确实不会依赖它。
  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 实例使用新的虚拟机管理程序堆栈并且相关内核驱动程序不会像 Xen 驱动程序那样在 sysfs(挂载在 /sys)中创建文件其他/较旧的实例类型所使用的。检测操作系统是否在 EC2 实例上运行的最佳方法是考虑您链接的文档

答案2

更改了 Hannes 的答案以避免出现错误消息并在脚本中包含示例用法:

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

这在 Windows 实例中不起作用。与 curl 相比,它的优势在于它在 EC2 和非 EC2 上都接近即时。

更新:对于新的 C5/M5 实例,请使用文件/sys/devices/virtual/dmi/id/product_uuid代替并检查EC2 而不是ec2。(感谢评论中的 Josh 和 Saumitra 提到这一点)

答案3

如果目标是判断它是 EC2 实例还是另一种云实例(如谷歌),那么这种方法dmidecode非常有效,而且不需要联网。与其他一些方法相比,我喜欢这种方法,因为 EC2 和 GCE 的元数据 URL 路径不同。

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

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

答案4

主机名可能会改变,请针对你的公共 IP 运行 whois:

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

或者点击 AWS 元数据 URL

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

相关内容