Last active
June 23, 2021 16:21
-
-
Save kwilczynski/8e7807b22148fe2c1631 to your computer and use it in GitHub Desktop.
AWS EC2, Ephemeral volumes, create RAID level 0 (stripe), etc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -u | |
| set -e | |
| set -o pipefail | |
| export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
| readonly LOCK_FILE='/tmp/.format-volume' | |
| readonly EC2_METADATA_URL='http://169.254.169.254/latest/meta-data' | |
| # Make sure files are 644 and directories are 755. | |
| umask 022 | |
| # Check whether this script was already run? | |
| if [[ -f $LOCK_FILE ]]; then | |
| echo "Previous (completed at "$(. $LOCK_FILE ; echo $DATE)") run has been detected, aborting ..." | |
| exit 1 | |
| fi | |
| # Get current time. | |
| readonly TIMESTAMP=$(TZ=UTC date +%s) | |
| declare -a DEVICE_MAPPING=() | |
| # Get the list of devices from Amazon ... | |
| DEVICE_MAPPING=($( | |
| curl -s ${EC2_METADATA_URL}/block-device-mapping/ | \ | |
| awk '/ephemeral[[:digit:]]+/ { print }' | |
| )) | |
| if (( ${#DEVICE_MAPPING[@]} < 1 )); then | |
| echo 'Unable to find any attached volumes, nothing to do.' | |
| exit 0 | |
| fi | |
| STORAGE_DEVICES_COUNT=0 | |
| declare -a STORAGE_DEVICES=() | |
| # Try to detect the device (based on the current root volume) taking into | |
| # the account different naming scheme e.g., /dev/sdb vs /dev/xvdb, etc. | |
| DEVICE_SCHEME='sd' | |
| if blkid | cut -d' ' -f 1 | grep -qF '/dev/xvda'; then | |
| DEVICE_SCHEME='xvd' | |
| fi | |
| # ... and validate whether a particular device actually | |
| # exists which is not always the case, as sometimes the | |
| # meta-data service would return data where no actual | |
| # device is present. | |
| for device in "${DEVICE_MAPPING[@]}"; do | |
| DEVICE=$(curl -s ${EC2_METADATA_URL}/block-device-mapping/${device}) | |
| # Got a device? Great. | |
| if [[ -n $DEVICE ]]; then | |
| STORAGE_DEVICES+=( "/dev/$(echo $DEVICE | sed -e "s/sd/${DEVICE_SCHEME}/")" ) | |
| fi | |
| done | |
| # How may devices do we have at our disposal? This is | |
| # needed to setup RAID (stripe) later. | |
| STORAGE_DEVICES_COUNT=${#STORAGE_DEVICES[@]} | |
| # Make sure to sort the devices list. | |
| STORAGE_DEVICES=( $(printf '%s\n' "${STORAGE_DEVICES[@]}" | sort) ) | |
| if (( $STORAGE_DEVICES_COUNT < 1 )); then | |
| echo "The attached storage volumes could not be found, aborting..." | |
| exit 1 | |
| fi | |
| # Make sure "noop" scheduler is set. Alternatively, | |
| # the "deadline" could be used to potentially reduce | |
| # I/O latency in some cases. Also, set read-ahead | |
| # value to double the default. | |
| for device in "${STORAGE_DEVICES[@]}"; do | |
| echo 'noop' > /sys/block/${device##*/}/queue/scheduler | |
| blockdev --setra 512 $device | |
| done | |
| # Remove anything that looks like a floppy drive. | |
| sed -i -e \ | |
| '/^.\+fd0/d;/^.\*floppy0/d' \ | |
| /etc/fstab | |
| # Re-format /etc/fstab to fix whitespaces there. | |
| sed -i -e \ | |
| '/^#/!s/\s\+/\t/g' \ | |
| /etc/fstab | |
| # Make sure that attached volume really is not mounted anywhere. | |
| for device in "${STORAGE_DEVICES[@]}"; do | |
| if grep -q $device /proc/mounts; then | |
| # Sort by length, in order to unmount longest path first. | |
| grep $device /proc/mounts | awk '{ print length, $2 }' | \ | |
| sort -gr | cut -d' ' -f2- | xargs umount -f || true | |
| # Remove from /etc/fstab, if needed. | |
| sed -i -e \ | |
| "/^$(echo $device | sed -e 's/\//\\\//g')/d" \ | |
| /etc/fstab | |
| fi | |
| done | |
| # Make sure that /mnt and /srv are not mounted. | |
| for directory in /media /mnt /srv; do | |
| # Nothing of value should be there in these directories. | |
| if [[ -d $directory ]]; then | |
| umount -f $directory || true | |
| rm -rf ${directory}/* | |
| else | |
| mkdir -p $directory | |
| fi | |
| chown root: $directory | |
| chmod 755 $directory | |
| done | |
| # Wipe any old file system signature, just in case. | |
| for device in "${STORAGE_DEVICES[@]}"; do | |
| wipefs -a$(wipefs -f &>/dev/null && echo 'f') $device || true | |
| done | |
| # Make sure to install dependencies if needed. | |
| REFRESH_YUM=0 | |
| for package in mdadm xfsprogs; do | |
| if ! rpm -q $package &>/dev/null; then | |
| if (( $REFRESH_YUM < 1 )); then | |
| yum makecache | |
| REFRESH_YUM=1 | |
| fi | |
| yum install -y $package | |
| fi | |
| done | |
| # Grab first device (to be overridden later, if needed). | |
| DEVICE=${STORAGE_DEVICES[0]} | |
| # Create RAID0 if there is more than one device. | |
| if (( $STORAGE_DEVICES_COUNT > 1 )); then | |
| # Override the device that will be used when mounting. | |
| DEVICE='/dev/md0' | |
| # Stop any RAID array that might be running, | |
| # although there should be no arrays present. | |
| if [[ -b $DEVICE ]]; then | |
| rm -f /etc/mdadm.conf | |
| for option in '--stop' '--remove'; do | |
| mdadm $option --force $DEVICE || true | |
| done | |
| mdadm --zero-superblock \ | |
| $(printf '%s\n' "${STORAGE_DEVICES[@]}") || true | |
| fi | |
| mdadm --create --verbose $DEVICE --level=stripe --chunk=256 \ | |
| --raid-devices=${STORAGE_DEVICES_COUNT} \ | |
| $(printf '%s\n' "${STORAGE_DEVICES[@]}") | |
| # Activate device immediately. | |
| mdadm --readwrite $DEVICE || true | |
| # Display details about the assembled array. | |
| mdadm --detail $DEVICE | |
| # Set read-ahead that makes sense for RAID device. | |
| blockdev --setra 65536 $DEVICE | |
| # Populate the /etc/mdadm.conf file. | |
| cat <<'EOF' | tee /etc/mdadm.conf | |
| DEVICE /dev/sd[a-z] /dev/xvd[a-z] | |
| CREATE owner=root group=disk mode=0660 auto=yes | |
| HOMEHOST <system> | |
| MAILADDR root | |
| EOF | |
| mdadm --detail --scan >> /etc/mdadm.conf | |
| chown root: /etc/mdadm.conf | |
| chmod 644 /etc/mdadm.conf | |
| cat /proc/mdstat | |
| fi | |
| # By default, the attached volume is formatted with ext3. | |
| mkfs.xfs -q -L '/srv' -f $DEVICE | |
| # Add extra volume. | |
| cat <<EOS | sed -e 's/\s\+/\t/g' | tee -a /etc/fstab | |
| $DEVICE /srv xfs defaults,noatime,nodiratime,nobarrier,nofail,comment=cloudconfig 0 2 | |
| EOS | |
| mount /srv | |
| xfs_info $DEVICE | |
| sync | |
| sync | |
| # Update initramfs for all kernels ... | |
| while read version; do | |
| version=${version#*-} | |
| dracut -a mdraid --mdadmconf -f -H /boot/initramfs-${version}.img $version | |
| ls -l /boot/initramfs-${version}.img | |
| done < <(rpm -qa kernel) | |
| # Release I/O buffer cache. | |
| echo '3' > /proc/sys/vm/drop_caches | |
| # Mount everything else... | |
| mount -a | |
| # Display mount points and free space. | |
| mount | |
| printf "\n" | |
| df -h | |
| cat <<EOF | tee $LOCK_FILE | |
| TIMESTAMP=$TIMESTAMP | |
| DATE="$(date -d @${TIMESTAMP})" | |
| EOF | |
| chown root:root $LOCK_FILE | |
| chmod 644 $LOCK_FILE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment