Ansible has some great modules for VMware vCenter (especially in 2.5), but none for managing standalone ESXi hosts. There are many cases when full vCenter infrastructure is not required (and web-based Host UI is quite enough for administrative tasks).
Modules, roles and playbooks presented here allow to manageme standalone ESXi hosts (although hosts under vCenter are ok too) with SSH connection, usually with transparent key-based authentication.
- role to configure ESXi host (
roles/hostconf_esxi
) - playbooks to deploy new VM on ESXi host (in
vm_deploy/
)- by uploading (template) VM from some other host (
upload_clone
) - or by cloning local VM (
clone_local
)
- by uploading (template) VM from some other host (
- modules used by role and deployment playbook
- to gather VM facts from ESXi host (
esxi_vm_info
) - to manage autostart of VMs (
esxi_autostart
) - to install or update custom VIBs (
esxi_vib
)
- to gather VM facts from ESXi host (
- some helper filter plugins to simplify working with ESXi shell commands output
split
: split string into a listtodict
: convert a list of records into a dictionary, using specified field as a key
- example playbook to update ESXi host with offline bundle (
update_esxi.yaml
) - helper script to get vault pass from macOs keychain (
get_vault_pass.esxi.sh
)
This role takes care of many aspects of standalone ESXi server configuration like
- ESXi license key (if set)
- host name, DNS servers
- NTP servers, enable NTP client, set time
- users
- create missed, remove extra ones
- assign random passwords to new users (and store in
creds/
) - make SSH keys persist across reboots
- grant DCUI rights
- portgroups on vSwitch0
- create missed, remove extra
- assign specified tags
- block BPDUs from guests
- create vMotion interface (off by default, see
create_vmotion_iface
in role defaults) - datastores
- partition specified devices if required
- create missed datastores
- rename empty ones with wrong names
- autostart for specified VMs (optionally disabling it for all others)
- logging to syslog server; lower
vpxa
and other noisy components logging level from defaultverbose
toinfo
- certificates for Host UI and SSL communication (if present)
- install or update specified VIBs
Only requirement is correctly configured network (especially uplinks) and reachability over ssh with root password. ESXi must be reasonably recent (6.0+, although some newer versions of 5.5 have working python 2.7 too).
ansible.cfg
: specify remote user, inventory path etc; specify vault pass method if using one for certificate private key encryption.group_vars/all.yaml
: specify global parameters like NTP and syslog servers theregroup_vars/<site>.yaml
: set specific params for each<site>
in inventoryhost_vars/<host>.yaml
: override global and group values with e.g. host-specific users list or datastore config- put public keys for users into
roles/hostconf-esxi/files/id_rsa.<user>@<keyname>.pub
for referencing them later in user listhost_vars
orgroup_vars
-
serial number to assign, usually set in global
group_vars/all.yaml
; does not get changed if not setesxi_serial: "XXXXX-XXXXX-XXXX-XXXXX-XXXXX"
-
general network environment, usually set in
group_vars/<site>.yaml
dns_domain: "m0.maxidom.ru" name_servers: - 10.0.128.1 - 10.0.128.2 ntp_servers: - 10.1.131.1 - 10.1.131.2 # defaults: "log." + dns_domain # syslog_host: log.m0.maxidom.ru
-
user configuration: those users are created (if not present) and assigned random passwords (printed out and stored in
creds/<user>.<host>.pass.out
), have ssh keys assigned to them (persistently) and restricted to specified hosts (plus global list inpermit_ssh_from
), are granted administrative rights and access to the consoleesxi_local_users: "<user>": desc: "<user description>"" pubkeys: - name: "<keyname>" hosts: "1.2.3.4,some-host.com"
users that are not in this list (except root) are removed from host, so be careful.
-
network configuration: portgroups list in
esxi_portgroups
are exhaustive, i.e. those and only those portgroups (with exactly matched tags) should be present oh host after playbook run (missed are created, wrong names are fixed, extra are removed if not used)esxi_portgroups: all-tagged: { tag: 4095 } adm-srv: { tag: 210 } srv-netinf: { tag: 131 } pvt-netinf: { tag: 199 }
-
datastore configuration: datastores would be created on those devices if missed and
create_datastores
is set; existent datastores would be renamed to match specified name ifrename_datastores
is set and they are emptylocal_datastores: "vmhba0:C0:T0:L1": "nest-test-sys" "vmhba0:C0:T0:L2": "nest-test-apps"
-
VIBs to install or update (like latest esx-ui host client fling)
vib_list: - name: esx-ui url: "http://www-distr.m1.maxidom.ru/suse_distr/iso/esxui-signed-6360286.vib"
-
autostart configuration: listed VMs are added to esxi auto-start list, in specified order if order is present, else just randomly; if
autostart_only_listed
is set, only those VMs will be autostarted on host with extra VMs removed from autostartvms_to_autostart: eagle-m0: order: 1 hawk-m0: order: 2 falcon-u1:
- add host into corresponding group in
inventory.esxi
- set custom certificate for host
- put certificate into
files/<host>.rui.crt
, - put key into
files/<host>.key.vault
(and encrypt vault)
- put certificate into
- override any group vars in
host_vars/hostname.yaml
For the initial config only the "root" user is available, so run playbook like this:
ansible-playbook all.yaml -l new-host -u root -k --tags hostconf --diff
After local users are configured (and ssh key auth is in place), just use remote_user
from ansible.cfg
and run it like
ansible-playbook all.yaml -l host-or-group --tags hostconf --diff
- only one vSwitch (
vSwitch0
) is currently supported - password policy checks (introduced in 6.5) are turned off to allow for truly random passwords (those are sometimes miss one of the character classes).
There are two playbooks in vm_deploy/
subdir
- first (
upload_clone
) is for copying template VM from source host to new target - second (
clone_local
) is for making custom clones of local template VM
See playbook source and comments at the top for a list if parameters, some are mentioned below.
- ansible 2.3+ (2.2 "replace" is not compatible with python 3 on ESXi)
- local modules
netaddr
anddnspython
- clone source must be powered off
- for VM customization like setting IPs etc, ovfconf must be configured on clone source VM (to take advantage of passing OVF params to VM)
This playbooks is mostly used to upload initial "template" VM to target host (to be, in turn, template for further local cloning). Source of template VM is usually at another ESXi host, and there are 3 modes of copy:
- direct "pull" SCP: destination host is SCP'ing VM files from source; authorization is key-based with agent forwarding, so both hosts must have current Ansible user configured and destination host must be in allowed hosts list for this user
- direct "push" SCP: source host is SCP'ing VM files to destination, exactly as above (if e.g. firewall is more permissive in that direction)
- slow copy via current hosts: download VM files from source to temp dir first (with
Ansible "copy" module; rather fast if file is already staged there), then upload it
to destination hosts (must have enough space in "tmp" for that, see
ansible-deploy.cfg
for tmp configuration)
There are no options for customization there, only for src and dst params like datastore, and usual invocation looks like
ansible-playbook upload_clone.yaml -l nest2-k1 \
-e 'src_vm_name=phoenix11-1-k1 src_vm_vol=nest1-sys src_vm_server=nest1-k1' \
-e 'dst_vm_name=phoenix11-2-k1' \
-e 'direct_scp=true'
This playbook is used to produce new VM from local template source, optionally customize parameters like datastore, network and disks, and optionally power it on. Invocation to create new machine (with additional network card and disk) and power it on looks like
ansible-playbook clone_local.yaml -l nest1-mf1 -e 'vm_name=files-mf1-vm \
vm_desc="samba file server" vm_net2=srv-smb vm_disk2=100G' \
-e 'do_power_on=true'
To simplify cloning, it is better to
- specify local clone source vm in ESXi host
host_vars
(assrc_vm_name
) - already have new machine's name in DNS (so IP is determined automatically)
- have ovfconf configured in source (template) VM, as OVF is used to pass network config there (DHCP server would be ok too)
Modules (library/
) are documented with usual Ansible docs. They could be used
stand-alone, like
ansible -m esxi_vm_list -a 'get_power_state=true get_start_state=true' esxi-name
to get a list of host VMs together with autostart state and current run state