Bulk NTP Configuration for vCenter'd ESXi hosts

Problem

You've got a vCenter environment with many ESXi hosts, and for some reason they've not been set up correctly to the point where the time differences are massive across the board, no consistency etc etc.

We can fix that with NTP! But, it's a proper nightmare having to configure each host individually. So, how do we configure the entire lot of ESXi hosts to use a particular NTP server?

Solution

I've managed to grab some powershell which can do what we're looking for:

  • Adds an NTP server
  • Opens the firewall to allow NTP out
  • Starts the NTP service
  • Sets the NTP service to automatic on ESXi bootup
  • Sets the current time on all ESXi hosts to current

Add NTP servers to hosts (replace servername)

Get-VMHost | Add-VmHostNtpServer -NtpServer servername  

Allow NTP queries outbound through the firewall

Get-VMHost | Get-VMHostFirewallException | where {$_.Name -eq "NTP client"} | Set-VMHostFirewallException -Enabled:$true  

Start NTP client service and set to automatic

Get-VMHost | Get-VmHostService | Where-Object {$_.key -eq "ntpd"} | Start-VMHostService  
Get-VMHost | Get-VmHostService | Where-Object {$_.key -eq "ntpd"} | Set-VMHostService -policy "automatic"  

Now we need to sync the time manually across all the hosts:

$t = Get-Date
$dst = Get-VMHost | %{ Get-View $_.ExtensionData.ConfigManager.DateTimeSystem } 
$dst.UpdateDateTime((Get-Date($t.ToUniversalTime()) -format u))

Entire Lot (slightly more efficient as well by saving the hosts to a variable):

$hosts = Get-VMHost
$hosts | Add-VmHostNtpServer -NtpServer servername
$hosts | Get-VMHostFirewallException | where {$_.Name -eq "NTP client"} | Set-VMHostFirewallException -Enabled:$true
$hosts | Get-VmHostService | Where-Object {$_.key -eq "ntpd"} | Start-VMHostService
$hosts | Get-VmHostService | Where-Object {$_.key -eq "ntpd"} | Set-VMHostService -policy "automatic"
$t = Get-Date
$dst = $hosts | %{ Get-View $_.ExtensionData.ConfigManager.DateTimeSystem }
$dst.UpdateDateTime((Get-Date($t.ToUniversalTime()) -format u))