Using Ansible to provision LXC containers
Since all of us have a bit of extra time lately I grabbed a copy of Jeff Geerling's Ansible for DevOps to finally tackle the project to translate my many, many bash scripts into something for flexible and idempotent.
Ever since I began moving a lot of my cloud-hosted projects and applications to my own hardware in a colocation facility, I've spent a lot of time spinning up linux containers on Proxmox and running bash scripts to get them into a state that's useful for me. This can get tedious and time consuming!
My first project with Ansible was to not only streamline the creating of linux containers on my Proxmox hypervisor, but to provision them with the base configuration they need—and to subscribe them to my FreeIPA domain for central authentication.
Besides the included README, you can find the entire playbook on GitHub.
ansible-pve-lxc
ansible-pve-lxc is an Ansible playbook and set of roles for provisioning and configuring LXC containers in a Proxmox virtual environment, and subsequently subscribing them to a FreeIPA domain.
Define inventory with container configurations
This inventory is in the YAML format, but will also work in INI format
---
proxmox:
hosts:
pve.site.domain
containers:
hosts:
db1.site.domain:
ansible_host: 10.0.10.125
app1.site.domain:
ansible_host: 10.0.10.126
Populate host variables with individual container configurations
host_vars/db1.site.domain.yml
---
node: 'gold'
vmid: '110'
cores: '1'
memory: '1024'
swap: '0'
onboot: true
network: '{"net0":"name=eth0,ip=10.0.10.125/24,gw=10.0.10.1,ip6=dhcp,bridge=vmbr1"}'
host_vars/app1.site.domain.yml
---
node: 'gold'
vmid: '111'
cores: '2'
memory: '2048'
swap: '0'
onboot: true
network: '{"net0":"name=eth0,ip=10.0.10.126/24,gw=10.0.10.1,ip6=dhcp,bridge=vmbr1"}'
Configure variables
Define PVE API and LXC default variables
group_vars/proxmox.yml
---
api_host: 'pve.site.domain'
api_user: 'root@pam'
defaults:
node: 'gold'
storage: 'local-zfs'
cores: '1'
memory: '1024'
onboot: true
pubkey: '{{ ssh_pubkey }}'
searchdomain: 'site.domain'
nameserver: '1.1.1.1,8.8.8.8'
ostemplate: 'bulk:vztmpl/centos-8-20200402_amd64.tar.gz'
network: '{"net0":"name=eth0,ip=dhcp,ip6=dhcp,bridge=vmbr1"}'
Define PVE API password, SSH public key, and IPA admin password
group_vars/all.yml
---
api_password: '<proxmox_api_password>'
ssh_pubkey: '<ssh_public_key>'
ipa_domain: 'ipa.site.domain'
ipa_realm: 'IPA.SITE.DOMAIN'
ipa_principal: 'admin'
ipa_admin_pw: '<ipa_admin_password>'
Optional (but suggested!): Use ansible-vault to encrypt group_vars/all.yml
$ nsible-vault encrypt group_vars/all.yml
Use ansible-pve-lxc
Optional: Temporarily disable ssh host key checking
$ export ANSIBLE_HOST_KEY_CHECKING=False
Run playbook
$ ansible-playbook -i inventory site.yml --ask-become-pass
Run playbook while asking for the vault password interactively
$ ansible-playbook -i inventory site.yml --ask-become-pass --ask-vault-pass
Optional: Re-enable ssh host key checking
$ unset ANSIBLE_HOST_KEY_CHECKING