In the nitro-based instances (m5, i3en, etc), AWS presents all drives as NVMe volumes. This provides better I/O performance, but can make life complicated when mapping drives from the terraform or web console to the device the machine actually sees.
The EBS mapping is stored in the NVMe metadata. You can grab it by running:
nvme id-ctrl --raw-binary /dev/nvmXXX | cut -c 3073-3104 | sed 's/ //g'
#!/bin/bash
#
# Creates symbolic links from the nvme drives to /dev/sdX or /dev/xvdX.
# This may not be compatible with instances that have local storage, such
# as i3's
PATH="${PATH}:/usr/sbin"
for blkdev in $( nvme list | awk '/^\/dev/ { print $1 }' ) ; do
mapping=$(nvme id-ctrl --raw-binary "${blkdev}" 2>/dev/null | cut -c3073-3104 | sed 's/ //g')
if [[ "${mapping}" == xvd* ]]; then
( test -b "${blkdev}" && test -L "/dev/${mapping}" ) || ln -s "${blkdev}" "/dev/${mapping}"
for partition in $( ls -1 ${blkdev}p* 2> /dev/null ) ; do
ln -s ${partition} /dev/${mapping}${partition/${blkdev}p/}
done
fi
done
#!/bin/bash
#
# Provides a simple way to create and format logical volumes for
# nitro-based AWS instances based off their configured mount point.
# NOTE: It does not create the fstab entry
#
# Syntax: define_logical_volume.sh <LABEL> <VOLGROUP> <LOGICALVOL> <DEVICE>
# Sample: define_logical_volume.sh SPLUNKFROZEN vg_frozen lv_frozen xvdj
LABEL=$1
VOLGRP=$2
LOGVOL=$3
DEVICE=$4
# Iterate over all the nvme devices, looking for those in /dev
for blkdev in $( nvme list | awk '/^\/dev/ {print $1 }' ); do
# For each device grab the desired device name from the vendor data
mapping=$(nvme id-ctrl --raw-binary "${blkdev}" 2>/dev/null | cut -c3073-3104 | sed 's/ //g')
# If the desired device name is one of those currently requested
if `echo $* | egrep -q "\<${mapping}\>"`; then
# Repoint our device variable to the real device
DEVICE="$blkdev"
# Then partition it for use
parted $DEVICE --script -- mklabel gpt
parted -a optimal $DEVICE mkpart primary 0% 100%
partprobe
sleep 1
fi
done
vgcreate $VOLGRP ${DEVICE}p1
lvcreate -l 100%FREE -n ${LOGVOL} ${VOLGRP}
mkfs.ext4 -L $LABEL /dev/mapper/${VOLGRP}-${LOGVOL}
#!/bin/bash
# Create a simple way to prepare and initialize a swap
# volume on AWS nitro based instances.
# NOTE: Unlike create_logical_volume, this script DOES
# create an fstab entry.
#
# Syntax: define_swap_volume.sh <LABEL> <DEVICE>
# Sample: define_swap_volume.sh SWAP xvdb
LABEL=$1
DEVICE=$2
# Iterate over all the nvme devices, looking for those in /dev
for blkdev in $( nvme list | awk '/^\/dev/ {print $1 }' ); do
# For each device grab the desired device name from the vendor data
mapping=$(nvme id-ctrl --raw-binary "${blkdev}" 2>/dev/null | cut -c3073-3104 | sed 's/ //g')
# If the desired device name is one of those currently requested
if `echo $* | egrep -q "\<${mapping}\>"`; then
# Repoint our device variable to the real device
DEVICE="$blkdev"
# Then partition it for use
parted $DEVICE --script -- mklabel gpt
parted -a optimal $DEVICE mkpart primary 0% 100%
partprobe
sleep 1
mkswap -L $LABEL $DEVICE
swapon $DEVICE
echo "LABEL=$LABEL swap swap defaults,nofail 0 2" >> /etc/fstab
fi
done
#!/bin/bash
#
# This needs to be called every boot, before Splunk starts. It
# initializes local storage as RAID-0.
#
# NOTE: This determines which NVMe drives are local based on
# whether they are 2.5TB or 7.5TB! THIS IS NOT A GOOD
# WAY, but works in a pinch. If you create 2.5TB EBS
# volumes, you're in for some trouble.
if [ ! -b /dev/md0 ]; then
# We are fresh or on new hardware. Recreate the RAID.
rm -f /etc/mdadm.conf 2> /dev/null
DEVICES=$( nvme list | egrep "[72].50 TB" | awk '{print $1}' )
NUM=$( nvme list | egrep "[72].50 TB" | wc -l )
mdadm --create --force --verbose /dev/md0 --level=0 --name=SMARTSTORE_CACHE --raid-devices=${NUM} ${DEVICES}
mkfs -t xfs /dev/md0
mkdir -p /opt/splunk/var/lib/splunk 2> /dev/null
chown splunk:splunk /opt/splunk 2> /dev/null
mdadm --verbose --detail --scan | tee -a /etc/mdadm.conf
fi
# Alternatively, could be mounted to /opt/splunk/var
mount /dev/md0 /opt/splunk/var/lib/splunk
# Configures the splunk initialization script to run on
# boot.
# Because splunk is started by an init.d script, we
# cannot set dependencies in here, and instead must
# also modify the splunk init script.
[Unit]
#DefaultDependencies=no
#After=sysinit.target local-fs.target
#Before=base.target
RequiresMountsFor=/opt/splunk
[Service]
ExecStart=/usr/local/sbin/initialize_nvme_storage.sh
[Install]
WantedBy=default.target
The splunk init script needs to be modified to wait for
the instance storage RAID array to become active. To do
so, modify the splunk_start()
function in the script
to begin with:
# WaitForMount BEGIN
echo Waiting for mount point...
count=0
while ! mountpoint -q /opt/splunk/var/lib/splunk
do
echo "Mount point not ready. Sleep 1 second..."
sleep 1
count=`expr $count + 1`
if test $count -eq 90
then
echo "timed out!"
exit 1
fi
done
# WaitForMount END
echo Starting Splunk...