Skip to content

Instantly share code, notes, and snippets.

@davidalger
Created April 15, 2020 20:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidalger/f0eed5e369276584df0c7dfdec1ce09b to your computer and use it in GitHub Desktop.
Save davidalger/f0eed5e369276584df0c7dfdec1ce09b to your computer and use it in GitHub Desktop.
Automatically format and mount both EBS Volume devices and Amazon EC2 NVMe Instance Storage devices (ephemeral local storage) via cloud-init on Nitro instances running CentOS 7
#cloud-config
packages:
- epel-release # required for jq installation to succeed
write_files:
- path: /usr/local/bin/mount-scratch-disks
owner: root:root
permissions: '0700'
content: |
#!/bin/bash
set -euo pipefail
if ! which nvme 1>2 2>/dev/null || ! which jq 1>2 2>/dev/null; then
yum install -y nvme-cli jq
fi
# List and extract the DevicePath for each "Amazon EC2 NVMe Instance Storage" device (ephemeral local storage)
device_list=$(
nvme list -o json | jq -r '.Devices[] | select(.ModelNumber | test("instance storage"; "i")) | .DevicePath'
)
# The following loop assumes that all ephemeral devices will either require formatting or not; should one be
# already formatted, the loop will likely encounter an error due to the sequential index used to label them
device_index=0
for device_path in $device_list; do
if [[ ! $(lsblk -nfo uuid $device_path) ]]; then
device_label=$(printf "scratch%02d" $device_index)
echo "[$(basename $0)] Formatting $device_path with LABEL=$device_label"
mkfs -t ext4 -L $device_label $device_path
((device_index+=1)) # Increment index for next iteration
else
device_label=$(lsblk -nfo label $device_path)
echo "[$(basename $0)] Device $device_path already formatted with LABEL=$device_label"
fi
if ! grep -qs /$device_label /proc/mounts; then
echo "[$(basename $0)] Mounting $device_path at /$device_label"
mkdir -p /$device_label
mount -o rw,noatime,nobarrier $device_path /$device_label
else
echo "[$(basename $0)] Mount /$device_label already exists:"
echo "[$(basename $0)] $(grep -s /$device_label /proc/mounts)"
fi
done
# The ${ebs_volume_id} placeholder here is replaced by Terraform when rendering the
# template. Since however volume ids contain a hyphen that is excluded from the alias
# created for the EBS device, the 'vol' prefix is specified here with the latter half
# passed in using the following expression: split("-", aws_ebs_volume.default.id)[1]
fs_setup:
- label: data00
filesystem: ext4
device: /dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_vol${ebs_volume_id}
overwrite: false
mounts:
- [ "LABEL=data00", "/data00" ]
# This will run following reboot or stop/start operation, but will do nothing on the
# initial configuration cycle as write_files follows bootcmd during the init phase.
bootcmd:
- test -x /usr/local/bin/mount-scratch-disks && /usr/local/bin/mount-scratch-disks
# This will run only during the initial configuration sequence following the script
# having been written to disk by the write_files declaration.
runcmd:
- test -x /usr/local/bin/mount-scratch-disks && /usr/local/bin/mount-scratch-disks
@davidalger
Copy link
Author

Example of the output nvme list -o json will print out on an m5ad.4xlarge EC2 instance having one additional EBS volume attached:

{
  "Devices": [
    {
      "DevicePath": "/dev/nvme0n1",
      "Firmware": "1.0",
      "Index": 0,
      "ModelNumber": "Amazon Elastic Block Store",
      "ProductName": "Non-Volatile memory controller: Amazon.com, Inc. Device 0x8061",
      "SerialNumber": "vol0d51c43f7fc495e96",
      "UsedBytes": 0,
      "MaximumLBA": 16777216,
      "PhysicalSize": 8589934592,
      "SectorSize": 512
    },
    {
      "DevicePath": "/dev/nvme1n1",
      "Firmware": "0",
      "Index": 1,
      "ModelNumber": "Amazon EC2 NVMe Instance Storage",
      "ProductName": "Unknown device",
      "SerialNumber": "AWS1E5D8D368228D9C34",
      "UsedBytes": 300000000000,
      "MaximumLBA": 585937500,
      "PhysicalSize": 300000000000,
      "SectorSize": 512
    },
    {
      "DevicePath": "/dev/nvme2n1",
      "Firmware": "0",
      "Index": 2,
      "ModelNumber": "Amazon EC2 NVMe Instance Storage",
      "ProductName": "Unknown device",
      "SerialNumber": "AWS19F542E256CE22982",
      "UsedBytes": 300000000000,
      "MaximumLBA": 585937500,
      "PhysicalSize": 300000000000,
      "SectorSize": 512
    },
    {
      "DevicePath": "/dev/nvme3n1",
      "Firmware": "1.0",
      "Index": 3,
      "ModelNumber": "Amazon Elastic Block Store",
      "ProductName": "Non-Volatile memory controller: Amazon.com, Inc. Device 0x8061",
      "SerialNumber": "vol055ed87e06e355aa0",
      "UsedBytes": 0,
      "MaximumLBA": 629145600,
      "PhysicalSize": 322122547200,
      "SectorSize": 512
    }
  ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment