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 is configured with LXD, 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 remoting. The client should be installed and configured on your workstation.
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
Once you have your Ansible inventory configured, you may run ansible playbooks against your containers like you would any other system managed by Ansible.
---
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"}