PowerEdge: ESXi Automated Deployment

== This entry is a work in progress ==

 

This post will describe how to automatically configure and image a clean PowerEdge (or generic vendor) for ESXi deployment:

Step 1: Automation Process

 

Step 2: DHCP

DHCP will be used to perform the following activities:

  • Initially provision the iDRAC with a (fixed) DHCP IP address
  • DHCP process is expanded to force system to boot an ESXi installation imag

Install DHCP Service on the automation host:

# mkdir /data/binaries/staging

Configure a basic DHCP file:

# scp <image-file> root@vrslcm.local.domain:/data/binaries/staging

Step 3: Ansible

Ansible will be used to configure basic iDRAC parameters on the host:

ddd

Step 4: Kickstart Web Server

Generate a new root password, of course we will one-way encrypt this so its unreadable two options for this:

Option 1 – Using OpenSSL which returns a SHA512 password:

# openssl passwd -6 <password>

Option 2 – Using Python you can use the following code:

import hashlib

def hash_password(password):
    # Convert the password to bytes and create SHA-512 hash
    sha512_hash = hashlib.sha512(password.encode()).hexdigest()
    return sha512_hash

# Example usage
password = input("Enter password to hash: ")
hashed_password = hash_password(password)
print(f"SHA-512 hash: {hashed_password}")

Generate the kickstart file /var/lib/www/ks.cfg this file will be generic for all nodes deployed, specific node configuration items are defined in sub-configuration files:

# Sample ks.cfg for automated ESXi deployment
# Accept the VMware EULA
vmaccepteula

# Set the root password
rootpw VMware123!

# Install on the first disk, overwrite any existing VMFS datastore
install --firstdisk --overwritevmfs

# Configure network (temporary DHCP for fetching config)
network --bootproto=dhcp

# Keyboard layout
keyboard US

# Reboot after installation
reboot

# Post-installation script to fetch and apply host-specific configuration
%post --interpreter=busybox
# Get the hostname (set during PXE boot or manually)
HOSTNAME=$(esxcli system hostname get | grep "Host Name" | awk '{print $3}')

# Fetch host-specific configuration from web server
wget http://192.168.1.100/configs/${HOSTNAME}.cfg -O /tmp/host.cfg

# Source the configuration file
if [! -f /tmp/host.cfg ]; then
    echo "Failed to fetch config file for $HOSTNAME" > /var/log/config_error.log
    exit 1
fi
. /tmp/host.cfg

# Create a new standard vSwitch (vSwitch0) if it doesn't exist
esxcli network vswitch standard add --vswitch-name=vSwitch0

# Add the specific Host Management NIC to the vSwitch0
esxcli network vswitch standard uplink add --uplink-name=$VMKERNEL_IFACE --vswitch-name=vSwitch0
# Apply vmkernel IP configuration for vmk0 
esxcli network vswitch standard portgroup add --portgroup-name=Management --vswitch-name=vSwitch0
esxcli network vswitch standard portgroup set --portgroup-name=Management --vlan-id=$VMKERNEL_VLAN

# assign vmk0 to the Management PortGroup
esxcli network ip interface add --interface-name=vmk0 --portgroup-name=Management

# set static IP for vmk0
esxcli network ip interface ipv4 set -i vmk0 -t static -I $VMKERNEL_IP -N $VMKERNEL_MASK -g $VMKERNEL_GW 

# Configure DNS (optional, can be in host.cfg if needed) 
esxcli network ip dns server add --server=8.8.8.8 
esxcli network ip dns server add --server=4.4.4.4 

# Configure DNS search domain 
esxcli network ip dns search add --domain=example.com 

# Configure NTP servers 
echo "server 0.pool.ntp.org" >> /etc/ntp.conf 
echo "server 1.pool.ntp.org" >> /etc/ntp.conf 
/sbin/chkconfig ntpd on 

# Set hostname 
esxcli system hostname set --fqdn=$HOSTNAME 

# Clean up 
rm /tmp/host.cfg 

# Enable and start SSH 
vim-cmd hostsvc/enable_ssh 
vim-cmd hostsvc/start_ssh 

# Make sure ESXi shell is disabled (Audit & Compliance) 
vim-cmd hostsvc/disable_esx_shell 
vim-cmd hostsvc/disable_esx_shell 

# Disable IPv6 
esxcli network ip set --ipv6-enabled=false 

# Restart network services to apply changes 
/etc/init.d/hostd restart 
/etc/init.d/vpxa restart

Create unique files for each ESXi host. For example,  create for host1 a file /var/lib/www/host1.cfg this file will contain the basic configuration parameters for this host :

# Configuration for esxi-host1
VMKERNEL_IFACE=vmnic0
VMKERNEL_VLAN=800
VMKERNEL_IP=192.168.10.10
VMKERNEL_MASK=255.255.255.0
VMKERNEL_GW=192.168.1.1

Step 5: TFTP Service

Install TFTP package:

# sudo apt install -y tftpd-hpa

Configure the tftp repository and configuration settings in file /etc/default/tftpd-hpa this file will be generic for all nodes deployed, specific node configuration items are defined in sub-configuration files:

# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure --verbosity 4"

Restart the service after configuraiton change:

# systemctl enable tftpd-hpa
# systemctl restart tftpd-hpa

 

Step 5: ESXi Image

Download the ESXi image and extract it to the tftp location

# mount -o loop ESXi-8.0u3.iso /mnt
# mkdir /var/lib/tftpboot/ESXi-8.0u3
# rsync -a /mnt/ /var/lib/tftpboot/ESXi-8.0u3/

Define (copy) the boot files for legacy BIOS:

# cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
# cp /usr/share/syslinux/menu.c32 /var/lib/tftpboot/

Define (copy) the boot files for UEFI BIOS:

# cp /var/lib/tftpboot/ESXi-8.0u3/efi/boot/bootx64.efi /var/lib/tftpboot/
# cp /var/lib/tftpboot/ESXi-8.0u3/efi/boot/cryto64.efi /var/lib/tftpboot/

Create a PXELINUX directory:

# mkdir -p /var/lib/tftpboot/pxelinux.cfg

Edit the PXELINUX default configuration file /var/lib/tftpboot/pxelinux.cfg/default:

DEFAULT menu.c32
MENU TITLE ESXi 8.0 Boot Menu
LABEL install
  KERNEL ESXi-8.0u3/mboot.c32
  APPEND -c ESXi-8.0u3/boot.cfg

Modify  the /var/lib/tftpboot/ESXi-8.0u3/boot.cfg file to include some details and also a kickstart location:

prefix=ESXi-8.0u3
kernelopts=ks:http://<your-server-ip>/ks.cfg