Ansible framework for managing Ubuntu virtual machines on VMware vCenter
- Comprehensive lifecycle management (provision, rename, re-align, decommission)
- Hot-scalable virtual hardware resources
- Out-of-band provisioning & alignment, vCenter API in place of SSH
- Burying: cache scanned state in vCenter custom attributes
- Template-based provisionning includes admins, SSH keys
- Feature-rich YAML inventory format, with linting
- Fine-grained automation features control, with
auto/*tags - State auditing, inventory canonicalization
- Tag-based in-house/galaxy roles management
Scale virtual hardware resources without rebooting:
- CPU (number of cores)
- RAM (MB)
- Root FS (MB)
- Swap (MB)
- HW flags: power state, hotplug ram/cpu, reserved ram
- vCenter references: datacenter, cluster, folder, datastore, network
- Network config using Netplan
- Admin users, including SSH keys
- Tag-based roles assignation, via
apps/*andgalaxy/*tags - Ansible Galaxy supported, with automatic updates
- Included WUcenter credentials wizard helps creating a vaulted credentials bundle
- Included WUcenter player reads the master vault password interactively, or either as a file or an env var
- VMware vCenter cluster
- version >=6.7U3
- Ansible control host
- Python 3
- Ansible version >=2.9.6
- tested on Ubuntu bionic
- Ubuntu bionic (18.04) VM template (use wucenter-packer)
- static IP
- password-less sudoer user
- configured APT
- pre-installed Python 3 & VMware Guest Tools
- Limitation: Ansible check-mode is not supported
These install instructions are here for experimented users, detailed instructions follow.
First install Ansible for Python3:
sudo apt install python3-pip
sudo -H pip3 install --no-cache-dir --upgrade pip ansible
Then create WUcenter workspace:
mkdir workspace
cd workspace
ansible-galaxy collection install wucenter.wucenter -p ./
ansible_collections/wucenter/wucenter/wucenter_setup.sh
ansible_collections/wucenter/wucenter/wucenter_creds.sh
mkdir inventory roles
touch inventory/users.yml inventory/vms.ymlSee sister project wucenter-packer to build your VM template.
- Install requirements
WUcenter is tested on Ubuntu bionic with Ansible for Python 3.
Once you installed the python3-pip package you can install Ansible with pip3:
sudo -H pip3 install --no-cache-dir ansible
- Install WUcenter software
- either, pull last tagged version from Ansible Galaxy into existing Ansible workspace
cd $EXISTING_WORKSPACE
ansible-galaxy collection install wucenter.wucenter -f -p ./- or, clone current master from Github as a new Ansible workspace
cd $SOMEWHERE
git clone https://github.com/wucenter/wucenter $NEW_WORKSPACE_NAME- finally, run WUcenter installation script
ansible_collections/wucenter/wucenter/wucenter_setup.sh- Configure WUcenter credentials
- either, use WUcenter Vaulted credentials wizard
ansible_collections/wucenter/wucenter/wucenter_creds.sh- or manually edit plain-text files, see
samples/credentials/*.ymland read Credentials Spec below
- Configure WUcenter inventory
WUcenter requires 2 files, check samples/inventory/.
inventory/vms.ymlfor defining virtual machines, theirs specs & their rolesinventory/users.ymladmin users directory
- Optional: roles
-
copy your custom Ansible roles to
roles/ -
configure
roles/requirements.ymlto automatically install pristine roles toroles_galaxy/
Once wucenter.wucenter collection has been deployed to ./ansible_collections directory, run wucenter_setup.sh to setup your Ansible workspace with WUcenter:
- Install WUcenter player
- Generate WUcenter playbooks
- Install/update Python librairies (pip3)
- Install/update Ansible collections/roles
- Setup Ansible configuration (
ansible.cfg)
Workspace layout:
ansible-collections/Ansible collections managed byansible-collections/requirements.ymlansible-collections/wucenter/wucenter/WUcenter softwareansible.cfgWUcenter Ansible defaults, generated bywucenter_setup.shbooks/WUcenter playbooks, generated bywucenter_setup.shcredentials/WUcenter credentials bundle, generated bywucenter_creds.shinventory/users.ymlWUcenter operators directoryinventory/vms.ymlWUcenter virtual machines inventoryroles/Custom Ansible rolesroles_galaxy/Pristine Ansible roles, managed byroles/requirements.yml
Recommended usage is to have credentials/, inventory/ and roles/ symlinked to GIT repos.
All playbooks are meant to be used with the provided playbook player wucenter_player.sh.
All playbooks include a shebang to call the player transparently.
- Ansible setup checking
- Playbook roles syntax checking
- Hosts inventory linting
- Users directory linting
- Remote roles updating
- Single-command run, no need to
cd - Vault password management
- using variable, if
VAULT_PASSenv set - using file, if
credentials/VAULT_PASSfile exists - single interactive password prompt otherwise
- using variable, if
The player accepts the following options:
USAGE: wucenter_player.sh --book PLAYBOOK.yml [OPTIONS] [MORE_OPTIONS]
DESC: Ansible playbook wrapper
MODES:
-P, --book PB Mandatory if not shebang-run
OPTIONS:
-V, --vault Manage vault password
-B, --no-bury Don't write (bury) vCenter cache
-G, --no-dig Don't read (dig up) vCenter cache
-A, --no-auto Bypass all below:
-S, --no-synt Bypass playbook syntax check
-L, --no-lint Bypass inventory lint check
-I, --no-deps Bypass dependencies update
-R, --no-role Bypass additional roles update
MORE_OPTIONS:
See: ansible-playbook --help
It is possible to specify ansible-playbook options after the player's ones:
./scan.yml -A -F -vv --limit localhost,myhostThe above command will scan myhost VM:
- Bypass all additional player features (
-A) - Force full scan, disabling bury cache (
-F) - Pass additional options to
ansible-playbook(-vv --limit localhost,myhost) - Please note that inventory limiting (using
--limitor-l) requireslocalhostinclusion
apply.yml is the main entrypoint, featuring a minimalistic Gitops workflow. It combines the following playbooks:
scan.ymlGather VMs statedecommission.ymlRemove VMsprovision.ymlCreate VMs from templaterename.ymlChange VMs namealign.ymlAlign VMs specsapps.ymlPlay tagged roles
More playbooks are provided:
lint.ymlLint desired state (inventory)lint_full.ymlLint desired state (vCenter)audit.ymlShow VMs specs divergences (desired/scanned/cached)updates.ymlShow available APT updatessetup.ymlInstall WUcenter workspace dependenciesinit.ymlWUcenter internals
Following credentials definitions are required:
- vCenter server admin
- Template password-less sudoer (for provisioning)
robopssudoer (for alignment)opsSSH sudoer (for additional roles)- Private Git repository user (for custom roles, optional)
- Private Docker registry user (for custom roles, optional)
Configuration consists of YAML files in credentials directory (or symlink).
| Main playbooks | vcenter.yml |
template.yml |
robops.yml |
ops.yml |
git.yml |
registry.yml |
vmware.yml |
|---|---|---|---|---|---|---|---|
apply.yml |
β | β | β | β | β | β | |
scan.yml |
β | ||||||
decommission.yml |
β | ||||||
rename.yml |
β | β | |||||
provision.yml |
β | β | |||||
align.yml |
β | β | |||||
apps.yml |
β | β | β | β | |||
| More playbooks | |||||||
lint_full.yml |
β | β | β | β | β | ||
lint.yml |
β | β | β | β | |||
audit.yml |
β | β | |||||
updates.yml |
β | ||||||
init.yml |
β | β | β | β | |||
setup.yml |
Credential files supports Ansible Vault both for full file-vaulting and for YAML key vaulting.
Use the provided interactive wizard to generate a complete credentials bundle or follow the credentials spec to populate your credentials directory.
To interactively populate all required credentials, run from project base directory:
ansible_collections/wucenter/wucenter/wucenter_creds.sh- In
credentials/vcenter.yml:
| vC Credentials | Description |
|---|---|
vcenter_host |
STRING vCenter Host |
vcenter_dc |
STRING vCenter Datacenter Id |
vcenter_user |
STRING vCenter Username |
vcenter_pass |
STRING vCenter Password |
- Full linting uses vmware_vm_inventory dynamic inventory plugin.
This requires an additional configuration file that does not support selective vaulting:
credentials/vmware.yml:
| Plugin Credentials | Description |
|---|---|
plugin |
CONST community.vmware.vmware_vm_inventory |
hostname |
STRING vCenter Host |
username |
STRING vCenter Username |
password |
STRING vCenter Password |
validate_certs |
BOOL vCenter self-signed certificate |
properties |
CONST [config.name, config.uuid, guest.guestId, guest.net] |
- Template password-less sudoer
Used for provisioning: credentials/template.yml
| TPL Credentials | Description |
|---|---|
template_name |
STRING Template vCenter Id |
template_user |
STRING Username, password-less sudoer |
template_pass |
STRING Password |
robopssudoer
Used for alignment: credentials/robops.yml
| VM Credentials | Description |
|---|---|
robops_user |
STRING Username |
robops_pass |
STRING Password |
opsSSH sudoer
Used for additional roles: credentials/ops.yml
| VM Credentials | Description |
|---|---|
ops_user |
STRING Username |
ops_pass |
STRING Password |
ops_sshk |
STRING SSH private key |
- Optional Private GIT cloner
For specific roles: credentials/git.yml
| TPL Credentials | Description |
|---|---|
git_host |
STRING Template vCenter Id |
git_user |
STRING Username |
git_pass |
STRING Password |
- Encrypt vault single variable
ansible-vault encrypt_string --name 'git_pass' 's3(r3t' --vault-password-file credentials/VAULT_PASS- Decrypt vault single variable
ansible localhost -m debug -a var='git_pass' -e '@credentials/git.yml' --vault-password-file credentials/VAULT_PASSVirtual machines inventory is defined by an inventory YAML file in inventory/vms.yml.
This enables multi-level variables overrides. Recommended usage is mapping projects to vCenter folders.
Each VM identified by a unique key, holds the following attributes:
| VM Unique Id | Description |
|---|---|
vm_name |
OPTIONAL STRING Hostname. Defaults to VM_KEY.vm_net_sd |
vm_folder |
OPTIONAL STRING Must start with /. Defaults to / |
| vC Resources | Description |
|---|---|
vm_cluster |
STRING vCenter cluster |
vm_datastore |
STRING vCenter datastore |
vm_network |
STRING vCenter network |
| VM Hardware | Description |
|---|---|
vm_power |
BOOL Power state |
vm_hotplug |
BOOL Hot-scalable CPU/RAM |
vm_ram_reserved |
BOOL Reserve RAM |
vm_ram |
INT Memory (MB) |
vm_cpu |
INT Number of cores |
vm_disk |
INT Root filesystem (MB) |
vm_swap |
INT Swap (MB) |
| VM Network | Description |
|---|---|
vm_net_ip |
IP VM |
vm_net_gw |
IP Gateway |
vm_net_nm |
IP VM Netmask |
vm_net_ns1 |
IP DNS Server 1 |
vm_net_ns2 |
IP DNS Server 2 |
vm_net_sd |
STRING DNS Search Domain |
| VM Mgmt | Description |
|---|---|
vm_auto |
LIST[STRING] See automation tags |
| VM Roles | Description |
|---|---|
vm_roles |
OPTIONAL LIST[STRING] See roles tags |
vm_vars |
OPTIONAL DICT[STRING] See roles tags |
| VM Renaming | Description |
|---|---|
vm_rename |
OPTIONAL STRING New name |
| VM Removal | Description |
|---|---|
state |
OPTIONAL STRING Set to absent for decommissioning |
vm_auto toggles automation features:
auto=auto/allauto/manageauto/provisionauto/decommissionauto/renameauto/rolesauto/folderauto/bury
auto/hwauto/powerauto/cpuauto/ramauto/hwflagsauto/hotplugauto/ram_reserved
auto/dataauto/datastoreauto/disksauto/diskauto/swap
auto/netauto/networkauto/netconfauto/hostnameauto/sshrequiresauto/user
auto/user
vm_roles can specify:
apps/*tags to reference in-house or patched roles fromrolesdirectorygalaxy/*tags to reference pristine 3rd-party roles fromroles_galaxydirectory, those should be declared inroles/requirements.ymlto benefit from automatic installation/update.
Optionally, vm_vars can specify custom variables used by roles. Contained variables will get copied to the root level at runtime.
Alternatively it is possible to define those directly at the root level (hostvars), in this case, defined variables won't get burried to vCenter custom attributes, thus protecting sensitive information.
Users directory is defined by a custom YAML file.
Users directory is necessary to provision & align admin credentials sush as hashed user password or ssh public key.
Users directory can be easily extended for custom roles.
User management is currently limited to two hard-coded groups:
robops, robots, password-less sudoers, NOT AUTHORIZED to connect over SSHops, robots/ops, sudoers, MUST setup SSH key(s) to access VM
| Main playbooks | robops |
ops |
|---|---|---|
apply.yml |
β | β |
scan.yml |
β | |
decommission.yml |
||
rename.yml |
β | |
provision.yml |
β | |
align.yml |
β | |
apps.yml |
β | |
| More playbooks | ||
lint_full.yml |
β | |
lint.yml |
β | |
audit.yml |
β | |
updates.yml |
β | |
init.yml |
||
setup.yml |
- Declare
usersdictionary ininventory/users.yml
users dictionary keys represent the username
Follow the following dictionary format for user attributes:
| User spec | Description |
|---|---|
user_name |
STRING This is the GECOS, the username is the dict key ! |
user_hash |
STRING Hashed password, mkpasswd --method=SHA-512 --stdin |
user_tags |
LIST[STRING] |
user_keys |
LIST[DICT] SSH Keys Specs |
user_state |
STRING OPTIONAL Set to absent to remove user |
user_keysdictionaries attributes:
| Key spec | Description |
|---|---|
ssh_rsa |
STRING SSH RSA public key |
comment |
STRING OPTIONAL |
state |
STRING OPTIONAL Set to absent to remove key |
To generate a RSA key pair:
ssh-keygen -t rsa -b 4096 -a 100 -N '' -f NEW_id_rsa`- Supported
user_tags:
| User tags | Description |
|---|---|
robops |
User for alignment (vCenter API) |
ops |
User for additional roles (SSH) |
- Ansible VMware modules
- Ansible VMware source code (=2.9.9)
- Ansible VMware source code (>=2.10)
- Ansible core filters
- Jinja2 builtin filters
- JMESPath spec (
json_query()) - Python regular expressions
- YAML Block Chomping
- YAML Gotchas
- IP Assignation management
- Build template from Ubuntu OVA with cloud-init intrumentation
- Implement DRS affinities
- Minimal VM healthchecks
- df root_fs
- resolv dns1
- ping gw
- apt update