Skip to content

Commit d63f66f

Browse files
committed
Terraform Code to build a local LibVirt Qemu/KVM lab
1 parent 3ccae5d commit d63f66f

11 files changed

+371
-0
lines changed

tf_libvirt/Cloudinit.tf

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
resource "random_id" "id" {
2+
for_each = local.VMs
3+
4+
byte_length = 4
5+
}
6+
7+
data "template_file" "user_data" {
8+
for_each = local.VMs
9+
10+
template = file("templates/user-data.yml")
11+
vars = {
12+
hostname = each.value.hostname
13+
sshdport = each.value.ssh_port
14+
timezone = each.value.timezone
15+
gh_user = each.value.gh_user
16+
}
17+
}
18+
19+
data "template_file" "network_config" {
20+
template = file("templates/netplan.yml")
21+
}
22+
23+
resource "libvirt_cloudinit_disk" "cloud-init" {
24+
for_each = local.VMs
25+
26+
name = "${random_id.id[each.key].id}_cloud-init.iso"
27+
user_data = data.template_file.user_data[each.key].rendered
28+
29+
depends_on = [data.template_file.user_data]
30+
}
31+
32+
resource "time_sleep" "wait_for_cloud_init" {
33+
create_duration = "20s"
34+
35+
depends_on = [libvirt_cloudinit_disk.cloud-init]
36+
}

tf_libvirt/Domain.tf

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
resource "libvirt_domain" "domain-ubuntu" {
2+
for_each = local.VMs
3+
4+
name = each.value.hostname
5+
6+
memory = each.value.vmem
7+
vcpu = each.value.vcpu
8+
9+
cloudinit = libvirt_cloudinit_disk.cloud-init[each.key].id
10+
11+
network_interface {
12+
network_name = "default"
13+
wait_for_lease = true
14+
}
15+
16+
console {
17+
target_type = "serial"
18+
type = "pty"
19+
target_port = "0"
20+
}
21+
console {
22+
target_type = "virtio"
23+
type = "pty"
24+
target_port = "1"
25+
}
26+
27+
disk {
28+
volume_id = libvirt_volume.ubuntu-base[each.key].id
29+
}
30+
31+
depends_on = [libvirt_cloudinit_disk.cloud-init]
32+
}
33+

tf_libvirt/Output.tf

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
output "VMs" {
2+
value = [ for vms in libvirt_domain.domain-ubuntu : format("%s %s", vms.network_interface.0.addresses[0], vms.name) ]
3+
4+
depends_on = [libvirt_domain.domain-ubuntu]
5+
}
6+

tf_libvirt/Provider.tf

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
terraform {
2+
required_version = ">= 1.2"
3+
4+
required_providers {
5+
libvirt = {
6+
source = "dmacvicar/libvirt"
7+
version = "0.6.14"
8+
}
9+
10+
template = {
11+
source = "hashicorp/template"
12+
}
13+
14+
random = {
15+
source = "hashicorp/random"
16+
}
17+
18+
time = {
19+
source = "hashicorp/time"
20+
}
21+
}
22+
}
23+
24+
provider "libvirt" {
25+
uri = "qemu:///system"
26+
}
27+

tf_libvirt/README.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Deploy ubuntu 22.04 LTS to libvirt/qemu via terraform
2+
3+
Terraform repo to deploy a kubernetes cluster for educational purposes.
4+
5+
It spawns three (3) Qemu/KVM Virtual Machines, based on ubuntu 22.04 LTS to libvirt.
6+
7+
## Variables
8+
9+
You need to edit **Variables.tf**
10+
11+
- timezone
12+
- ssh port
13+
- hostname
14+
- vcpu
15+
- vmem
16+
- vol_size
17+
18+
and especially the Variable
19+
20+
- github user
21+
22+
so you can have ssh access to these VMs.
23+
24+
## init
25+
26+
```bash
27+
terraform init
28+
29+
```
30+
31+
## start
32+
33+
```bash
34+
./start.sh
35+
36+
...
37+
38+
Apply complete! Resources: 16 added, 0 changed, 0 destroyed.
39+
40+
Outputs:
41+
42+
VMs = [
43+
"192.168.122.169 k8scpnode",
44+
"192.168.122.40 k8wrknode1",
45+
"192.168.122.8 k8wrknode2",
46+
]
47+
48+
49+
$ ssh -l ubuntu 192.168.122.169 hostname
50+
k8scpnode
51+
52+
$ ssh 192.168.122.169 -l ubuntu 'grep ^VERSION= /etc/os-release'
53+
VERSION="22.04.1 LTS (Jammy Jellyfish)"
54+
55+
```
56+
57+
## destroy
58+
59+
```bash
60+
./destroy.sh
61+
62+
```
63+
64+
## root password
65+
66+
if needed
67+
68+
```bash
69+
$ sudo virsh console k8scpnode
70+
71+
userame: root
72+
password: ping
73+
74+
````

tf_libvirt/Variables.tf

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
locals {
2+
# Virtual Machines
3+
VMs = {
4+
k8scpnode = {
5+
# The host name of the VM
6+
hostname = "k8scpnode"
7+
8+
# The image source of the VM
9+
# cloud_image = "https://cloud-images.ubuntu.com/jammy/current/focal-server-cloudimg-amd64.img"
10+
cloud_image = "../jammy-server-cloudimg-amd64.img"
11+
12+
# TimeZone of the VM: /usr/share/zoneinfo/
13+
timezone = "Europe/Athens"
14+
15+
# The sshd port of the VM"
16+
ssh_port = 22
17+
18+
# The default ssh key for user ubuntu
19+
# https://github.com/<username>.keys
20+
gh_user = "ebal"
21+
22+
# The disk volume size of the VM
23+
# eg. 20G
24+
vol_size = 20 * 1024 * 1024 * 1024
25+
26+
# How many virtual CPUs the VM
27+
vcpu = 2
28+
29+
# How RAM will VM have will have
30+
vmem = 2048
31+
32+
},
33+
34+
k8wrknode1 = {
35+
# The host name of the VM
36+
hostname = "k8wrknode1"
37+
38+
# The image source of the VM
39+
# cloud_image = "https://cloud-images.ubuntu.com/jammy/current/focal-server-cloudimg-amd64.img"
40+
cloud_image = "../jammy-server-cloudimg-amd64.img"
41+
42+
# TimeZone of the VM: /usr/share/zoneinfo/
43+
timezone = "Europe/Athens"
44+
45+
# The sshd port of the VM"
46+
ssh_port = 22
47+
48+
# The default ssh key for user ubuntu
49+
# https://github.com/<username>.keys
50+
gh_user = "ebal"
51+
52+
# The disk volume size of the VM
53+
# eg. 40G
54+
vol_size = 40 * 1024 * 1024 * 1024
55+
56+
# How many virtual CPUs the VM
57+
vcpu = 4
58+
59+
# How RAM will VM have will have
60+
vmem = 4096
61+
62+
},
63+
64+
k8wrknode2 = {
65+
# The host name of the VM
66+
hostname = "k8wrknode2"
67+
68+
# The image source of the VM
69+
# cloud_image = "https://cloud-images.ubuntu.com/jammy/current/focal-server-cloudimg-amd64.img"
70+
cloud_image = "../jammy-server-cloudimg-amd64.img"
71+
72+
# TimeZone of the VM: /usr/share/zoneinfo/
73+
timezone = "Europe/Athens"
74+
75+
# The sshd port of the VM"
76+
ssh_port = 22
77+
78+
# The default ssh key for user ubuntu
79+
# https://github.com/<username>.keys
80+
gh_user = "ebal"
81+
82+
# The disk volume size of the VM
83+
# eg. 40G
84+
vol_size = 40 * 1024 * 1024 * 1024
85+
86+
# How many virtual CPUs the VM
87+
vcpu = 4
88+
89+
# How RAM will VM have will have
90+
vmem = 4096
91+
92+
}
93+
94+
}
95+
}

tf_libvirt/Volume.tf

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
resource "libvirt_volume" "ubuntu-vol" {
2+
for_each = local.VMs
3+
4+
name = "${random_id.id[each.key].id}_ubuntu-vol"
5+
pool = "default"
6+
source = each.value.cloud_image
7+
format = "qcow2"
8+
}
9+
10+
resource "libvirt_volume" "ubuntu-base" {
11+
for_each = local.VMs
12+
13+
name = "${random_id.id[each.key].id}_ubuntu-base"
14+
pool = "default"
15+
base_volume_id = libvirt_volume.ubuntu-vol[each.key].id
16+
size = each.value.vol_size
17+
format = "qcow2"
18+
}

tf_libvirt/destroy.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
terraform destroy -auto-approve

tf_libvirt/start.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
terraform plan -out terraform.out && terraform apply terraform.out

tf_libvirt/templates/netplan.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
version: 2
2+
ethernets:
3+
ens3:
4+
dhcp4: true

tf_libvirt/templates/user-data.yml

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#cloud-config
2+
3+
#disable_root: true
4+
disable_root: false
5+
chpasswd:
6+
list: |
7+
root:ping
8+
expire: False
9+
10+
ssh_pwauth: no
11+
12+
users:
13+
- name: ubuntu
14+
ssh_import_id:
15+
- gh:${gh_user}
16+
shell: /bin/bash
17+
sudo: ALL=(ALL) NOPASSWD:ALL
18+
19+
write_files:
20+
- path: /etc/ssh/sshd_config
21+
content: |
22+
AcceptEnv LANG LC_*
23+
AllowUsers ubuntu
24+
ChallengeResponseAuthentication no
25+
Compression NO
26+
MaxSessions 3
27+
PasswordAuthentication no
28+
PermitRootLogin no
29+
Port ${sshdport}
30+
PrintMotd no
31+
Subsystem sftp /usr/lib/openssh/sftp-server
32+
UseDNS no
33+
UsePAM yes
34+
X11Forwarding no
35+
Ciphers [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
36+
KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
37+
38+
HostKeyAlgorithms [email protected],[email protected],[email protected],[email protected],ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
39+
40+
# Set TimeZone
41+
timezone: ${timezone}
42+
43+
hostname: "${hostname}"
44+
45+
growpart:
46+
mode: auto
47+
devices: ["/"]
48+
ignore_growroot_disabled: false
49+
50+
# Install packages
51+
packages:
52+
- bash-completion
53+
- figlet
54+
- mlocate
55+
- ncdu
56+
- python3-apt
57+
58+
# Update/Upgrade & Reboot if necessary
59+
package_update: true
60+
package_upgrade: true
61+
package_reboot_if_required: true
62+
63+
# PostInstall
64+
runcmd:
65+
- figlet ${hostname} > /etc/motd
66+
- updatedb
67+
# Firewall
68+
- ufw allow "${sshdport}"/tcp && ufw enable
69+
# Remove cloud-init
70+
- apt-get -y autoremove --purge cloud-init lxc lxd snapd
71+
- apt-get -y --purge autoremove
72+
- apt -y autoclean
73+
- apt -y clean all
74+
- date -R > /root/Finished.txt

0 commit comments

Comments
 (0)