Since I'm not running vCenter in my 2 ESXi 7.x node homelab, I'm missing out on some features. Actually the only one I really miss the ability to clone machines. I use this a lot when building new K8s clusters for testing out stuff.

But there is a solution for that of course, lots of articles written about that. In fact a little too much, it took me a while to find the best solution for my taste.
Eventually I settled for a script created by Luc Dekens from here. But that was written in 2013 for an older version of ESXi. So I altered it a little bit to avoid it throwing errors, but not much:

function Clone-MasterVM {
.SYNOPSIS  Clone a VM without using vCenter   
.DESCRIPTION The function will clone a VM to a
  specified datastore. Optionally the new VM will be
  registered and powered on.
.NOTES  Author:  Luc Dekens  
  The name of the VM that will be cloned
  The name of the VM that is cloned
.PARAMETER DatastoreName
  The name of the datastore where the clone will be stored
  Register the clone on the vSphere server
  Power on the clone. Can only be used when the Register switch is selected.
  $vm = Get-VM -Name $MasterName
  if($vm.ExtensionData.Snapshot -or $vm.PowerState -eq "PoweredOn"){
    Write-Error "The VM should be powered off and have no snapshots"
  $si = Get-View ServiceInstance
  $vdkMgr = Get-View $si.Content.virtualDiskManager
  $fileMgr = Get-View $si.Content.FileManager
  $dcMoRef = (Get-Datacenter -VM $vm).ExtensionData.MoRef
  $srcDSName = $vm.ExtensionData.Config.Files.VmPathName.Split(']')[0].Trim('[')
  $srcDS = Get-Datastore -Name $srcDSName
  $srcDSBrowser = Get-View $srcDS.ExtensionData.Browser
  $tgtDS = Get-Datastore -Name $DatastoreName
  $spec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
  # Create folder for new VM
  $fileMgr.MakeDirectory("[$DatastoreName] $CloneName",$dcMoRef,$false)
  # Copy vDisks
  $spec.Query = New-Object VMware.Vim.VmDiskFileQuery
  $qResult = $srcDSBrowser.SearchDatastore("[$srcDSName] $MasterName",$spec)
    $qResult.File | %{
      $srcPath = "$($qResult.FolderPath)/$($_.Path)"
      $tgtPath = $srcPath.Replace($srcDSName,$DatastoreName).Replace($MasterName,$CloneName)
      $hd = $vm.ExtensionData.Config.Hardware.Device |
        where {$_ -is [VMware.Vim.VirtualDisk] -and $_.Backing.FileName -eq $srcPath}
      $controller = $vm.ExtensionData.Config.Hardware.Device |
        where {$_.Key -eq $hd.ControllerKey}
      $vDiskSpec = New-Object VMware.Vim.VirtualDiskSpec
      $vDiskSpec.adapterType = &{
        if($controller -is [VMware.Vim.VirtualLsiLogicController] -or
          $controller -is [VMware.Vim.VirtualLsiLogicSASController] -or
          $controller -is [VMware.Vim.ParaVirtualSCSIController]){
        elseif($controller -is [VMware.Vim.VirtualBusLogicController]){
      $vDiskSpec.diskType = &{
  # Copy other VM files
  $dsDestination = New-PSDrive -Location $tgtDS -Name dest -PSProvider VimDatastore -Root '\'
  Get-ChildItem -Path "vmstore:\ha-datacenter\$srcDSName\$MasterName" |
  where {"vmdk","log","vmsd" -notcontains $_.Name.Split('.')[1]} | %{
  # The copy is done in a foreach loop, to bypass a Copy-DatastoreItem bug with pipeline
  Copy-DatastoreItem -Item $_ `
     -Destination ("dest:\$CloneName\" + $_.Name.Replace($MasterName,$CloneName)) -Confirm:$false
  # Update VMX file
  Copy-DatastoreItem -Item "dest:\$CloneName\$($CloneName).vmx" -Destination $env:Temp\t.vmx
  $text = Get-Content -Path $env:Temp\t.vmx | %{$_.Replace($MasterName,$CloneName)}
  $text | Set-Content -Path $env:Temp\t.vmx
  Copy-DatastoreItem -Item $env:Temp\t.vmx -Destination "dest:\$CloneName\$($CloneName).vmx" -Confirm:$false
    New-VM -VMFilePath "[$DatastoreName] $CloneName\$($CloneName).vmx" | Out-Null
      Start-VM -VM $CloneName -ErrorAction SilentlyContinue
      Get-VMQuestion -VM $CloneName | Set-VMQuestion -DefaultOption -Confirm:$false
  Remove-PSDrive -Name dest -Confirm:$false

Connect-VIServer -Server nuc02.singel.home
Clone-MasterVM -MasterName source-vm -CloneName new-vm -DatastoreName SSD -Register

Initially I was using this script to clone VM's that I created with vCenter. This is a bad idea, vCenter alters the .vmx file in such a way that the MAC address will be cloned also. In that case change the .vmx file or make a new VM in ESXi and you will be fine.

Note: you need the PowerCli tools for this to work, install with:

Install-Module -Name VMware.PowerCLI -Scope CurrentUser