Using Ansible & Terraform w/ LXD
I've been making more and more use of infrastructure as code tools, specifically Ansible & Terraform. Most of my servers are running in LXD containers, which these tools provide interactions with.
Source Documentation
Architecture
The server has LXD installed and is configured for remote connections. The client has LXD installed as well and connects to the server. See Remote LXD Connections for more details on setting up LXD remoting. The client should be installed and configured on your workstation. The following should work from the workstation:
$ lxc ls lxd-server-01:
+------------------+---------+----------------------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------------------+---------+----------------------+------+-----------+-----------+
| lxd-container-01 | RUNNING | 192.168.1.100 (eth0) | | CONTAINER | 0 |
+------------------+---------+----------------------+------+-----------+-----------+
| lxd-container-02 | RUNNING | 192.168.1.101 (eth0) | | CONTAINER | 0 |
+------------------+---------+----------------------+------+-----------+-----------+
Example Terraform Configuration
Below is an example main.tf
configuration for use with LXD. See comments in the example for important notes.
terraform {
required_providers {
lxd = {
source = "terraform-lxd/lxd"
version = ">= 1.10.1"
}
}
}
provider "lxd" {
generate_client_certificates = false
accept_remote_certificate = false
## If running the LXD client as a snap, the below config_dir should work
## If running another distro, try omitting this to use the default of $HOME/.config/lxc
config_dir = "$HOME/snap/lxd/common/config"
lxd_remote {
## name is the name as shown in 'lxc remote list'
name = "lxd-server-01"
default = true
}
}
resource "lxd_container" "lxd-container-01" {
name = "lxd-container-01"
image = "images:ubuntu/22.04"
## This copies a file in. In my case, I'm configuring static IPs using netplan,
## so the netplan configs are stored with the terraform code
file {
source = "netplan/lxd-container-01.yml"
target_file = "/etc/netplan/10-lxc.yaml"
}
## You can also configure disk mounts, and other LXD devices
device {
name = "mariadb"
type = "disk"
properties = {
path = "/var/lib/mysql"
source = "/tank/mariadb"
}
}
}
Example Ansible Inventory
---
all:
hosts:
lxd-server-01:
children:
containers:
hosts:
lxd-container-01:
lxd-container-02:
vars:
ansible_connection: lxd
ansible_lxd_remote: lxd-server-01
Once you have your inventory.yml
vars properly configured you can run ansible as you normally would.
$ ansible -bom ping -i inventory.yml lxd-container-0*
lxd-container-01 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"}
lxd-container-02 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"}