EBS Volume Available

Ed Reinoso
5 min readNov 30, 2020

Before Reading

  • This function will only run successfully only if an EBS volume is attached right after created.
  • At the moment, this is just working for the general purpose instances where their block device is XVD, not NVME block devices.
  • As always, there needs to be a set of IAM permissions for services to interact among each other.

Tech Stack

Lambda: Python — Boto3

SSM: Shell Scripting

CloudWatch: Events

Goal

One of the biggest motivation behind developing this function was to automate the process for which a volume is made available in an EC2 instance.

Usually, this is somewhat a process that requires some Linux SysAdmin knowledge. In the reference section, I will provide the resource with the commands to make these volumes available.

I wanted to create a solution like this to save time when launching a new EC2 instance. This would provide a more scalable way of deploying multiple servers at the same time.

Logic

For this function to execute, the following three steps are required:

CloudWatch Event

In this step, we’re setting up the trigger for the function to execute. Event patterns will allow us to call lambda function based on certain CloudWatch metrics.

As we are interested to know when a new volume is created, we are going to select EC2 as Service Name.

Then, we select EBS Volume Notification as the Event Type.

There are currently 5 specific events under EBS Volume Notification:

The option that we are going to be working with is createVolume.

It is very important to mention that this automation tool will only work if an EBS volume is created and then automatically attached to a running EC2 instance.

Note:

In other words, the EBS volume will have to be attached at the moment it is created. Otherwise, if it’s attached at a later moment, the volume will not get mounted in the EC2 instance.

The reason for this is because we’re using createVolume, which is the closest event that is captured from AWS regarding EBS Volume events.

Lambda Function

Now that we have the trigger, we need to take care of the lambda function which will carry the execution commands to SSM in order to make the volume available.

For this, we have a simple python script that would just get some input from the CloudWatch Events (previous step), and then call a SSM document to perform the Bash operations.

Code Breakdown (Optional):

17. time.sleep(40)
  • This timer is essential to wait for few seconds so that the volume gets attached to the instance right after it’s being created.
18. response = client.describe_volumes(
  • This line will look for the proper information about a volume, passing the volumeId that is obtained CloudWatch Events (previous step).
25. for attchmnt in volume['Attachments']:
  • This line would iterate through the list of attachments once the volume is attached to an instance. With this line, we will be able to get the instance’s information.
27. attchmnt_word = attchmnt['Device'][len(attchmnt['Device'])-1:len(attchmnt['Device'])]
  • This line would return the last character of the string attchment[‘Device’]. It will be useful because we can then then set the device, usually /dev/xvd(f-p).
32. response = ssm.send_command(
  • This line will trigger an SSM send command to execute the Bash commands into the specified instance. We’re passing as a parameter the device that is going to be made available.

Shell Function

The final step in this automation pipeline is to finally make the EBS volume available at the moment it is attached to the instance.

Here, we are just going to perform the specific Bash commands to:

  1. Get information about a device, such as its file system type
  2. Create a file system on the volume.
  3. Create a mount point directory for the volume
  4. Mount the volume at the directory created

Code Breakdown (Optional):

12. if [ $device != \"/dev/xvda\" ]; then
  • This line is the gateway to work only with XVD block devices
  • As mentioned before, at the moment, we are only with these block devices. If this were to be a Nitro system, which would require a NVME block device, which is not supported by the automation.
15. while [ $logic != \"true\" ]
16. do
  • I am iterating as long as the condition logic is not false.
  • As we may have multiple volumes that need to be available to an instance, we need a way to dynamically create directories, such as not all would have the same name.
17. x=`ls / | grep $value`
  • With grep, we can list all the directories that contain our value, which is /data. We store this in a variable called X since we’ll need to determine whether the directory /data exists.
18. if [[ -z  $x ]]; then
19. mkdir /$value
20. logic=true
21. else
22. ((n+=1)) #sum operations
23. value=\"data\"
24. value=\"$value$n\"
25. fi
  • Line 18 just checks whether the value of X is empty, this means that if a /data directory doesn’t exist, then a new directory needs to be created (line 19)
  • If it does exist, it increments a counter to the directory name so that it doesn’t conflict with the existing directory. For example, if name /data is already taken, then /data1 will be created.
  • Line 20 is declaring a boolean that will be evaluated in while do loop. This tells the while loop whether a new directory has been created. So while this value is not true, then it will keep iterating until meeting the condition.

--

--

Ed Reinoso

DevOps engineer trying to make technology accessible