Summary
With Pure Fusion, you can manage resources across multiple arrays from a single control plane, enabling consistency at scale and simplifying management of complex application storage requirements.
When managing storage infrastructure at scale, one of the most powerful approaches is treating related storage resources as cohesive workloads rather than individual components. This becomes especially important when dealing with applications like SQL Server that have specific storage patterns and requirements and are often deployed at scale in a data center or cloud.
In this post, I’ll walk through a complete workflow for creating and managing application-specific storage workloads using the Pure Fusion™ fleet capability with PowerShell. We’ll see how we can define storage templates, called presets, once and deploy them consistently across our entire fleet of storage arrays.
Why Pure Fusion Fleet Management?
Pure Fusion is a fleet management capability that allows you to manage resources across multiple arrays from a single control plane. Before diving into the implementation, let’s understand the challenges Pure Fusion addresses:
- Consistency at scale: Manually configuring storage across multiple arrays leads to configuration drift
- Complexity management: Applications like SQL Server require multiple volumes with different characteristics
- Operational efficiency: Repetitive tasks consume valuable time and increase error risk
- Governance: Ensuring compliance with organizational standards across all deployments
Pure Fusion fleet management solves these challenges by providing a single control plane for managing storage resources across your entire fleet as cohesive workloads.
Pure Fusion and PowerShell SDK2
With the release of the Pure Storage PowerShell SDK2 version 2.43.30, cmdlet support for Pure Fusion operations is now available. The release notes detail these new capabilities that make it easier than ever to implement consistent storage management across your entire fleet.
Connecting to the Pure Storage Array
First, we need to establish a connection to one of our fleet member arrays.
|
1 2 3 4 |
# Connect to any FlashArray in your Fleet $ArrayName = ‘sn1-x90r2-f06-27.puretec.purestorage.com’ $Credential = Import–CliXml –Path “$HOME\FA_Cred.xml” $FlashArray = Connect–Pfa2Array –EndPoint $ArrayName –Credential $Credential –IgnoreCertificateError |
Exploring Available Fleet cmdlets
The Pure Storage PowerShell SDK2 provides fleet management capabilities through several cmdlets. These cmdlets enable you to create and manage fleets (New-Pfa2Fleet, Update-Pfa2Fleet, Remove-Pfa2Fleet), view fleet information and membership (Get-Pfa2Fleet, Get-Pfa2FleetMember), and manage fleet membership by adding or removing arrays (New-Pfa2FleetMember, Remove-Pfa2FleetMember). Security is handled through fleet keys (New-Pfa2FleetKey, Get-Pfa2FleetKey), which allow arrays to join a fleet securely. When creating a fleet, the current array automatically becomes the first member, and additional arrays can be added using a fleet key generated from any existing member. Arrays can only be removed from a fleet if they’re not utilizing any fleet-wide resources, ensuring data integrity across the fleet.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Get all available Fleet-related PowerShell cmdlets Get–Command –Module PureStoragePowerShellSDK2 –Noun ‘*Fleet*’ CommandType Name Version Source —————– —— ———– ——— Cmdlet Get–Pfa2Fleet 2.43.30 PureStoragePowerShellSDK2 Cmdlet Get–Pfa2FleetKey 2.43.30 PureStoragePowerShellSDK2 Cmdlet Get–Pfa2FleetMember 2.43.30 PureStoragePowerShellSDK2 Cmdlet New–Pfa2Fleet 2.43.30 PureStoragePowerShellSDK2 Cmdlet New–Pfa2FleetKey 2.43.30 PureStoragePowerShellSDK2 Cmdlet New–Pfa2FleetMember 2.43.30 PureStoragePowerShellSDK2 Cmdlet Remove–Pfa2Fleet 2.43.30 PureStoragePowerShellSDK2 Cmdlet Remove–Pfa2FleetMember 2.43.30 PureStoragePowerShellSDK2 Cmdlet Update–Pfa2Fleet 2.43.30 PureStoragePowerShellSDK2 |
Similarly, let’s check what workload management cmdlets are available:
The workload management cmdlets provide functionality for creating and managing storage presets and workloads across your fleet. You can create and manage workload presets (New-Pfa2PresetWorkload, Set-Pfa2PresetWorkload, Update-Pfa2PresetWorkload, Remove-Pfa2PresetWorkload), which serve as templates defining volume configurations, QoS settings, placement rules, and snapshot policies. Once presets are defined, you can deploy actual workload instances (New-Pfa2Workload, Update-Pfa2Workload, Remove-Pfa2Workload) that inherit all the preset’s configurations. There are also cmdlets for workload placement recommendations (New-Pfa2WorkloadPlacementRecommendation, Get-Pfa2WorkloadPlacementRecommendation) that help optimize where workloads should be deployed across your fleet based on capacity and performance requirements. Additionally, you can manage workload tags (Get-Pfa2WorkloadTag, Set-Pfa2WorkloadTagBatch, Remove-Pfa2WorkloadTag) for governance, tracking, and organizational purposes. These cmdlets work together to provide a complete workload lifecycle management solution from template creation through deployment and ongoing management.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Get all available Workload and Preset-related PowerShell cmdlets Get–Command –Module PureStoragePowerShellSDK2 –Noun ‘*Workload*’ Cmdlet Get–Pfa2PresetWorkload 2.43.30 PureStoragePowerShellSDK2 Cmdlet Get–Pfa2Workload 2.43.30 PureStoragePowerShellSDK2 Cmdlet Get–Pfa2WorkloadPlacementRecommendation 2.43.30 PureStoragePowerShellSDK2 Cmdlet Get–Pfa2WorkloadTag 2.43.30 PureStoragePowerShellSDK2 Cmdlet New–Pfa2PresetWorkload 2.43.30 PureStoragePowerShellSDK2 Cmdlet New–Pfa2Workload 2.43.30 PureStoragePowerShellSDK2 Cmdlet New–Pfa2WorkloadPlacementRecommendation 2.43.30 PureStoragePowerShellSDK2 Cmdlet Remove–Pfa2PresetWorkload 2.43.30 PureStoragePowerShellSDK2 Cmdlet Remove–Pfa2Workload 2.43.30 PureStoragePowerShellSDK2 Cmdlet Remove–Pfa2WorkloadTag 2.43.30 PureStoragePowerShellSDK2 Cmdlet Set–Pfa2PresetWorkload 2.43.30 PureStoragePowerShellSDK2 Cmdlet Set–Pfa2WorkloadTagBatch 2.43.30 PureStoragePowerShellSDK2 Cmdlet Update–Pfa2PresetWorkload 2.43.30 PureStoragePowerShellSDK2 Cmdlet Update–Pfa2Workload 2.43.30 PureStoragePowerShellSDK2 |
Examining Our Fleet Members
Now let’s check which arrays are part of our Pure Fusion fleet:
|
1 2 3 4 5 6 7 8 |
# Get fleet membership – shows all arrays that are part of this Fusion fleet $FleetInfo = Get–Pfa2FleetMember –Array $FlashArray $FleetInfo.Member.Name sn1–c60–e12–16 sn1–x90r2–f06–27 sn1–x90r2–f06–33 sn1–s200–c09–33 |
We have four arrays in our fleet: three FlashArray™ systems and one FlashBlade® (//S200 model).
Understanding the Preset Structure
A workload preset in Pure Fusion consists of several interconnected configurations:
- Volume configurations: Define the number, size, and type of volumes
- QoS configurations: Set performance limits and guarantees
- Placement configurations: Determine which arrays can host the workload
- Snapshot configurations: Define data protection policies
- Workload tags: Provide metadata for tracking and governance
Let’s break down each component as we build our SQL Server preset:
Creating a SQL Server Workload Preset
Now for the interesting part. We’ll create a preset workload template designed specifically for SQL Server deployments. This template will define:
- Four volume types (Data, Log, TempDB, and System): Each with specific performance characteristics, separated for observability, management, and recovery reasons
- Specific sizes for each volume type based on best practices and system requirements
- Performance QoS settings to ensure consistent IOPS delivery (this is optional)
- Snapshot policies that exclude TempDB from snapshots (since it’s recreated on restart)
- Appropriate tagging for governance, compliance, and cost tracking
Here’s the complete template definition with detailed explanations:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# Example: Database with Data, Log, TempDB, and System volumes $presetParams = @{ Array = $FlashArray ContextNames = ‘fsa-lab-fleet1’ #needs to be the fleet name when creating a fleet-wide object like a Preset Name = “SQL-Server-MultiDisk-Optimized” Description = “SQL Server optimized Preset with different volumes for Data, Log, TempDB, and System” WorkloadType = “database” # Different QoS configurations for the whole Preset QosConfigurationsName = @(“Data-QoS”) QosConfigurationsIopsLimit = @(“75000”) # 75K IOPS limit suitable for high-performance SQL Workloads # Different placement configurations PlacementConfigurationsName = @(“Data-Placement”) PlacementConfigurationsStorageClassName = @(“flasharray-x”) # Target FlashArray//X series arrays PlacementConfigurationsStorageClassResourceType = @(“storage-classes”) PlacementConfigurationsQosConfigurations = @(@(“Data-QoS”)) # SQL Server volume configuration with different sizes and characteristics VolumeConfigurationsName = @(“SQL-Data”, “SQL-Log”, “SQL-TempDB”, “SQL-System”) VolumeConfigurationsCount = @(“1”, “1”, “1”, “1”) VolumeConfigurationsPlacementConfigurations = @( @(“Data-Placement”), @(“Data-Placement”), @(“Data-Placement”), @(“Data-Placement”) ) VolumeConfigurationsProvisionedSize = @( 5TB, 1TB, 500GB, 50GB ) # Data, Log, TempDB, System volumes using PowerShell’s native size suffixes # Different snapshot policies SnapshotConfigurationsName = @(“Data-Snapshots”) SnapshotConfigurationsRulesEvery = @(“600000”) # 10min in milliseconds SnapshotConfigurationsRulesKeepFor = @(“604800000”) # 7days in milliseconds # Create a snapshot configuration for all volumes. TempDB volume excluded from snapshot configurations VolumeConfigurationsSnapshotConfigurations = @( @(“Data-Snapshots”), # Data volume gets snapshots @(“Data-Snapshots”), # Log volume gets snapshots @(), # TempDB volume gets NO snapshots (empty array) @(“Data-Snapshots”) # System volume gets snapshots ) # Workload tags for identification WorkloadTagsKey = @(“database-type”, “application”, “tier”, “backup-required”) WorkloadTagsValue = @(“sql-server”, “enterprise-app”, “production”, “true”) } Write–Host “Creating SQL Server optimized multi-disk Preset…” –ForegroundColor Green New–Pfa2PresetWorkload @presetParams Creating SQL Server optimized multi–disk Preset... Id : 7d107723–4cb6–4d23–a6f0–09bac54a7ef6 Name : SQL–Server–MultiDisk–Optimized Context : @{Id=‘9c38723f-10df-4f64-85a4-db32548cc1ea’; Name=‘fsa-lab-fleet1’} Description : SQL Server optimized Preset with different volumes for Data, Log, TempDB, and System Parameters : {} PeriodicReplicationConfigurations : {} PlacementConfigurations : {@{Name=‘Data-Placement’; QosConfigurations=System.Collections.Generic.List`1[System.String]; StorageClass=@{Name=‘flasharray-x’; ResourceType=‘storage-classes’}}} QosConfigurations : {@{IopsLimit=‘75000’; Name=‘Data-QoS’}} Revision : 1 SnapshotConfigurations : {@{Name=‘Data-Snapshots’; Rules=System.Collections.Generic.List`1[PureStorage.FlashArray.Rest.Model.PresetWorkloadSnapshotRule]}} VolumeConfigurations : {@{Count=‘1’; Name=‘SQL-Data’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘5497558138880’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}, @{Count=‘1’; Name=‘SQL-Log’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘1099511627776’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}, @{Count=‘1’; Name=‘SQL-TempDB’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘536870912000’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}, @{Count=‘1’; Name=‘SQL-System’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘2199023255552’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}} WorkloadTags : {@{Copyable=‘true’; Key=‘database-type’; Namespace=‘default’; Value=‘sql-server’}, @{Copyable=‘true’; Key=‘application’; Namespace=‘default’; Value=‘enterprise-app’}, @{Copyable=‘true’; Key=‘tier’; Namespace=‘default’; Value=‘production’}, @{Copyable=‘true’; Key=‘backup-required’; Namespace=‘default’; Value=‘true’}} WorkloadType : database |
Let’s verify that our preset is now visible across the fleet:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# Get the newly created Workload — the -Filter parameter is missing from this cmdlet Get–Pfa2PresetWorkload –Array $FlashArray | Where–Object { $_.Name –like “fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized” } | Format–List Id : 7d107723–4cb6–4d23–a6f0–09bac54a7ef6 Name : fsa–lab–fleet1:SQL–Server–MultiDisk–Optimized Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Description : SQL Server optimized Preset with different volumes for Data, Log, TempDB, and System Parameters : {} PeriodicReplicationConfigurations : {} PlacementConfigurations : {@{Name=‘Data-Placement’; QosConfigurations=System.Collections.Generic.List`1[System.String]; StorageClass=@{Name=‘flasharray-x’; ResourceType=‘storage-classes’}}} QosConfigurations : {@{IopsLimit=‘75000’; Name=‘Data-QoS’}} Revision : 1 SnapshotConfigurations : {@{Name=‘Data-Snapshots’; Rules=System.Collections.Generic.List`1[PureStorage.FlashArray.Rest.Model.PresetWorkloadSnapshotRule]}} VolumeConfigurations : {@{Count=‘1’; Name=‘SQL-Data’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘5497558138880’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}, @{Count=‘1’; Name=‘SQL-Log’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘1099511627776’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}, @{Count=‘1’; Name=‘SQL-TempDB’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘536870912000’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}, @{Count=‘1’; Name=‘SQL-System’; PlacementConfigurations=System.Collections.Generic.List`1[System.String]; ProvisionedSize=‘2199023255552’; SnapshotConfigurations=System.Collections.Generic.List`1[System.String]}} WorkloadTags : {@{Copyable=‘true’; Key=‘database-type’; Namespace=‘default’; Value=‘sql-server’}, @{Copyable=‘true’; Key=‘application’; Namespace=‘default’; Value=‘enterprise-app’}, @{Copyable=‘true’; Key=‘tier’; Namespace=‘default’; Value=‘production’}, @{Copyable=‘true’; Key=‘backup-required’; Namespace=‘default’; Value=‘true’}} WorkloadType : database |
Deploying a SQL Server Workload Instance
Now that we have our template defined, let’s create an actual workload instance from this preset. Once created, this storage can be attached to a physical or virtual machine.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Example 1: Create Production SQL Server Workload $workloadParams1 = @{ Array = $FlashArray Name = “Production-SQL-01” PresetNames = @(“fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized”) } New–Pfa2Workload @workloadParams1 Id : c4d35063–cc7e–4a34–8a1d–5d2590d40879 Name : Production–SQL–01 Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Created : 8/14/2025 9:59:57 PM Destroyed : False Preset : @{Id=‘7d107723-4cb6-4d23-a6f0-09bac54a7ef6’; Name=‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’; Revision=1} Status : ready StatusDetails : {} TimeRemaining : |
And confirm it was created:
|
1 2 3 4 5 6 7 |
# Get the newly created Workload — the -Filter parameter is missing from this cmdlet Get–Pfa2Workload –Array $FlashArray | Where–Object { $_.Preset.Name –eq ‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’ } | Format–Table –AutoSize Id Name Context Created Destroyed Preset Status StatusDetails TimeRemaining — —— ———– ———– ————– ——— ——— ——————– ——————– c4d35063–cc7e–4a34–8a1d–5d2590d40879 Production–SQL–01 @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} 8/14/2025 9:59:57 PM False @{Id=‘7d107723-4cb6-4d23-a6f0-09bac54a7ef6’; Name=‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’; Revision=1} ready {} |
Examining the Created Resources
Let’s examine what exactly was created for this workload. First, let’s look at the volume group. Here, you’ll find the QoS configuration, as well as space accounting information about all of the volumes in the volume group. When examining Pure Storage resources in a Pure Fusion-managed environment, you’ll notice two critical attributes: Context and Workload. Let’s look at those more closely.
Context: This identifies where the resource is located within the fleet hierarchy. It contains:
- Id: A unique identifier for the location
- Name: The human-readable name (usually the array name for array-specific resources or fleet name for fleet-wide resources)
In our example, Context: @{Id=’081f096d-1c16-42a6-9855-92678d705a1c’; Name=’sn1-x90r2-f06-27′} tells us this volume group resides on the array named sn1-x90r2-f06-27. The Id is a unique identifier for the resource.
Workload: This links the resource back to its parent workload and configuration source. It contains:
- Id: The unique identifier of the parent workload
- Name: The workload instance name
- ResourceType: Always ‘workloads’ for workload-related resources
- _Configuration: Which configuration from the preset this resource implements (e.g., ‘Data-QoS’, ‘SQL-Data’)
In our example, Workload: @{Id=’c4d35063-cc7e-4a34-8a1d-5d2590d40879′; Name=’Production-SQL-01′; ResourceType=’workloads’; _Configuration=’Data-QoS’} shows that this volume group belongs to the Production-SQL-01 workload and implements the ‘Data-QoS’ configuration from our preset.
These attributes are crucial for tracking and managing resources across your fleet, as they provide the linkage between fleet-level definitions and array-specific implementations.
In the code below, we’re using the Pure Storage PowerShell SDK2’s API filtering capabilities to retrieve only the volume group that belongs to our Production-SQL-01 workload. This server-side filtering is crucial for performance at scale. Rather than retrieving all volume groups and filtering locally (which could be hundreds or thousands of objects), we let the array do the work and return only the specific resource we need. For a deeper dive into filtering and querying Pure Storage resources, check out my blog series on PowerShell SDK filtering techniques. You’ll find that each of the examples in this post uses array-side API filtering.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Get the volume group and volume information for the new Workload using the array-side API filtering Get–Pfa2VolumeGroup –Array $FlashArray –Filter “workload.name=’Production-SQL-01′” Id : cc7bbf54–20b6–bb98–1ce6–62893466ce8d Name : vg–c4d35063–Data–QoS–9rpck Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Workload : @{Id=‘c4d35063-cc7e-4a34-8a1d-5d2590d40879’; Name=‘Production-SQL-01’; ResourceType=‘workloads’; _Configuration=‘Data-QoS’} Destroyed : False Pod : PriorityAdjustment : @{PriorityAdjustmentOperator=‘+’; PriorityAdjustmentValue=0} Qos : @{IopsLimit=75000} Space : @{DataReduction=1; Snapshots=0; ThinProvisioning=0; TotalPhysical=0; TotalProvisioned=0; TotalReduction=1; TotalUsed=0; Unique=0; UsedProvisioned=0; Virtual=0} TimeRemaining : VolumeCount : 4 |
And now let’s check the individual volumes that were created.
In the listing below, you’ll see the technical details of each of the volumes created: things like QoS configuration, space accounting, and volume group member. And again, you’ll find Context and Workload. Again, we’re using array-side API filtering with the parameter -Filter “workload.name=’Production-SQL-01′”
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
Get–Pfa2Volume –Array $FlashArray –Filter “workload.name=’Production-SQL-01′” Id : 9e439b3f–86bd–c219–7101–007db6725cb6 Name : vg–c4d35063–Data–QoS–9rpck/vol–c4d35063–SQL–Data–0000–ds7qz ConnectionCount : 0 Created : 8/14/2025 9:59:58 PM Destroyed : False HostEncryptionKeyStatus : none PriorityAdjustment : @{PriorityAdjustmentOperator=‘+’; PriorityAdjustmentValue=0} Provisioned : 5497558138880 Qos : Serial : 81F096D1C1642A69025A4680 Space : @{DataReduction=1; Snapshots=0; ThinProvisioning=1; TotalPhysical=0; TotalProvisioned=5497558138880; TotalReduction=1; TotalUsed=0; Unique=0; UsedProvisioned=5497558138880; Virtual=0} TimeRemaining : Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Pod : Priority : 0 PromotionStatus : promoted ProtocolEndpoint : RequestedPromotionState : promoted Source : Subtype : regular VolumeGroup : @{Id=‘cc7bbf54-20b6-bb98-1ce6-62893466ce8d’; Name=‘vg-c4d35063-Data-QoS-9rpck’} Workload : @{Id=‘c4d35063-cc7e-4a34-8a1d-5d2590d40879’; Name=‘Production-SQL-01’; ResourceType=‘workloads’; _Configuration=‘SQL-Data’} Id : 0eb82b0e–ad47–0547–db9d–c60222f84eef Name : vg–c4d35063–Data–QoS–9rpck/vol–c4d35063–SQL–Log–0000–c7j4r ConnectionCount : 0 Created : 8/14/2025 9:59:58 PM Destroyed : False HostEncryptionKeyStatus : none PriorityAdjustment : @{PriorityAdjustmentOperator=‘+’; PriorityAdjustmentValue=0} Provisioned : 1099511627776 Qos : Serial : 81F096D1C1642A69025A4681 Space : @{DataReduction=1; Snapshots=0; ThinProvisioning=1; TotalPhysical=0; TotalProvisioned=1099511627776; TotalReduction=1; TotalUsed=0; Unique=0; UsedProvisioned=1099511627776; Virtual=0} TimeRemaining : Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Pod : Priority : 0 PromotionStatus : promoted ProtocolEndpoint : RequestedPromotionState : promoted Source : Subtype : regular VolumeGroup : @{Id=‘cc7bbf54-20b6-bb98-1ce6-62893466ce8d’; Name=‘vg-c4d35063-Data-QoS-9rpck’} Workload : @{Id=‘c4d35063-cc7e-4a34-8a1d-5d2590d40879’; Name=‘Production-SQL-01’; ResourceType=‘workloads’; _Configuration=‘SQL-Log’} Id : 26907ebe–76a2–d72c–446b–8b2b775a1e21 Name : vg–c4d35063–Data–QoS–9rpck/vol–c4d35063–SQL–TempDB–0000–qcksj ConnectionCount : 0 Created : 8/14/2025 9:59:58 PM Destroyed : False HostEncryptionKeyStatus : none PriorityAdjustment : @{PriorityAdjustmentOperator=‘+’; PriorityAdjustmentValue=0} Provisioned : 536870912000 Qos : Serial : 81F096D1C1642A69025A4682 Space : @{DataReduction=1; Snapshots=0; ThinProvisioning=1; TotalPhysical=0; TotalProvisioned=536870912000; TotalReduction=1; TotalUsed=0; Unique=0; UsedProvisioned=536870912000; Virtual=0} TimeRemaining : Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Pod : Priority : 0 PromotionStatus : promoted ProtocolEndpoint : RequestedPromotionState : promoted Source : Subtype : regular VolumeGroup : @{Id=‘cc7bbf54-20b6-bb98-1ce6-62893466ce8d’; Name=‘vg-c4d35063-Data-QoS-9rpck’} Workload : @{Id=‘c4d35063-cc7e-4a34-8a1d-5d2590d40879’; Name=‘Production-SQL-01’; ResourceType=‘workloads’; _Configuration=‘SQL-TempDB’} Id : 589be22c–749c–c22b–70f7–b2e052f1fcf9 Name : vg–c4d35063–Data–QoS–9rpck/vol–c4d35063–SQL–System–0000–rp7q8 ConnectionCount : 0 Created : 8/14/2025 9:59:58 PM Destroyed : False HostEncryptionKeyStatus : none PriorityAdjustment : @{PriorityAdjustmentOperator=‘+’; PriorityAdjustmentValue=0} Provisioned : 2199023255552 Qos : Serial : 81F096D1C1642A69025A4683 Space : @{DataReduction=1; Snapshots=0; ThinProvisioning=1; TotalPhysical=0; TotalProvisioned=2199023255552; TotalReduction=1; TotalUsed=0; Unique=0; UsedProvisioned=2199023255552; Virtual=0} TimeRemaining : Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Pod : Priority : 0 PromotionStatus : promoted ProtocolEndpoint : RequestedPromotionState : promoted Source : Subtype : regular VolumeGroup : @{Id=‘cc7bbf54-20b6-bb98-1ce6-62893466ce8d’; Name=‘vg-c4d35063-Data-QoS-9rpck’} Workload : @{Id=‘c4d35063-cc7e-4a34-8a1d-5d2590d40879’; Name=‘Production-SQL-01’; ResourceType=‘workloads’; _Configuration=‘SQL-System’} |
Perfect! We have our four volumes with the proper naming, sizes, and configuration based on our preset configuration.
Examining Protection Group Configuration
Let’s also check the protection group that was created for this workload. Notice the Workload attribute is populated with the PG’s workload name, allowing us to tie these snapshots back to the source system’s easily. We’ll be using this in an upcoming post where we work with our snapshots globally.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# Get the protection group for the new Workload $PGName = Get–Pfa2ProtectionGroup –Array $FlashArray –Filter “workload.name=’Production-SQL-01′” $PGName Name : pg–c4d35063–Data–Snapshots–ncf79 Id : e5aa9074–1013–2864–8c7b–b228ced1ea6e Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Workload : @{Id=‘c4d35063-cc7e-4a34-8a1d-5d2590d40879’; Name=‘Production-SQL-01’; ResourceType=‘workloads’; _Configuration=‘Data-Snapshots’} Destroyed : False EradicationConfig : @{ManualEradication=‘enabled’} HostCount : 0 HostGroupCount : 0 IsLocal : True Pod : ReplicationSchedule : @{Enabled=False; Frequency=14400000} RetentionLock : unlocked SnapshotSchedule : @{Enabled=True; Frequency=600000} Source : @{Name=‘sn1-x90r2-f06-27’} SourceRetention : @{AllForSec=604800; Days=0; PerDay=0} Space : @{Snapshots=0} TargetCount : 0 TargetRetention : @{AllForSec=86400; Days=7; PerDay=4} TimeRemaining : VolumeCount : 3 |
Notice it has VolumeCount: 3 because the TempDB volume was excluded from snapshots, exactly as we configured in our template.
Let’s look at the snapshots that have been created. We set a snapshot policy of every 10 minutes; this is the first one from that policy.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Get the snapshots for the protection group Get–Pfa2ProtectionGroupSnapshot –Array $FlashArray –Filter “name=’$($PGName.Name)*'” Name : pg–c4d35063–Data–Snapshots–ncf79.1 Id : 7ac90c69–b77e–6da7–5860–05d71aaa2d13 Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Created : 8/14/2025 10:00:30 PM Destroyed : False EradicationConfig : @{ManualEradication=‘enabled’} Pod : Source : @{Id=‘e5aa9074-1013-2864-8c7b-b228ced1ea6e’; Name=‘pg-c4d35063-Data-Snapshots-ncf79’} Space : @{Snapshots=0} Suffix : 1 TimeRemaining : |
Scaling Workload Deployment
One of the most powerful aspects of the Pure Fusion fleet management capability is how easily you can create multiple workloads from a single preset. Once you’ve defined your SQL Server preset, you can rapidly deploy it for any number of SQL Server instances. Here’s where we’re creating several more SQL Server workloads from our preset configuration.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# Create multiple SQL Server Workload instances from the same Preset $SQLInstances = @(“Production-SQL-02”, “DR-SQL-01”, “Test-SQL-01”, “Dev-SQL-01”) foreach ($instance in $SQLInstances) { $workloadParams = @{ Array = $FlashArray Name = $instance PresetNames = @(“fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized”) } New–Pfa2Workload @workloadParams Write–Output “Created Workload for $instance” –ForegroundColor Green } Id : 2c3def74–54ad–458d–8e57–834784dcaacc Name : Production–SQL–02 Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Created : 8/14/2025 10:14:03 PM Destroyed : False Preset : @{Id=‘7d107723-4cb6-4d23-a6f0-09bac54a7ef6’; Name=‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’; Revision=1} Status : ready StatusDetails : {} TimeRemaining : Created Workload for Production–SQL–02 Id : cc53e813–734a–4c36–8870–d73905b77815 Name : DR–SQL–01 Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Created : 8/14/2025 10:13:44 PM Destroyed : False Preset : @{Id=‘7d107723-4cb6-4d23-a6f0-09bac54a7ef6’; Name=‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’; Revision=1} Status : ready StatusDetails : {} TimeRemaining : Created Workload for DR–SQL–01 Id : 31c2ca3f–06fe–4e9c–9e78–76a18678c43c Name : Test–SQL–01 Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Created : 8/14/2025 10:13:50 PM Destroyed : False Preset : @{Id=‘7d107723-4cb6-4d23-a6f0-09bac54a7ef6’; Name=‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’; Revision=1} Status : ready StatusDetails : {} TimeRemaining : Created Workload for Test–SQL–01 Id : 2928e71e–d9f5–49b6–bfca–b4eac82e0e45 Name : Dev–SQL–01 Context : @{Id=‘081f096d-1c16-42a6-9855-92678d705a1c’; Name=‘sn1-x90r2-f06-27’} Created : 8/14/2025 10:13:56 PM Destroyed : False Preset : @{Id=‘7d107723-4cb6-4d23-a6f0-09bac54a7ef6’; Name=‘fsa-lab-fleet1:SQL-Server-MultiDisk-Optimized’; Revision=1} Status : ready StatusDetails : {} TimeRemaining : Created Workload for Dev–SQL–01 |
Summary
In this post, we’ve seen how to:
- Create a SQL Server-optimized workload preset with multiple volume types and snapshot policies
- Deploy a workload instance from this preset
- Examine the created resources (volumes, volume groups, protection groups)
- Manage and monitor these resources across our entire fleet of arrays
- Scale deployments by creating multiple workloads from a single preset
Pure Fusion fleet management capabilities, coupled with the newly released PowerShell SDK2 support introduced in version 2.43.30, provide a platform for defining workload templates once and deploying them consistently across a fleet. This approach enables consistency, implementing best practices and simplifying management of complex application storage requirements.
With this approach, we can ensure that every SQL Server deployment in our environment follows the same best practices for volume layout, performance settings, and data protection, regardless of which array it’s deployed on in our fleet.
What’s Next
This post covered the fundamentals of creating and deploying workload presets with Pure Fusion. In future posts, we’ll explore more advanced fleet management capabilities:
- Cross-array replication: Configure periodic replication between arrays in your fleet for disaster recovery and data mobility.
- Using Pure Fusion for remote command execution: Pure Fusion allows for remote command execution across all objects in your fleet rather than just per array.
- Building a global snapshot catalog: Using tags combined with the fleet-wide scope of Pure Fusion, you can find and consume a snapshot anywhere in your fleet.
- Updating workload presets: Modify existing presets and handle versioning as your requirements evolve.
- Finding configuration skew: Use PowerShell to find configuration skew in your environment.
- Fleet-wide monitoring: Gather performance metrics and capacity data across all arrays from a single control point.
- Advanced placement strategies: Use workload placement recommendations to optimize resource utilization across your fleet.
Stay tuned as we dive deeper into these powerful fleet management capabilities, which help you operate storage infrastructure at scale with confidence and consistency.
Prerequisites
Before following this guide, ensure you have:
- Pure Storage PowerShell SDK 2.43.30 or later (Install-Module PureStoragePowerShellSDK2)
- Access to a Pure Storage® FlashArray system with Pure Fusion enabled and a fleet configured
- Appropriate permissions to create and manage workloads
Additional Resources
For more information about Pure Fusion, visit:
- Pure Storage Support Portal: Get started with documentation on Pure Fusion
- Pure Storage Community: Connect with other Pure Fusion users
- Pure Storage Blog: Search for Pure Fusion-related posts and announcements
Unified Control for All of Your Data
Pure Fusion powers workflows, provisioning, and governance across your entire data estate.






