AWS Cloud Operations Blog
Get Disk Utilization of Your Fleet Using AWS Systems Manager Custom Inventory Types
Some of my customers need assistance while operating their Amazon Elastic Compute Cloud (Amazon EC2) infrastructure. They need to:
- Review the disk usage of various volumes/ disks within an EC2 instance. To do it in a scalable way, one does not need to access the instance either through a Remote Desktop Session (RDP) or use a third party tool.
- Limit access to an EC2 instance for performing operational activities such as reviewing disk utilization.
In this blog, I’ll show how AWS Systems Manager Inventory provides a centralized way to collect and query system, application, and instance metadata. The inventory data collection policy is configured using State Manager, which in turn gets executed by aws:softwareInventory plugin in amazon-ssm-agent.
AWS Systems Manager Inventory provides two ways to define the types of data that it collects: predefined and custom.
- Predefined data types (with prefix AWS) are natively supported by the inventory plugin via multiple gatherers. Some examples of predefined inventory types are AWS:Application and AWS:WindowsUpdate.
- Custom data type (with prefix Custom) is a special inventory data type that can be defined by end users. This data type provides the flexibility of collecting additional inventory data, such as server rack location of a managed instance.
In this blog, I share an example that shows how to use the custom inventory data type to collect disk utilization for Windows instances. And use PowerShell scripts to collect disk utilization data in the Inventory. After the data is collected, I use this data to get fleet-level aggregation of disk usage.
Step1: Create Inventory Policy Document with aws:runPowerShellScript plugin
By default, you can use the AWS-GatherSoftwareInventory document to collect Inventory data. However, for this example you’ll create a document with aws:runPowerShellScript & aws:softwareInventory plugins to ensure that a PowerShell script is invoked before Inventory collection begins. Since amazon-ssm-agent preserves the order of the plugin’s executions, it ensures that the latest Disk Utilization data is captured before Inventory data is collected.
-
Option 1: Create Document using the AWS Management Console
Create the document in the AWS Management Console by going to AWS Systems Manager → Documents → Create document → Command or Session -> Enter a “Name” -> replace JSON content with the following and click on the Create document button:
{ "schemaVersion": "2.2", "description": "Run first a shell script & then inventory plugin.", "mainSteps": [{ "action": "aws:runPowerShellScript", "name": "runPowerShellScript", "inputs": { "runCommand": "{{ commands }}" } }, { "action": "aws:softwareInventory", "name": "collectSoftwareInventoryItems", "inputs": { "applications": "{{ applications }}", "awsComponents": "{{ awsComponents }}", "networkConfig": "{{ networkConfig }}", "windowsUpdates": "{{ windowsUpdates }}", "customInventory": "{{ customInventory }}" } } ], "parameters": { "commands": { "type": "StringList", "description": "(Required) Specify a shell script or a command to run.", "minItems": 1, "displayType": "textarea" }, "applications": { "type": "String", "default": "Enabled", "description": "(Optional) Collect data for installed applications.", "allowedValues": [ "Enabled", "Disabled" ] }, "awsComponents": { "type": "String", "default": "Enabled", "description": "(Optional) Collect data for AWSComponents like amazon-ssm-agent.", "allowedValues": [ "Enabled", "Disabled" ] }, "networkConfig": { "type": "String", "default": "Enabled", "description": "(Optional) Collect data for Network configurations.", "allowedValues": [ "Enabled", "Disabled" ] }, "windowsUpdates": { "type": "String", "default": "Enabled", "description": "(Optional) Collect data for all WindowsUpdates.", "allowedValues": [ "Enabled", "Disabled" ] }, "customInventory": { "type": "String", "default": "Enabled", "description": "(Optional) Collect data for custom inventory.", "allowedValues": [ "Enabled", "Disabled" ] } } }
-
Option 2: Create Document using the AWS command line (aws-cli)
- Create the document by running the aws-cli command that creates the document:
aws ssm create-document --content file://path to your file\FileName —name "CustomInventory-Doc" —document-type Command
- Verify the document’s status by running the following command:
aws ssm list-documents —document-filter-list key=Name,value=CustomInventory-Doc
Here is a sample output that you should see:{ “DocumentIdentifiers”: [ { “Name”: ” CustomInventory-Doc “, “PlatformTypes”: [ “Windows”, “Linux” ], “DocumentVersion”: “1”, “DocumentType”: “Command”, “Owner”: “xxx”, “SchemaVersion”: “2.0” } ] }
- Create the document by running the aws-cli command that creates the document:
Step2: Create association using CustomInventory-Doc
Now that the inventory policy document is created, you will “Create Association”, that is you’ll associate this policy document to targeted instances. To use the AWS Systems Manager console to Create Association, go to State Manager under Node Management category and click on Create association button.
-
- Select the CustomInventory-Doc in Document section:
- Paste the following PowerShell script in the Commands parameter (as shown in the screenshot that follows). This script is executed by the aws:runPowerShellScript plugin before the Inventory plugin is invoked.Script:
- For PowerShell version 3 and above
$data = get-ciminstance win32_logicaldisk | Select-Object @{n="DeviceId";e={$_."DeviceID"}}, @{n="VolumeName";e={$_."VolumeName"}}, @{n="Use%";e={"{0}" -f [math]::Round(($_."Size" - $_."FreeSpace") * 100 / $_."Size",0)}}, @{n="Size(GB)";e={"{0}" -f [math]::Round($_."Size" / 1GB ,0)}} | ConvertTo-Json $content = "{`"SchemaVersion`" : `"1.0`", `"TypeName`": `"Custom:DiskUtilization`", `"Content`": $data}" $instanceId = Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/instance-id $filepath = "C:\ProgramData\Amazon\SSM\InstanceData\" + $instanceId + "\inventory\custom\CustomDiskUsage.json" if (-NOT (Test-Path $filepath)) { New-Item $filepath -ItemType file } Set-Content -Path $filepath -Value $content
- For PowerShell version below 3
$data = get-wmiobject win32_logicaldisk | Select-Object @{n="DeviceId";e={$_."DeviceID"}}, @{n="VolumeName";e={$_."VolumeName"}}, @{n="Use%";e={"{0}" -f [math]::Round(($_."Size" - $_."FreeSpace") * 100 / $_."Size",0)}}, @{n="Size(GB)";e={"{0}" -f [math]::Round($_."Size" / 1GB ,0)}} | ConvertTo-Json $content = "{`"SchemaVersion`" : `"1.0`", `"TypeName`": `"Custom:DiskUtilization`", `"Content`": $data}" $instanceId = Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/instance-id $filepath = "C:\ProgramData\Amazon\SSM\InstanceData\" + $instanceId + "\inventory\custom\CustomDiskUsage.json" if (-NOT (Test-Path $filepath)) { New-Item $filepath -ItemType file } Set-Content -Path $filepath -Value $content
Note: For PowerShell 3.0 and above, you should use CIM cmdlet which performs the same tasks as the WMI cmdlets. The CIM cmdlets comply with WS-Management (WSMan) standards and the Common Information Model (CIM) standard, which enables the cmdlets to use the same techniques to manage Windows computers and those running other operating systems.
This script gets disk utilization data using win32_logicaldisk. It uses Instance-Metadata to get InstanceId, which is required in order to save the content in the path:
%SystemDrive%\ProgramData\Amazon\SSM\InstanceData\<instance-id>\inventory\custom
- For PowerShell version 3 and above
- Next, you need to pick instances to which you want to attach this Association. (Note – All/* target is currently only supported for associations with AWS-GatherSoftwareInventory document).
In addition, define a schedule for the inventory collection. In this blog, we have executed association on selected instances with an hourly schedule.
- Select the CustomInventory-Doc in Document section:
Choose Create Association button and that’s it. After the policy runs on the targeted instances, disk utilization data will be collected and become ready for consumption.
Step3: Reviewing disk utilization
Now that associate is created and executed successfully, let’s check disk utilization for an instance by visiting Fleet Manager under Node Management → open intended instance ID → select Inventory under Properties → select Custom:DiskUtilization from Inventory type drop-down menu. The following screenshot shows the new Custom data for one of my instances.
You can also apply various filters to determine the instance’s Disk Utilization health.
Let’s apply a filter to disk utilization of more than 80 percent. The following screenshot shows instances matching the filter.
Data visualization
Using the resource data sync feature of AWS Systems Manager, you can sync the metadata collected by AWS Systems Manager Inventory to Amazon S3. In Amazon S3, you can aggregate the metadata for different AWS Regions and accounts. After you sync this inventory data to Amazon S3, you can create various visuals of the data using Amazon Athena and Amazon QuickSight.
Conclusion
This blog shows you how to create a custom document with aws:runPowerShellScript & aws:softwareInventory plugins. This allows you to collect and then send Custom Inventory data from an instance every time the Inventory policy is run. The data can then be queried at both the fleet and instance level.
In this blog, you used a PowerShell script to get the custom data, however the same document can also be used to trigger any third-party application running in the instance to collect custom data.
Additionally, recently AWS Systems Manager Fleet Manager’s feature of managing Amazon EBS volumes on managed instances introduced the ability to perform tasks such as initializing an EBS volume, formatting a partition, and mounting the volume.