update the README to reflect recent changes

add script to automatically add SSH key pair to main.tf files, for deployments that do require it
This commit is contained in:
Lukas Greve
2025-10-18 13:19:22 +02:00
parent 91e23f0765
commit 6076b096f1
2 changed files with 132 additions and 280 deletions

332
README.md
View File

@@ -11,16 +11,16 @@ The folder *multiple* contains two subfolders, one with shared modules and the o
The idea is to reuse modules across multiple virtual machines and operating systems.
```
./multiple:
.:
environments shared_modules
./multiple/environments:
./environments:
cloud_init.yaml ubuntu-cloud-server-2404-bios
./multiple/environments/ubuntu-cloud-server-2404-bios:
./environments/ubuntu-cloud-server-2404-bios:
ubuntu-cloud-server-2404-bios.tf
./multiple/shared_modules:
./shared_modules:
cloud-init.tf domain.tf network.tf outputs.tf pool.tf provider.tf variables.tf volume.tf
```
@@ -29,320 +29,92 @@ cloud-init.tf domain.tf network.tf outputs.tf pool.tf provider.tf variable
- [QEMU](https://www.qemu.org/)
- [libvirt](https://libvirt.org/)
- [Terraform provider for Libvirt](https://github.com/dmacvicar/terraform-provider-libvirt)
- An SSH key pair to connect to machines that are deployed using cloud-init
## Assumptions
Your Linux x86_64-based machine has at least 4 GB of available memory and 2 CPUs.
- 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 *example*
- Execute the following commands, which will download and install the required Terraform provider if not already present
- Run the following to generate a public key pair
```
$ 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!
[...]
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/terraform_key -C "terraform-deployment"
```
- The following command will plan the deployment, describing actions that will be taken when applied
- Make the script executable
```
$ chmod +x update_ssh_keys.sh
```
- Run the script (it will use terraform_key by default), and will update all `main.tf` file so that they use the previously generated key:
```
$ ./update_ssh_keys.sh
```
> Alternatively, you can use your own public key and update it manually in the `main.tf` deployment file
- Navigate to one of the available deployment
```
$ cd environments/ubuntu-cloud-server-2404-bios/
```
- Initialize your terraform environment
```
$ terraform init
```
- Plan the deployment
```
$ 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
- Deploy
```
$ 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.
$ terraform deploy
```
- Identify the created machine
- Identify the name of the machine, which requires elevated privileges
```
$ sudo virsh list --all
Id Name State
---------------------------------------------
10 ubuntu-cloud-server-2404-0 running
# virsh list --all
Id Name State
--------------------------------------------
2 u24-bios-0 running
```
- Determine its IP address
- Fetch IP address
```
$ sudo virsh domifaddr ubuntu-cloud-server-2404-0
# virsh domifaddr u24-bios-0
```
- Connect to the machine with the user `groot`
```
$ ssh groot@10.17.3.107
```
```
Name MAC address Protocol Address
----------------------------------------------------------------
vnet3 52:54:00:e2:51:c0 ipv4 192.168.122.24/24
groot@ubuntu:~$
```
- Connect to the machine
- Logout
```
$ 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
```
- Exit the virtual machine
```
root@ubuntu$ exit
```
- To destroy the virtual machine, execute the following command
- Destroy the machine
```
$ 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