Infrastructure Automation Lab
Photo Credits: Unsplash, VMWare, Docker, Proxmox, Packer, and Git
I: Source Code Link
Source code for completing all labs is available here
II: Infrastructure Automation Lab
This repo serves as the "answer key" and lesson plan for a 2-day hands-on infrastructure automation lab. The goal of the lab is for students to fully automate the process of deploying a Proxmox VM to VMWare Workstation. This serves two purposes:
- Gives students the ability to "spin up" a testing environment for future automation development and/or testing with PVE
- Teaches students the skills they will need for future automation work
Students should not have access to this repo until after the lab. Throughout the 2-day course, the instructor is directed to provide specific components of this repo to students. The suggested method for doing this is to create a "class repo" and add the shared components to it one by one, allowing students to retrieve those files when they're needed.
II.A: Tools Covered
- git, Docker, Packer, WSL, VMWare, PVE
- some Bash/PowerShell scripting, including the scripting of API calls
II.B: Labs
- create and use a git repository throughout
- create and deploy a containerized build environment
- create and run Packer configs for automating:
- the installation of a Debian VM from an iso image
- the installation of the Proxmox Virtualization Environment onto a Debian VM
- use the VMWare Workstation Pro API to clone and deploy a PVE environment
- explore the PVE GUI
II.C: Prerequisites
Students should have the following installed and/or downloaded on their workstations:
- VMWare Workstation Pro
- "Pro" is required
- WSLv2
- Docker
- on the host or in WSL; though the answer key assumes Docker is on the host
- git
- a Debian iso
- the offline installer, not the "netinst" version
III: Suggested 2-Day Lesson Plan
III.A: Day 1, Part 1 (3 hours)
- Introductory material on infrastructure & infrastructure automation (30m)
- Discussion / Q&A format; Could benefit from slides in a future iteration
- What is "infrastructure"?
- How do we automate the deployment of impermanent infrastructure on physical hardware?
- Introduce the labs
- Tools covered:
- git, Docker, Packer, WSL, VMWare, PVE + some Bash/PowerShell scripting
- What we'll accomplish:
- create and deploy a containerized build environment
- create and run Packer configs for automating:
- the installation of a Debian VM from an iso image
- the installation of the Proxmox Virtualization Environment onto a Debian VM
- use the VMWare Workstation Pro API to clone and deploy a PVE environment
- explore the PVE GUI
- Tools covered:
- Discussion / Q&A format; Could benefit from slides in a future iteration
- Familiarization video and demos for git (30m)
- Video (12 minutes)
- Demos:
- creating a repo on GitHub or Gitlab
- cloning the repo locally
- making, staging, and committing changes
git show
andgit restore
git push
- Hands-On (15m)
- Instruct students to create a repo on the platform of their choice
- Students should clone the repo locally
- When complete, instruct students to clone the class repo (which should currently be empty)
- Break (15m)
- Familiarization slides and demos for containerization and Docker: (45m)
- Video 1 (8 minutes)
- Video 2 (11 minutes)
- Discuss the benefits of containerization and why students might want to containerize their build and test environments
- Demos:
- running a container
- building a container image
- Hands-On (45m)
- Instruct students to create a
/build-env
directory in their local repo - Within that repo, they should create a Dockerfile for a build environment
- Requirements for their image:
- install Hashicorp Packer and Terraform
- Students are free to install any other tools they find useful
- Conclude by having a student demonstrate building and running their image
III.B: Day 1, Part 2 (3 hours)
- Video introduction to Packer (30m)
- Discussion on Packer "internals" (30m)
- Testing Understanding
- Discussion points
- How does Packer interact with virtualization platforms like AWS?
- Does Packer itself understand how to 'talk' to various platforms? How does it understand the platform-specific mechanisms?
- How can Packer's functionality be extended to new platforms?
- By the end of the discussion, students should understand that:
- Packer uses modular plugins to isolate the "integration logic" (how to create or manipulate resources within a given virtualization platform) from the "core logic" of Packer itself
- The vast majority of plugins will be using the REST APIs exposed by various virtualization platforms and public cloud providers
- Discussion points
- Instruction
- "Bare Metal" Considerations
- When using Packer for the public cloud, you're generally starting from an image that already has an OS installed
- When using Packer for a private cloud (like Workstation or PVE), you typically have to start by installing the OS
- We will be using Packer to install an OS from an iso (the one students were instructed to download). This will create our "base image"
- We will then use Packer to clone our base image and perform further customization (installing PVE)
- VMWare Workstation Considerations
- The official Packer plugin for VMWare Workstation is unusual in that it does not use API calls (even though the Pro version does have an API available)
- Instead, the plugin runs VMWare executables on the local host
- These labs still containerize the build environment, but the unusual plugin implementation requires us to implement some workarounds; The workarounds will be provided by the instructor so students may focus on the core tasks of the labs
- "Bare Metal" Considerations
- Introduction to WSL (30m)
- Video 1 (10 minutes)
- Video 2 (5 minutes)
- Discussion / Q&A
- Have students open WSL on their own computers
- guide them through running Linux GUI apps, calling Windows .exe's from Linux, etc.
- Hands-On (30m)
- Instructor-led walkthrough
- Add
/build-env
from this repo to the class repo; Instruct students togit pull
- Explain the purpose of the workarounds
link-vmware-binaries.sh
- WSL distros are able to run Windows executables, but bc the Packer plugin will believe it is running on Linux, we need to link the vmware binaries without the ".exe"
- We are also creating a dummy script at
/usr/lib/vmware/bin/vmware-vmx
to make sure the plugin knows which version of the VMWare driver to use
link-vmware-configs.sh
- Similar to the binary linking; make sure the configs that the Packer plugin expects are in the right place (or appear to be)
netmap.conf
won't exist by default, but we know what the contents need to be, so we simply create a basic version of it if it is not present
prep-network.sh
- Packer will attempt to connect to VMs over VNC on the localhost. Because we actually want Packer to connect to VNC on the Windows host, we're going to use iptables to DNAT connections to Windows
bashrc
- most of the provided profile is from WSL's "stock" Debian distro
- at the bottom, we've added conditional commands to call our three scripts, as well as to add the VMWare executables to our PATH
- Walk students through the "Building the Build Environment" section from the Answer Key below
- Break (15m)
- Hands-On (15m)
- Instruct students to create a Debian VM in Workstation, using the iso they were instructed to download
- Before turning them loose, discuss the "why": Automating an installation from .iso is a lot easier if you first understand the steps that are being automated
- Packer Demo (45m)
- Explain Debian "preseed" files
- Pull up documentation
- Explain how the planned Packer config will work
- Uses VMWare commands to start the VM
- Connects to the VM over VNC and types a "boot command"
- The boot command will instruct the installing process to retrieve a preseed file that the Packer process is hosting over HTTP
- The preseed file will contain all config information needed to installation
- After the VM reboots, Packer can use "provisioners" to connect and perform additional installation steps
- Screenshare and demonstrate
packer build .
for the debian VM in this repo
III.C: Day 2, Part 1 (3 hours)
- Hands-On (2h)
- Provide a trimmed-down version of
/packer/debian
to the class repo- Provide
debian.pkr.hcl
, but remove:- the values of
http_content
,cpus
,memory
, andnetwork
- the
provisioner
block - Point out to students that links to relevant docs are at the top of the file
- the values of
- Provide students with the "Preparation" block from "Packer > Building Debian" in the answer key
- Provide
- Have students create a packer build of Debian
- stop this at the 90m mark
- Conclude by:
- Having a student demonstrate their build
- Get all students to the same stage
- Add the full
/packer/debian
to the class repo - Instruct students to
git pull
- Instruct students to
packer build .
- Troubleshoot until all students have a successful, standardized build
- Add the full
- Break (15m)
- Hands-On (45m)
- Instructor-led Walkthrough
- Guide students through:
- Manually cloning their packer-debian VM
- Installing PVE on top of the new VM
- Follow the steps in
install-pve-1.sh
andinstall-pve-2.sh
, but execute manually while students follow along
- Follow the steps in
- Provide
packer/proxmox
to students - Walk them through the
packer build
- Don't forget the preparation steps in "Packer > Building Proxmox"
- Ensure all students have a successful, standardized build
III.D: Day 2, Part 2 (3 hours)
- Video Introduction to Terraform (30m)
- VMWare APIs (30m)
- Discussion / Explanation
- The original intent of the lab was to deploy our final VM with Terraform, but the VMWare Workstation Terraform provider turned out to be buggy
- Instead, we will make our own API calls
- While more manual, this gives us a peek under the hood at what tools like Terraform and Packer are actually doing
- Instructor Demo
- Referencing the "Cloning Proxmox with the VMWare API" section below:
- Configure credentials for the vmrest API
- Start the API
- Navigate to
http://localhost:8697
; vmrest runs an "API Explorer" in addition to the API itself - Demonstrate the "GET VMS" API call from PowerShell. Explanation should include:
Invoke-WebRequest
- Including Basic Authentication headers
- the
ContentType
arg and meaning - how to interpret and work with the JSON response
ConvertFrom-Json
and working with PowerShell objects
- See examples in the
clone-vm.ps1
script
- Referencing the "Cloning Proxmox with the VMWare API" section below:
- Hands-On (1h)
- Instruct students to create a PowerShell script that will:
- Clone the packer-proxmox VM
- Register the new VM with Workstation
- Turn the new VM on
- After 30 minutes, ask for a volunteer to demonstrate their script
- If no one has finished, that is fine. See how far they've managed to get
- Pull up the script from this repo, explain it, and demonstrate it
- Break (15m)
- Hands-On (45m)
- Guide students through connecting to their Proxmox VM from the Windows host's browser
- Discuss Proxmox/VM networking and
vmbr
devices - Download the Alpine lxc template and deploy it
- Why Alpine? The template is small and will download quickly
- Demonstrate how to generate an API key and discuss how that will be used for Packer and Terraform automation
- Explore any other aspects of PVE that come to mind, and take questions on any of the lab material
IV: Lab "Answer Key"
IV.A: Building the Build Environment
# NOTE: From the repo's base dir, not from build-env/
# build the container
$tag = "niwamo/build-env:1.0" # you will probably want to use your own tag
docker build -t $tag -f ./build-env/Dockerfile .
# export the container
$tarPath = "$env:temp/build-env.tar"
docker export $(docker create $tag) --output=$tarPath
# import as a wsl distro
$wslDir = "$env:LOCALAPPDATA\wsl\build_env"
New-Item -ItemType Directory -Path $wslDir -Force
wsl.exe --import build-env $wslDir $tarPath
# open the distro
wsl -d build-env
IV.B: Packer
IV.B.a: Building Debian
Note: The following step assumes you have placed two items in an iso
directory at the base of the repo:
- a debian iso
- a "sha256sum" file with the iso hash
# from WSL in the base repo dir, set environment variables needed by the packer config
export REPO_DIR_WSL=$(pwd)
export REPO_DIR="C:$(pwd | grep -Po "(?<=/mnt/c).*" | sed 's/\//\\/g')"
export IDE_PATH="$REPO_DIR\\iso\\debian-12.2.0-amd64-DVD-1.iso"
export ISO_URL="file:$(find $REPO_DIR_WSL/iso/ -name "*.iso")"
export ISO_CHECKSUM="$(cat $(find $REPO_DIR_WSL/iso/ -name "*sum"))"
export LOCAL_IP=$(ip address show dev eth0 | grep -Po "(?<=inet\s)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
# In Bash/WSL
# move to packer dir and run build
cd ./packer/debian
packer init .
packer build .
IV.B.b: Building Proxmox
# In Bash/WSL
cd $REPO_DIR_WSL/packer/proxmox
# get the vmx path for our clone
vmx_path="$REPO_DIR\\packer\\debian\\output-debian\\packer-debian.vmx"
targetPath="$REPO_DIR_WSL/packer/debian/output-debian/packer-debian.vmx"
# create a dummy link to fool the packer plugin
ln -s $targetPath $vmx_path
# create the environment variable input for Packer
export VMX_PATH=$vmx_path
# run the build
packer build .
# remember to clean up the hacky symlink
IV.C: Cloning Proxmox with the VMWare API
# In PowerShell on the Windows host
# configure credentials for the API
& 'C:\Program Files (x86)\VMWare\VMWare Workstation\vmrest.exe' -C
# run the API - note, this will "hang", so you'll need a new shell for API calls
& 'C:\Program Files (x86)\VMWare\VMWare Workstation\vmrest.exe'
# in another shell
./vmrest-scripts/clone-vm.ps1
# note: you may need to reopen the VMWare GUI to see the new VM
# kill the vmrest terminal when you're done; no additional cleanup necessary
IV.D: To Clean Up
# In PowerShell on the Host
wsl --unregister build-env
rm "$env:TEMP/build-env.tar"
rm -r "$env:LOCALAPPDATA\wsl\build_env"
# optionally, clean up docker
$tag = "niwamo/build-env:1.0" # needs to be same tag as before
$containerIds = (docker container ls -a | Select-String -Pattern "(\w+)(?=\s+$tag)").matches.value
if ($containerIds) {
foreach ($container in $containerIds) {
docker container rm $container
}
}
$tag = ($tag | Select-String -Pattern ".*(?=:)").matches.value
$imageIds = (docker image ls -a | Select-String -Pattern "(?<=$tag\s+\S+\s+)\S+").matches.value
if ($imageIds) {
foreach ($image in $imageIds) {
docker image rm $image
}
}
# optionally,
# - remove VMs from VMWare Workstation (use the GUI console)
# - remove any new VM dirs in VMWare Workstation's default path
# - remove the packer 'output-<vmname>' directories