diff --git a/proxmox/.gitignore b/proxmox/.gitignore new file mode 100644 index 0000000..210f214 --- /dev/null +++ b/proxmox/.gitignore @@ -0,0 +1 @@ +cloud_drives diff --git a/proxmox/README.md b/proxmox/README.md new file mode 100644 index 0000000..a6d0a64 --- /dev/null +++ b/proxmox/README.md @@ -0,0 +1,26 @@ +# Proxmox + +This small examplez demo how to provision flatcar on proxmox using terraform + +## Prerequisite + + - A proxmox cluster with credentials + - `terraform` + - `mkisofs`: + ArchLinux: `pacman -Sy crdtools` + Debian/Ubuntu: `apt install genisoimage` + Mac OS: `brew install cdrtools` + RPM/DNF based OS: `dnf install mkisofs` + + +## How-to + +This module use the `bpg/proxmox` provider, and you configure it using environment variable [here](https://registry.terraform.io/providers/bpg/proxmox/latest/docs#argument-reference) + +``` +export PROXMOX_VE_ENDPOINT= +export PROXMOX_VE_USERNAME= +export PROXMOS_VE_PASSWORD= +terraform init +terraform apply +``` diff --git a/proxmox/cloud_drives.tf b/proxmox/cloud_drives.tf new file mode 100644 index 0000000..e032f4b --- /dev/null +++ b/proxmox/cloud_drives.tf @@ -0,0 +1,50 @@ +locals { + cloud_drives = { for vm in var.machines : + vm => "${path.module}/cloud_drives/${vm}/cloud_drive.iso" + } +} + +data "ct_config" "ignition" { + for_each = toset(var.machines) + content = templatefile("templates/machine-${each.key}.yaml", { + ssh_keys = var.ssh_keys + }) + + strict = true +} +resource "local_file" "userdata_ignition" { + for_each = toset(var.machines) + content = data.ct_config.ignition[each.key].rendered + filename = "${path.module}/cloud_drives/${each.key}/drive/openstack/latest/user_data" +} + +resource "local_file" "meta_data_openstack" { + for_each = toset(var.machines) + content = templatefile("${path.module}/templates/meta_data.json", { + vm_name = each.key + }) + filename = "${path.module}/cloud_drives/${each.key}/drive/openstack/latest/meta_data.json" +} + +# Create cloud-drive cdrom locally +resource "null_resource" "cloud_init_drive" { + for_each = toset(var.machines) + provisioner "local-exec" { + command = "mkisofs -output ${local.cloud_drives[each.key]} -volid config-2 -joliet -r ${path.module}/cloud_drives/${each.key}/drive" + } + + depends_on = [local_file.meta_data_openstack, local_file.userdata_ignition] +} + +# Upload cloud_drives to proxmox +resource "proxmox_virtual_environment_file" "cloud_drive" { + for_each = toset(var.machines) + content_type = "iso" + datastore_id = var.datastore_local + node_name = local.hypervisor + + source_file { + file_name = "${each.key}_cloud_drive.iso" + path = local.cloud_drives[each.key] + } +} diff --git a/proxmox/output.tf b/proxmox/output.tf new file mode 100644 index 0000000..a59e56e --- /dev/null +++ b/proxmox/output.tf @@ -0,0 +1,3 @@ +output "flatcar_template" { + value = proxmox_virtual_environment_vm.flatcar_template +} diff --git a/proxmox/providers.tf b/proxmox/providers.tf new file mode 100644 index 0000000..0ce04d2 --- /dev/null +++ b/proxmox/providers.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + ct = { + source = "poseidon/ct" + } + proxmox = { + source = "bpg/proxmox" + } + } +} diff --git a/proxmox/templates/machine-test-flatcar.yaml b/proxmox/templates/machine-test-flatcar.yaml new file mode 100644 index 0000000..73fc963 --- /dev/null +++ b/proxmox/templates/machine-test-flatcar.yaml @@ -0,0 +1,24 @@ +variant: flatcar +version: 1.1.0 +passwd: + users: + - name: core + ssh_authorized_keys: + %{ for key in ssh_keys } + - ${key} + %{ endfor } +systemd: + units: + - name: flatcar-openstack-hostname.service + mask: true +storage: + files: + - path: /etc/systemd/network/00-eth0.network + contents: + inline: | + [Match] + Name=eth0 + [Network] + Address=192.0.2.10/24 + Gateway=192.0.2.1/24 + DNS=1.1.1.1 diff --git a/proxmox/templates/meta_data.json b/proxmox/templates/meta_data.json new file mode 100644 index 0000000..ff65b25 --- /dev/null +++ b/proxmox/templates/meta_data.json @@ -0,0 +1,10 @@ +{ + "uuid": "${ uuidv5("dns", vm_name) }", + "availability_zone": "nova", + "hostname": "${ vm_name }", + "launch_index": 0, + "meta": {}, + "project_id": "${ uuidv5("dns", "proxmox") }", + "name": "${ vm_name }" +} + diff --git a/proxmox/variables.tf b/proxmox/variables.tf new file mode 100644 index 0000000..7070067 --- /dev/null +++ b/proxmox/variables.tf @@ -0,0 +1,45 @@ +variable "machines" { + type = list(string) + description = "Machine names, corresponding to templates/machine-NAME.yaml" +} + +variable "datastore_local" { + default = "local" + description = "datastore_id of hypervisor local storage" + type = string +} + +variable "datastore_vm" { + default = "local-zfs" + description = "datastore_id of VM storage" + type = string +} + +variable "flatcar_version" { + type = string + description = "The Flatcar version associated to the release channel" + default = "current" +} + +variable "release_channel" { + type = string + description = "Release channel" + default = "stable" + + validation { + condition = contains(["lts", "stable", "beta", "alpha"], var.release_channel) + error_message = "release_channel must be lts, stable, beta, or alpha." + } +} + +variable "ssh_keys" { + default = [] + description = "List of ssh-keys to authenticate to the flatcar VM" + type = list(string) +} + +variable "vm_name" { + default = "test-flatcar" + description = "proxmox VM name (also used as hostname in this repository)" + type = string +} diff --git a/proxmox/virtual_machine.tf b/proxmox/virtual_machine.tf new file mode 100644 index 0000000..84b0f18 --- /dev/null +++ b/proxmox/virtual_machine.tf @@ -0,0 +1,32 @@ + +resource "proxmox_virtual_environment_vm" "instance" { + for_each = toset(var.machines) + clone { + vm_id = proxmox_virtual_environment_vm.flatcar_template.vm_id + node_name = local.hypervisor + } + + name = each.key + node_name = local.hypervisor + started = true + + cpu { + cores = 2 + } + + memory { + dedicated = 2048 + } + + cdrom { + enabled = true + file_id = "${var.datastore_local}:iso/${each.key}_cloud_drive.iso" + } + + lifecycle { + ignore_changes = [ + node_name + ] + } +} + diff --git a/proxmox/vm_template.tf b/proxmox/vm_template.tf new file mode 100644 index 0000000..d28c1d6 --- /dev/null +++ b/proxmox/vm_template.tf @@ -0,0 +1,40 @@ +data "proxmox_virtual_environment_nodes" "available_nodes" {} + +locals { + hypervisor = element(data.proxmox_virtual_environment_nodes.available_nodes.names, 0) + image_file = "flatcat-openstack-${var.release_channel}-${var.flatcar_version}.img" +} + +resource "proxmox_virtual_environment_download_file" "flatcar_image" { + + content_type = "iso" + datastore_id = var.datastore_local + node_name = local.hypervisor + file_name = local.image_file + overwrite = false + url = "https://${var.release_channel}.release.flatcar-linux.net/amd64-usr/${var.flatcar_version}/flatcar_production_openstack_image.img.gz" + + decompression_algorithm = "gz" +} + +resource "proxmox_virtual_environment_vm" "flatcar_template" { + depends_on = [proxmox_virtual_environment_download_file.flatcar_image] + + name = "flatcar-${var.release_channel}-${var.flatcar_version}" + node_name = local.hypervisor + + cpu { + cores = 1 + } + + memory { + dedicated = 1024 + } + disk { + datastore_id = var.datastore_vm + file_id = "${var.datastore_local}:iso/${local.image_file}" + interface = "virtio0" + } + + template = true +}