Compare commits
3 Commits
74126fd43a
...
e0518f90b6
Author | SHA1 | Date | |
---|---|---|---|
|
e0518f90b6 | ||
|
7cc9094dff | ||
|
470abd06f8 |
329
README.md
329
README.md
@@ -1,3 +1,328 @@
|
||||
# advanced-libvirt-terraform-examples
|
||||
# Modern libvirt-driven Terraform examples
|
||||
|
||||
This repository contains terraform examples to deploy various modern virtual machines using QEMU and libvirt
|
||||
This repository contains Terraform recipes to deploy various modern virtual machines using QEMU and libvirt.
|
||||
|
||||
By modern, it is meant virtual machines that leverage the use of modern desktop-oriented technologies, like UEFI firmware and recent virtual motherboard chipset (i.e. Phyllome OS itself), by staying as close as possible as domain definitions maintained [here](https://git.phyllo.me/roots/xml-definition-for-domains).
|
||||
|
||||
## Requirements
|
||||
|
||||
- [QEMU](https://www.qemu.org/)
|
||||
- [libvirt](https://libvirt.org/)
|
||||
- [Terraform provider for Libvirt](https://github.com/dmacvicar/terraform-provider-libvirt)
|
||||
|
||||
## Assumptions
|
||||
|
||||
Your Linux x86_64-based machine has at least 4 GB of available memory and 2 CPUs.
|
||||
|
||||
## How to use it
|
||||
|
||||
- Clone this repository
|
||||
- Go to folder *ubuntu-cloud-server-2404-bios*
|
||||
- Execute the following commands, which will download and install the required Terraform provider if not already present
|
||||
|
||||
```
|
||||
$ terraform init
|
||||
|
||||
Initializing the backend...
|
||||
Initializing provider plugins...
|
||||
- Reusing previous version of dmacvicar/libvirt from the dependency lock file
|
||||
- Using previously-installed dmacvicar/libvirt v0.8.3
|
||||
|
||||
Terraform has been successfully initialized!
|
||||
|
||||
[...]
|
||||
```
|
||||
|
||||
- The following command will plan the deployment, describing actions that will be taken when applied
|
||||
|
||||
```
|
||||
$ terraform plan
|
||||
|
||||
[...]
|
||||
|
||||
Terraform will perform the following actions
|
||||
|
||||
# A cloud-init ISO disk is created, which provides pre-configured settings and scripts that are applied to a cloud-native disk image during its initial boot. Without it, no user would be created and it would not be possible to log into the virtual machine
|
||||
|
||||
+ resource "libvirt_cloudinit_disk" "commoninit" {
|
||||
+ name = "commoninit.iso"
|
||||
+ pool = "ubuntu-bios"
|
||||
|
||||
[...]
|
||||
|
||||
}
|
||||
|
||||
# The libvirt domain or virtual machine will be created
|
||||
|
||||
+ resource "libvirt_domain" "domain" {
|
||||
+ cloudinit = (known after apply)
|
||||
|
||||
[...]
|
||||
|
||||
}
|
||||
|
||||
# Here, a libvirt pool to store the virtual machine disk image will be created. It should be possible to use the default one
|
||||
|
||||
+ resource "libvirt_pool" "ubuntu-bios" {
|
||||
|
||||
[...]
|
||||
|
||||
+ name = "ubuntu-bios"
|
||||
+ type = "dir"
|
||||
|
||||
+ target {
|
||||
+ path = "/tmp/ubuntu-bios"
|
||||
}
|
||||
}
|
||||
|
||||
# A qcow2 disk volume will be created and stored in the previously created pool, based on a Ubuntu noble (24.04) hosted cloud image
|
||||
|
||||
+ resource "libvirt_volume" "ubuntu-qcow2" {
|
||||
+ format = "qcow2"
|
||||
|
||||
[...]
|
||||
|
||||
# The plan summaries the action to be taken, which in this case is about creating resources
|
||||
|
||||
Plan: 4 to add, 0 to change, 0 to destroy.
|
||||
```
|
||||
|
||||
- The last command will carry out the plan
|
||||
|
||||
```
|
||||
$ terraform apply
|
||||
|
||||
[...]
|
||||
|
||||
Do you want to perform these actions?
|
||||
Terraform will perform the actions described above.
|
||||
Only 'yes' will be accepted to approve.
|
||||
|
||||
Enter a value: yes
|
||||
|
||||
# The actions are carried out
|
||||
libvirt_pool.ubuntu-bios: Creating...
|
||||
libvirt_pool.ubuntu-bios: Creation complete after 0s
|
||||
|
||||
[...]
|
||||
|
||||
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
|
||||
```
|
||||
|
||||
- Identify the created machine
|
||||
|
||||
```
|
||||
$ sudo virsh list --all
|
||||
|
||||
Id Name State
|
||||
---------------------------------------------
|
||||
10 ubuntu-cloud-server-2404-0 running
|
||||
```
|
||||
|
||||
- Determine its IP address
|
||||
|
||||
```
|
||||
$ sudo virsh domifaddr ubuntu-cloud-server-2404-0
|
||||
```
|
||||
|
||||
```
|
||||
Name MAC address Protocol Address
|
||||
----------------------------------------------------------------
|
||||
vnet3 52:54:00:e2:51:c0 ipv4 192.168.122.24/24
|
||||
```
|
||||
|
||||
- Connect to the machine
|
||||
|
||||
```
|
||||
$ ssh root@192.168.122.24
|
||||
|
||||
[...]
|
||||
|
||||
# Use the password defined in the cloud-init.cfg file
|
||||
|
||||
root@192.168.122.24's password:
|
||||
|
||||
Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.8.0-71-generic x86_64)
|
||||
[...]
|
||||
System information as of Tue Aug 26 10:40:49 UTC 2025
|
||||
|
||||
System load: 0.0 Processes: 113
|
||||
Usage of /: 67.4% of 2.35GB Users logged in: 0
|
||||
Memory usage: 5% IPv4 address for ens3: 192.168.122.24
|
||||
Swap usage: 0%
|
||||
```
|
||||
|
||||
- Exit the virtual machine
|
||||
|
||||
```
|
||||
root@ubuntu$ exit
|
||||
```
|
||||
|
||||
- To destroy the virtual machine, execute the following command
|
||||
|
||||
```
|
||||
$ terraform destroy
|
||||
|
||||
[...]
|
||||
|
||||
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
|
||||
- destroy
|
||||
|
||||
Terraform will perform the following actions:
|
||||
|
||||
# libvirt_cloudinit_disk.commoninit will be destroyed
|
||||
- resource "libvirt_cloudinit_disk" "commoninit" {
|
||||
|
||||
[...]
|
||||
|
||||
# libvirt_domain.domain[0] will be destroyed
|
||||
- resource "libvirt_domain" "domain" {
|
||||
- arch = "x86_64" -> null
|
||||
|
||||
[...]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# libvirt_pool.ubuntu2 will be destroyed
|
||||
- resource "libvirt_pool" "ubuntu2" {
|
||||
- allocation = 798310400 -> null
|
||||
- available = 16019255296 -> null
|
||||
|
||||
[...]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# libvirt_volume.ubuntu-qcow2 will be destroyed
|
||||
- resource "libvirt_volume" "ubuntu-qcow2" {
|
||||
|
||||
[...]
|
||||
|
||||
}
|
||||
|
||||
Plan: 0 to add, 0 to change, 4 to destroy.
|
||||
|
||||
Do you really want to destroy all resources?
|
||||
Terraform will destroy all your managed infrastructure, as shown above.
|
||||
There is no undo. Only 'yes' will be accepted to confirm.
|
||||
|
||||
Enter a value: yes
|
||||
|
||||
libvirt_domain.domain[0]: Destroying... [id=611d5ede-e4b4-4ca5-ad83-83030942a6b5]
|
||||
libvirt_domain.domain[0]: Destruction complete after 0s
|
||||
libvirt_cloudinit_disk.commoninit: Destroying... [id=/tmp/cluster_storage2/commoninit.iso;5f4e08ef-ad51-484f-a9f2-c926f582974a]
|
||||
libvirt_volume.ubuntu-qcow2: Destroying... [id=/tmp/cluster_storage2/ubuntu-qcow2]
|
||||
libvirt_cloudinit_disk.commoninit: Destruction complete after 0s
|
||||
libvirt_volume.ubuntu-qcow2: Destruction complete after 0s
|
||||
libvirt_pool.ubuntu2: Destroying... [id=dbd62f8b-5d09-4e96-87e2-88e95c582896]
|
||||
libvirt_pool.ubuntu2: Destruction complete after 0s
|
||||
|
||||
Destroy complete! Resources: 4 destroyed.
|
||||
```
|
||||
|
||||
## Explanations
|
||||
|
||||
Let's take a look inside the *ubuntu-cloud-server-2404-bios* folder, which contains two files, *ubuntu-cloud-server-2404-bios.tf* and *cloud_init.cfg*
|
||||
|
||||
The first file *ubuntu-cloud-server-2404-bios.tf* contains the main configuration for the Terraform deployment.
|
||||
|
||||
- It starts by defining the required Terraform version and provider
|
||||
|
||||
```
|
||||
terraform {
|
||||
required_version = ">= 0.13"
|
||||
required_providers {
|
||||
libvirt = {
|
||||
source = "dmacvicar/libvirt"
|
||||
version = "0.8.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- The specific provider is defined here
|
||||
|
||||
```
|
||||
provider "libvirt" {
|
||||
uri = "qemu:///system"
|
||||
}
|
||||
```
|
||||
|
||||
> The [connection URI](https://libvirt.org/uri.html#qemu-qemu-and-kvm-uris) of the libvirt instance can be defined. One could for instance specific a libvirt instance that is hosted remotely
|
||||
|
||||
- A libvirt pool, to store the virtual machine image, is created:
|
||||
|
||||
```
|
||||
resource "libvirt_pool" "ubuntu-bios" {
|
||||
name = "ubuntu-bios"
|
||||
type = "dir"
|
||||
target {
|
||||
path = "/tmp/ubuntu-bios"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- The cloud-init user data will be fetched from a specific file whose path has to be declared:
|
||||
|
||||
```
|
||||
data "template_file" "user_data" {
|
||||
template = file("${path.module}/cloud_init.cfg")
|
||||
}
|
||||
```
|
||||
|
||||
- The ISO cloud-init disk will be created:
|
||||
|
||||
```
|
||||
resource "libvirt_cloudinit_disk" "commoninit" {
|
||||
name = "commoninit.iso"
|
||||
user_data = data.template_file.user_data.rendered
|
||||
pool = libvirt_pool.ubuntu-bios.name
|
||||
}
|
||||
```
|
||||
|
||||
- Perhaps the most important, the domain will be created:
|
||||
|
||||
> Values can be adjusted, such as memory or vCPU counts. In the examples, multiple virtio-based device hardware are created, such as a virtio-gpu.
|
||||
|
||||
```
|
||||
resource "libvirt_domain" "domain" {
|
||||
count = 1
|
||||
name = "ubuntu-cloud-server-2404-${count.index}"
|
||||
memory = "4092"
|
||||
vcpu = 2
|
||||
cloudinit = libvirt_cloudinit_disk.commoninit.id
|
||||
|
||||
cpu {
|
||||
mode = "host-model"
|
||||
}
|
||||
|
||||
disk {
|
||||
volume_id = libvirt_volume.ubuntu-qcow2.id
|
||||
}
|
||||
|
||||
console {
|
||||
type = "pty"
|
||||
target_port = "0"
|
||||
target_type = "virtio"
|
||||
}
|
||||
|
||||
video {
|
||||
type = "virtio"
|
||||
}
|
||||
|
||||
tpm {
|
||||
backend_type = "emulator"
|
||||
backend_version = "2.0"
|
||||
}
|
||||
|
||||
network_interface {
|
||||
network_name = "default"
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [Terraform provider domain documentation](https://github.com/dmacvicar/terraform-provider-libvirt/blob/master/website/docs/r/domain.html.markdown)
|
10
ubuntu-cloud-server-2404-bios/cloud_init.cfg
Normal file
10
ubuntu-cloud-server-2404-bios/cloud_init.cfg
Normal file
@@ -0,0 +1,10 @@
|
||||
ssh_pwauth: true
|
||||
chpasswd:
|
||||
list: |
|
||||
root:phyllome
|
||||
expire: False
|
||||
disable_root: false
|
||||
|
||||
runcmd:
|
||||
- sed -i '/PermitRootLogin/s/.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
||||
- systemctl restart sshd
|
@@ -0,0 +1,74 @@
|
||||
terraform {
|
||||
required_version = ">= 0.13"
|
||||
required_providers {
|
||||
libvirt = {
|
||||
source = "dmacvicar/libvirt"
|
||||
version = "0.8.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "libvirt" {
|
||||
uri = "qemu:///system"
|
||||
}
|
||||
|
||||
resource "libvirt_pool" "ubuntu-bios" {
|
||||
name = "ubuntu-bios"
|
||||
type = "dir"
|
||||
target {
|
||||
path = "/tmp/ubuntu-bios"
|
||||
}
|
||||
}
|
||||
|
||||
resource "libvirt_volume" "ubuntu-qcow2" {
|
||||
name = "ubuntu-qcow2"
|
||||
pool = libvirt_pool.ubuntu-bios.name
|
||||
source = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
|
||||
format = "qcow2"
|
||||
}
|
||||
|
||||
data "template_file" "user_data" {
|
||||
template = file("${path.module}/cloud_init.cfg")
|
||||
}
|
||||
|
||||
resource "libvirt_cloudinit_disk" "commoninit" {
|
||||
name = "commoninit.iso"
|
||||
user_data = data.template_file.user_data.rendered
|
||||
pool = libvirt_pool.ubuntu-bios.name
|
||||
}
|
||||
|
||||
resource "libvirt_domain" "domain" {
|
||||
count = 1
|
||||
name = "ubuntu-cloud-server-2404-${count.index}"
|
||||
memory = "4092"
|
||||
vcpu = 2
|
||||
cloudinit = libvirt_cloudinit_disk.commoninit.id
|
||||
|
||||
cpu {
|
||||
mode = "host-model"
|
||||
}
|
||||
|
||||
disk {
|
||||
volume_id = libvirt_volume.ubuntu-qcow2.id
|
||||
}
|
||||
|
||||
console {
|
||||
type = "pty"
|
||||
target_port = "0"
|
||||
target_type = "virtio"
|
||||
}
|
||||
|
||||
video {
|
||||
type = "virtio"
|
||||
}
|
||||
|
||||
tpm {
|
||||
backend_type = "emulator"
|
||||
backend_version = "2.0"
|
||||
}
|
||||
|
||||
network_interface {
|
||||
network_name = "default"
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user