EDIT and 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 /
Explanation:
I would like to know in advance which block device a particular AWS instance is supposed to have post-attachment.
Unfortunately, the instance metadata endpoint for block devices introduced back in 2007 does not seem to work reliably anymore?
Here's an example t2.medium
instance I'm running with latest Ubuntu (17.10) AMI at the time of writing this (not Amazon Linux):
Not only the EBS modules show up in the console, but seem to be properly attached:
According to the official AWS docs on block-device-mappings:
block-device-mapping/ebsN
: The virtual devices associated with Amazon EBS volumes, if any are present. Amazon EBS volumes are only available in metadata if they were present at launch time or when the instance was last started. The N indicates the index of the Amazon EBS volume (such as ebs1 or ebs2).2007-12-15
But unfortunately there are no such endpoints present after the instance is fully up and running and all EBS volumes are attached:
$ 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>
On the other hand, the operating system (under XEN device scheme), exposes the volumes via xvdXX
devices:
$ ls /dev/xvd*
/dev/xvda /dev/xvda1 /dev/xvdf /dev/xvdg
So this leaves me with a poor solution of just assuming which block device is going to be depending on which instance I'm running, which predictably breaks once, for instance, Amazon introduces new iron with completely different underlying block device naming schemes such as /dev/nvme0n1p1
:
https://twitter.com/braincode/status/968005482102190080
Here's what happens on freshly instantiated M5 instance with an EBS volume attached:
$ 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
ebs2
listed and not ebs1
?sdf
?There's not a single sd*
on m5 instance's operating system:
$ ls /dev/sd*
ls: cannot access '/dev/sd*': No such file or directory
What am I doing wrong? Is this a known bug? How do people/boto/cloudinit modules handle that?
To view instance metadata, you can only use the link-local address of 169.254. 169.254 to access. Requests to the metadata via the URI are free, so there are no additional charges from AWS. Using the curl tool on Linux or the PowerShell cmdlet Invoke-WebRequest on Windows, you will first create your token.
Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/ . In the navigation pane, choose Instances. Select the instance. On the Storage tab, the Block devices section lists the volumes that are attached to the instance.
Instance metadata is data about your instance that you can use to configure or manage the running instance. Instance metadata is divided into categories, for example, host name, events, and security groups. You can also use instance metadata to access user data that you specified when launching your instance.
Getting and tagging the EBS RootVolume from running EC2instance: this is how you can achieve it:
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)
if you want to set a RootVolume Tag (which isn't supported by CloudFormation yet (2019-03-14)):
aws ec2 create-tags --resources ${RootVolumeId} --tags Key=Name,Value=RootVolume-${Instance_Name}
You need the following IAM Permissions for that:
"ec2:DescribeInstances"
"ec2:CreateTags"
This is how it works:
just look at the (shortened) ec2 json response:
aws ec2 describe-instances --instance-ids ${Instance_ID}
{
"Reservations": [
{
"Instances": [
{
"InstanceId": "i-XXXXX",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"Status": "attached",
"DeleteOnTermination": true,
"VolumeId": "vol-XXXXX",
"AttachTime": "2019-02-27T07:56:07.000Z"
}
},
{
"DeviceName": "/dev/sdm",
"Ebs": {
"Status": "attached",
"DeleteOnTermination": false,
"VolumeId": "vol-XXXXX",
"AttachTime": "2019-02-27T07:58:02.000Z"
}
}
],
"RootDeviceType": "ebs",
"RootDeviceName": "/dev/xvda",
}
],
"ReservationId": "r-XXXXX",
"RequesterId": "XXXXX",
"Groups": [],
"OwnerId": "XXXXX"
}
]
}
As you can see: every instance has BlockDeviceMappings and a RootDeviceName property.
1) You can select the current as DeviceName as Value from RootDeviceName property.
2) With that information you can parse your BlockDeviceMappings by matching your selected DeviceName and finally get the VolumeID.
Thats it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With