Configuring ESXi for iSCSI Storage Using PowerCLI
Configuring host VMKernel adapters for iSCSI can be a time consuming process. PowerCLI can take away a lot if not all of the effort.
Below is an example of using PowerCLI to create a Standard Virtual Switch (vSS), configure a VMKernel adapter, set the VLAN, enable the software iSCSI adapter (if that’s what you are using), bind it to the required network adapter and finally, add a dynamic Discovery target and rescanning the HBA’s.
This is based on targeting a single host at a time and re-running it with the paramaters for each host.
#Load PowerCLI Modules
Import-module VMware.PowerCLI
#Variables
#vCenter or Host to Connect to
$vCenter = "smt-lab-vcsa-01.smt-lab.local"
#ESX Host to target
$ESXHost = Get-VMHost "smt-lab-esx-01.smt-lab.local"
#Name of the iSCSI Switch
$iSCSISwitchName = "vSS_Storage_iSCSI"
#vmnic to be used for iSCSI Switch
$iSCSISwitchNIC = "vmnic2"
#MTU size
$MTU = "9000"
#Name of the Portgroup for the VMKernel Adapter
$iSCSIVMKPortGroupName = "vSS_VMK_iSCSI_A"
#iSCSI VMK IP
$iSCSIIP = "10.200.33.50"
#iSCSI VMK SubnetMask
$iSCSISubnetMask = "255.255.255.0"
#iSCSI VMK VLAN ID
$VLANID = "300"
#iSCSI Portal Target
$Target = "10.200.33.1:3260"
#Connect to vCenter
Connect-VIServer $vCenter -Credential (Get-Credential) -Force
#New Standard Switch for iSCSI
$NewSwitch = New-VirtualSwitch -VMHost $ESXHost -Name $iSCSISwitchName -Nic $iSCSISwitchNIC -Mtu $MTU
$NewPortGroup = New-VMHostNetworkAdapter -VMhost $ESXHost -PortGroup $iSCSIVMKPortGroupName -VirtualSwitch $NewSwitch -IP $iSCSIIP -SubnetMask $iSCSISubnetMask -Mtu $MTU
Set-VirtualPortGroup -VirtualPortGroup (Get-virtualPortGroup -VMhost $ESXHost | Where {$_.Name -eq $iSCSIVMKPortGroupName}) -VLanId $VLANID
#Enable Software iSCSI Adapter
Get-VMHostStorage -VMHost $ESXHost | Set-VMHostStorage -SoftwareIScsiEnabled $True
#Bind the iSCSI VMKernel Adapter to Software iSCSI Adapter (credit to Luc Dekens for this)
$esxcli = Get-EsxCli -V2 -VMHost $ESXHost
$bind = @{
adapter = ($iscsiHBA = $ESXHost | Get-VMHostHba -Type iScsi | Where {$_.Model -eq "iSCSI Software Adapter"}).Device
force = $true
nic = $NewPortGroup.Name
}
$esxcli.iscsi.networkportal.add.Invoke($bind)
#Add Dynamic Discovery Target
$ESXHost | Get-VMHostHba $iscsiHBA | New-IScsiHbaTarget -Address $Target
#Rescan Hba
Get-VMHostStorage -VMHost $ESXHost -RescanAllHba
The results –





Something you may also want to do is set the Path Selection Policy (PSP) to the commonly used; ‘Round Robin’. The first command will provide a list of attached storage, showing you the CanonicalName (which is what you need for the second command), the current Multipathing Policy and the size of the storage device.
Identify the device you wish to set the pathing policy on and substitute the Canonical Name (naa.xxxx) into the second command.
#Get storage
$esxhost | Get-ScsiLun -LunType disk | Select CanonicalName,MultipathPolicy, CapacityGB
#Set Path Selection Policy (PSP)
$esxhost | Get-ScsiLun -LunType disk -CanonicalName naa.6589cfc0000004ac4d8f1fb0d7d02184 | Set-ScsiLun -MultipathPolicy "RoundRobin"

You could of course take this further by importing all the data required for multiple hosts using an array, whether as a a manually created array in PowerShell, or by importing a csv or txt file to enable you to configure numerous hosts at once by making use of a ForEach loop.
Now, if you are using Virtual Distributed Switches (vDS), here is an alternative (I have assumed you already have an operational vDS in place).
#Load PowerCLI Modules
Import-module VMware.PowerCLI
#Variables
#vCenter or Host to Connect to
$vCenter = "smt-lab-vcsa-01.smt-lab.local"
#ESX Host to target
$ESXHost = Get-VMHost "smt-lab-esx-02.smt-lab.local"
#Name of the vDS
$iSCSISwitchName = "smt-lab-dc01_vDS_01"
#Name of the Portgroup for the VMKernel Adapter
$iSCSIVMKPortGroupName = "smt-lab-dc01_vDS_VMK_iSCSI_B"
#MTU size
$MTU = "9000"
#iSCSI VMK IP
$iSCSIIP = "10.200.34.51"
#iSCSI VMK SubnetMask
$iSCSISubnetMask = "255.255.255.0"
#iSCSI VMK VLAN ID
$VLANID = "301"
#iSCSI Portal Target
$Target = "10.200.34.1:3260"
Connect-VIServer $vCenter -Credential (Get-Credential) -Force
#New VMKernel Adapter on vDS
$NewPortGroup = New-VMHostNetworkAdapter -VMhost $ESXHost -PortGroup $iSCSIVMKPortGroupName -VirtualSwitch $iSCSISwitchName -IP $iSCSIIP -SubnetMask $iSCSISubnetMask -Mtu $MTU
Set-VDPortGroup -VDPortgroup (Get-VDPortGroup | Where {$_.Name -eq $iSCSIVMKPortGroupName}) -VLanId $VLANID
#Bind iSCSI VMKernel Adapter to Software iSCSI Adapter (credit to Luc Dekens for this)
$esxcli = Get-EsxCli -V2 -VMHost $ESXHost
$bind = @{
adapter = ($iscsiHBA = $ESXHost | Get-VMHostHba -Type iScsi | Where {$_.Model -eq "iSCSI Software Adapter"}).Device
force = $true
nic = $NewPortGroup.Name
}
$esxcli.iscsi.networkportal.add.Invoke($bind)
#Add Dynamic Discovery Target
$ESXHost | Get-VMHostHba $iscsiHBA | New-IScsiHbaTarget -Address $Target
#Rescan Hba
Get-VMHostStorage -VMHost $ESXHost -RescanAllHba
A slight change to the cmdlts used; PortGroup > VDPortGroup.
Here are the results –




There are now two paths to my iSCSI device, one via a Standard Switch (vSS) and one via a Distributed Switch (vDS) across two subnets.

Hope this has been helpful. It has saved me plenty of time throughout the countless builds and tear downs of my VMware home lab.
Thanks