In common server configurations for VMware ESXi Hosts, the boot device is usually an SD-Card or a USB stick. These devices are cheap, require very low-maintenance and have a long life as long as not much is written to them. One disadvantage of Flash or SD storage devices is, that ESXi scratch locations are not created on them. The reason for this is the potentially limited read/write cycles available. In order to still meet the VMware best practice, this blog post will show how to set a persistent scratch location with PowerCLI.
If the ESXi Server is not able to automatically select a persistent scratch location during startup, a ramdisk at /tmp/scratch/
is created.
![Set persistent scratch location with PowerCLI - ramdisk](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image-4.png)
Note:
In case you have enabled vSAN, an additional ramdisk exists for vSAN Traces.
See also: VMware vSphere 6.5 Host Resources Deep Dive - vSAN STORAGE ARCHITECTURE - ESXi Boot Requirements
Possible persistent scratch locations are:
- The location configured in the
/etc/vmware/locker.conf
configuration file, set by the ScratchConfig.ConfiguredScratchLocation
configuration option, as in this blog post.
- A Fat16 filesystem of at least 4 GB on the Local Boot device.
- A Fat16 filesystem of at least 4 GB on a Local device.
- A VMFS datastore on a local device, in a
.locker/
directory.
It is not a fundamental problem if a ramdisk for scratch is used, but VMware highly recommends that ESXi has a persistent scratch location available for storing temporary data including logs, traces, diagnostic information, and system swap.
Major disadvantages of a ramdisk for scratch:
- Additional host memory is consumed
- No log persistence after reboot or crash (e.g. PSOD)
- Limited system swap capability in case of memory contention
Get current scratch configuration
PowerCLI
1
2
3
4
5
|
# Configured
$VMHost | Get-AdvancedSetting -Name "ScratchConfig.ConfiguredScratchLocation" | ft -Autosize
# Current
$VMHost | Get-AdvancedSetting -Name "ScratchConfig.CurrentScratchLocation" | ft -Autosize
|
![Set persistent scratch location with PowerCLI - current scratch config via PowerCLI](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image-6-1024x214.png)
Even when you have configured the persistent scratch location by datastore name, you will get the volume UUID as a result.
This small PowerCLI function returns a table to identify volume UUIDs:
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
|
function Get-DatastoreIDs {
[CmdletBinding()]
param (
[Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage="ESXi Host")]
[ValidateNotNullorEmpty()]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl] $VmHosts
)
begin{
$MyView = @()
}
process {
foreach ($VmHost in $VmHosts) {
$Ds_View = Get-View (Get-View $Vmhost.ID).ConfigManager.StorageSystem
foreach ($Volume in $Ds_View.FileSystemVolumeInfo.MountInfo) {
if ($Volume.Volume.Type -eq "VMFS") {
$Report = [PSCustomObject] @{
HostName = $VmHost.Name
VolName = $Volume.Volume.Name
VolUUID = $Volume.Volume.Uuid
DiskName = $Volume.Volume.Extent.DiskName
}
$MyView += $Report
}
}
}
}
end{
$MyView
}
}
|
![Set persistent scratch location with PowerCLI - UUIDs](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image-9.png)
vim-cmd
1
2
3
4
5
|
# Configured
vim-cmd hostsvc/advopt/view ScratchConfig.ConfiguredScratchLocation
# Current
vim-cmd hostsvc/advopt/view ScratchConfig.CurrentScratchLocation
|
![Set persistent scratch location with PowerCLI - current scratch config via vim-cmd](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image-5.png)
vSphere Client
![Set persistent scratch location with PowerCLI - current scratch config via vSphere Client](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image-7-1024x235.png)
Set persistent scratch location with PowerCLI
I was faced with the challenge to create a persistent scratch location for a huge number of productive VMware ESXi Hosts. I chose the option of a shared VMFS volume for this environment. So the required steps per host were:
- Enter Maintenance Mode (evacuate VMs)
- Create a host-individual .locker folder on the datastore
- Set persistent scratch location
- Reboot the host and wait until host is up again
- Exit Maintenance Mode
To limit the impact on the environment I wanted to process one host after the other.
PowerCLI Script
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
|
# Parameters
$ClusterName = "cluster01"
$DatastoreName = "scratch00"
# Get Cluster
$Cluster = Get-Cluster -Name $ClusterName
# Disable VM DRS Roles
$Cluster | Get-DrsRule | Set-DrsRule -Enabled:$false
# Disable HA Admissioin Control
$Trash = $Cluster | Set-Cluster -HAAdmissionControlEnabled:$false -Confirm:$False
foreach ($VMHost in $($Cluster | Get-VMHost )) {
$Shortname = ($VMHost | Get-VMHostNetwork).HostName
$Datastore = $VMhost | Get-Datastore -Name $DatastoreName
if ($Datastore){
$DatastoreDriveName = "HostStore_" + $Shortname
$Datastore | New-DatastoreDrive -Name $DatastoreDriveName | Out-Null
$Trash = New-Item -Path $($DatastoreDriveName + ":\.locker-$Shortname") -ItemType Directory -Confirm:$false -Force
Remove-PSDrive -Name $DatastoreDriveName
"Folder '/vmfs/volumes/$($Datastore.Name)/.locker-$Shortname' created"
$Trash = $VMHost | Get-AdvancedSetting -Name "ScratchConfig.ConfiguredScratchLocation" | Set-AdvancedSetting -Value "/vmfs/volumes/$($Datastore.Name)/.locker-$Shortname" -Confirm:$false
$Trash = $VMHost | Set-VMHost -State Maintenance -Evacuate -Confirm:$false
"$($VMHost.Name) entered Maintenance Mode"
$Trash = $VMHost | Restart-VMHost -Confirm:$false
"$($VMHost.Name) is Restarting"
do {
Start-Sleep 5
$ServerState = (Get-VMHost $VMHost.Name).ConnectionState
}
while ($ServerState -ne "NotResponding")
"$($VMHost.Name) is Down"
# Wait for server to reboot
do {
Start-Sleep 5
$ServerState = (Get-VMHost $VMHost.Name).ConnectionState
}
while ($ServerState -ne "Maintenance")
"$($VMHost.Name) is Up"
$Trash = $VMHost | Set-VMHost -State Connected -Confirm:$false
"$($VMHost.Name) exited Maintenance Mode"
}
else{ throw "No Datastore Found"}
}
$Cluster | Get-DrsRule | Set-DrsRule -Enabled:$true -ErrorAction SilentlyContinue
$Trash = $Cluster | Set-Cluster -HAAdmissionControlEnabled:$true -Confirm:$False
|
In addition to the configuration of the persistent scratch location, the script also prepares the Cluster for efficient host maintenance (DRS Rules, HA Admission Control).
![Set persistent scratch location with PowerCLI](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image.png)
After the VMware ESXi Host hat successfully restarted, the scratch location folder structure should be automatically created:
![Set persistent scratch location with PowerCLI - scratch location folder structure](/2020/01/14/set-persistent-scratch-location-with-powercli/images/image-3.png)
Metro Storage Cluster and shared scratch volume
This script is designed to set a single datastore as a persistent scratch location with PowerCLI, which means one datastore per vSphere cluster or the whole vSphere datacenter. In case you run a VMware vSphere Metro Storage Cluster setup you probably want to choose a datastore per site.
This snippet shows an example of choosing the datastore by vSphere Tag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
$DatastoreName_DC1 = "Scratch_DC1"
$TagCategory = Get-TagCategory -Name "Location"
foreach ($VMHost in $($Cluster | Get-VMHost )) {
$Shortname = ($VMHost | Get-VMHostNetwork).HostName
$HostLocation = $VMhost | Get-TagAssignment -Category $TagCategory
if ($HostLocation.Tag -match "DC1") {
"$($VMHost.Name) is in DC1"
$Datastore = $VMhost | Get-Datastore -Name $DatastoreName_DC1
}
if ($Datastore){
...
}
}
|
References: