从实例元数据端点检索正确的Amazon连接的EBS设备

bra*_*orm 5 amazon-ec2 amazon-web-services block-device

编辑和TL; DR:

ubuntu@ip-172-31-19-77:~/.aws$ aws ec2 describe-instances | jq . | grep -i device
          "BlockDeviceMappings": [],
          "RootDeviceType": "ebs",
          "RootDeviceName": "/dev/sda1",
                "DeviceIndex": 0,
          "BlockDeviceMappings": [
              "DeviceName": "/dev/sda1",
              "DeviceName": "/dev/xvdb",
          "RootDeviceType": "ebs",
          "RootDeviceName": "/dev/sda1",
                "DeviceIndex": 0,
          "BlockDeviceMappings": [
              "DeviceName": "/dev/sda1",
          "RootDeviceType": "ebs",
          "RootDeviceName": "/dev/sda1",
                "DeviceIndex": 0,
          "BlockDeviceMappings": [
              "DeviceName": "/dev/xvda",
          "RootDeviceType": "ebs",
          "RootDeviceName": "/dev/xvda",
                "DeviceIndex": 0,
          "BlockDeviceMappings": [
              "DeviceName": "/dev/sda1",
              "DeviceName": "/dev/sdf",
          "RootDeviceType": "ebs",
          "RootDeviceName": "/dev/sda1",
ubuntu@ip-172-31-19-77:~/.aws$ aws ec2 describe-volumes | jq . | grep -i device
          "Device": "/dev/sda1"
          "Device": "/dev/sdf"
          "Device": "/dev/xvda"
          "Device": "/dev/sda1"
          "Device": "/dev/xvdb"
          "Device": "/dev/sda1"
ubuntu@ip-172-31-19-77:~/.aws$ ls /dev/sd*
ls: cannot access '/dev/sd*': No such file or directory
ubuntu@ip-172-31-19-77:~/.aws$ ls /dev/xv*
ls: cannot access '/dev/xv*': No such file or directory
ubuntu@ip-172-31-19-77:~/.aws$ lsblk
NAME        MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1     259:0    0   1G  0 disk
nvme1n1     259:1    0   8G  0 disk
??nvme1n1p1 259:2    0   8G  0 part /
Run Code Online (Sandbox Code Playgroud)

说明:

我想提前知道特定的AWS实例应该在哪个块设备上进行附加。

不幸的是,早在2007年引入的块设备的实例元数据端点似乎不再可靠运行?

这是一个示例示例,在撰写本文时,t2.medium我正在使用最新的Ubuntu(17.10)AMI不是Amazon Linux)运行:

在此处输入图片说明

不仅EBS模块显示在控制台中,而且似乎已正确连接:

在此处输入图片说明

根据有关块设备映射的官方AWS文档

block-device-mapping/ebsN:与Amazon EBS卷关联的虚拟设备(如果有)。如果Amazon EBS卷在启动时或上次启动实例时存在,则仅在元数据中可用。N表示Amazon EBS卷的索引(例如ebs1或ebs2)。2007-12-15

但是不幸的是,在实例完全启动并运行并且所有EBS卷都已附加之后,没有这样的端点:

$ curl http://169.254.169.254/latest/meta-data/block-device-mapping/
ami
ephemeral0
ephemeral1
$ curl http://169.254.169.254/latest/meta-data/block-device-mapping/ami
/dev/sda1
$ curl http://169.254.169.254/latest/meta-data/block-device-mapping/ebs1
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>404 - Not Found</title>
 </head>
 <body>
  <h1>404 - Not Found</h1>
 </body>
</html>
$ curl http://169.254.169.254/latest/meta-data/block-device-mapping/ebs2
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>404 - Not Found</title>
 </head>
 <body>
  <h1>404 - Not Found</h1>
 </body>
</html>
Run Code Online (Sandbox Code Playgroud)

另一方面,操作系统(在XEN设备方案下)通过xvdXX设备公开卷:

$ ls /dev/xvd*
/dev/xvda  /dev/xvda1  /dev/xvdf  /dev/xvdg
Run Code Online (Sandbox Code Playgroud)

因此,这给我留下了一个糟糕的解决方案,即仅假设哪个块设备将取决于我正在运行的实例,而该实例一次就会中断,例如,Amazon引入了具有完全不同的底层块设备命名方案的新熨斗,例如/dev/nvme0n1p1

https://twitter.com/braincode/status/968005482102190080

这是在附加了EBS卷的新实例化的M5实例上发生的事情:

$ curl http://169.254.169.254/latest/meta-data/block-device-mapping/
ami
ebs2
root

$ curl http://169.254.169.254/latest/meta-data/block-device-mapping/ebs2
sdf
Run Code Online (Sandbox Code Playgroud)
  1. 为什么只ebs2列出而没有列出ebs1
  2. sdf

sd*m5实例的操作系统上没有一个:

$ ls /dev/sd*
ls: cannot access '/dev/sd*': No such file or directory
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?这是一个已知的错误?people / boto / cloudinit模块如何处理?

men*_*ann 5

通过运行 EC2instance获取和标记 EBS RootVolume:这是您实现它的方法:

Instance_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
Instance_Name=$(aws ec2 describe-instances --instance-ids ${Instance_ID} --query 'Reservations[0].Instances[0].Tags[?Key==`Name`].Value' --output text)
RootDeviceName=$(aws ec2 describe-instances --instance-ids ${Instance_ID} --query 'Reservations[0].Instances[0].RootDeviceName' --output text)
RootVolumeId=$(aws ec2 describe-instances --instance-ids ${Instance_ID} --query "Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==\`${RootDeviceName}\`].Ebs.VolumeId" --output text)
Run Code Online (Sandbox Code Playgroud)

如果要设置 RootVolume 标签(CloudFormation 尚不支持(2019-03-14)):

aws ec2 create-tags --resources ${RootVolumeId} --tags Key=Name,Value=RootVolume-${Instance_Name}
Run Code Online (Sandbox Code Playgroud)

为此,您需要以下 IAM 权限:

"ec2:DescribeInstances"
"ec2:CreateTags"
Run Code Online (Sandbox Code Playgroud)

这是它的工作原理:

看看(缩短的)ec2 json 响应:

Instance_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
Instance_Name=$(aws ec2 describe-instances --instance-ids ${Instance_ID} --query 'Reservations[0].Instances[0].Tags[?Key==`Name`].Value' --output text)
RootDeviceName=$(aws ec2 describe-instances --instance-ids ${Instance_ID} --query 'Reservations[0].Instances[0].RootDeviceName' --output text)
RootVolumeId=$(aws ec2 describe-instances --instance-ids ${Instance_ID} --query "Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==\`${RootDeviceName}\`].Ebs.VolumeId" --output text)
Run Code Online (Sandbox Code Playgroud)
aws ec2 create-tags --resources ${RootVolumeId} --tags Key=Name,Value=RootVolume-${Instance_Name}
Run Code Online (Sandbox Code Playgroud)

如您所见:每个实例都有 BlockDeviceMappings 和 RootDeviceName 属性。
1) 您可以从RootDeviceName属性中选择当前作为DeviceName作为值。 2) 有了这些信息,您可以通过匹配您选择的DeviceName来解析您的BlockDeviceMappings并最终获得VolumeID

就是这样。


Jef*_*unk 4

元数据服务显示实例启动时的块储存设备映射,并且是不可变的。您可以相信根设备和任何实例存储卷的值在实例的生命周期内都是准确的。NVMe 块设备不需要映射。/dev/xvd* 下的任何其他块设备当前都将附加 EBS 卷。

如果您需要知道每个设备文件对应哪个卷,唯一准确的方法是使用过滤器调用ec2.DescribeVolumesattachment.instance-id。您的实例将需要适当的实例配置文件才能进行该调用。您还需要小心不要过于频繁地调用它,并通过指数退避和抖动来实现重试以处理限制。

  • 不,你不能相信他们。在 m5 实例中,具有设备名称为“nvme0n1”的附加 EBS 卷,元数据端点将其显示为“sdf”,我将更新问题以反映来自 AWS 的此损坏。 (2认同)