diff --git a/terraform/kubernetes/kubernetes.tf b/terraform/kubernetes/kubernetes.tf new file mode 100644 index 0000000..d35dc9a --- /dev/null +++ b/terraform/kubernetes/kubernetes.tf @@ -0,0 +1,112 @@ +terraform { + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.38.1" + } + onepassword = { + source = "1Password/onepassword" + # version = "1.2.1" + } + } +} + +# https://registry.terraform.io/providers/1Password/onepassword/latest/docs +provider "onepassword" { + service_account_token = var.op_sa_token +} + +data "onepassword_item" "virtual_environment" { + vault = var.op_virtual_environment_vault_name + title = var.op_virtual_environment_item_name +} + +# https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external +# 1Password Terraform provider does not support retrieving SSH keys yet :( +# https://github.com/1Password/terraform-provider-onepassword/issues/74 +data "external" "op_ssh_key" { + program = ["${path.cwd}/scripts/op-ssh.sh"] + query = { + vault = var.op_ssh_vault_name + title = var.op_ssh_key_name + } +} + +# https://registry.terraform.io/providers/bpg/proxmox/latest/docs +provider "proxmox" { + endpoint = data.onepassword_item.virtual_environment.url + username = var.virtual_environment_username + password = data.onepassword_item.virtual_environment.password + insecure = true +} + +# https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm +resource "proxmox_virtual_environment_vm" "k3s" { + for_each = { + for node in var.nodes : node.name => node + } + + name = each.value.name + description = each.value.description + tags = ["k3s", "kubernetes"] + node_name = var.virtual_environment_node + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#agent + agent { + enabled = true + trim = true + } + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#clone + clone { + vm_id = var.virtual_environment_template_vm_id + } + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#cpu + cpu { + cores = each.value.cores + } + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#disk + # Always provision nodes with 2 disks - one for the OS and one for the data + # OS disk + disk { + interface = "virtio0" + datastore_id = var.virtual_environment_os_disk_datastore_id + discard = "on" + size = 50 + } + # Data disk + disk { + interface = "virtio1" + datastore_id = var.virtual_environment_data_disk_datastore_id + discard = "on" + size = 200 + file_format = "raw" + } + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#memory + memory { + dedicated = each.value.memory + } + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#initialization + initialization { + ip_config { + ipv4 { + address = each.value.ip + gateway = var.nodes_gateway + } + } + user_account { + keys = [trimspace(data.external.op_ssh_key.result["ssh_public_key"])] + password = each.value.password + username = each.value.username + } + } + + # https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#operating_system + operating_system { + type = "l26" + } +} diff --git a/terraform/kubernetes/scripts/op-ssh.sh b/terraform/kubernetes/scripts/op-ssh.sh new file mode 100755 index 0000000..9bfea91 --- /dev/null +++ b/terraform/kubernetes/scripts/op-ssh.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Author: Daniel Brennand +# License: MIT +# This script uses the 1Password CLI to retrieve a SSH public key from a 1Password vault +# https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external +set -e +eval "$(jq -r '@sh "VAULT=\(.vault) TITLE=\(.title)"')" +SSH_PUBLIC_KEY=$(op item get "${TITLE}" --fields "public key" --vault "${VAULT}") +jq -n --arg ssh_public_key "$SSH_PUBLIC_KEY" '{"ssh_public_key":$ssh_public_key}' diff --git a/terraform/kubernetes/terraform.tfvars b/terraform/kubernetes/terraform.tfvars new file mode 100644 index 0000000..4e87a74 --- /dev/null +++ b/terraform/kubernetes/terraform.tfvars @@ -0,0 +1,46 @@ +# 1Password variables +op_sa_token = "" +op_virtual_environment_vault_name = "" +op_virtual_environment_item_name = "" +op_ssh_vault_name = "" +op_ssh_key_name = "" + +# K3s cluster nodes +nodes = [ + { + name = "control01" + description = "K3s Control Node" + ip = "" + memory = 8192 + cores = 4 + username = "" + password = "" + }, + { + name = "worker01" + description = "K3s Worker Node 1" + ip = "" + memory = 4096 + cores = 2 + username = "" + password = "" + }, + { + name = "worker02" + description = "K3s Worker Node 2" + ip = "" + memory = 4096 + cores = 2 + username = "" + password = "" + }, + { + name = "worker03" + description = "K3s Worker Node 3" + ip = "" + memory = 4096 + cores = 2 + username = "" + password = "" + } +] diff --git a/terraform/kubernetes/variables.tf b/terraform/kubernetes/variables.tf new file mode 100644 index 0000000..d754702 --- /dev/null +++ b/terraform/kubernetes/variables.tf @@ -0,0 +1,75 @@ +variable "op_sa_token" { + description = "1Password Service Account token" + type = string + sensitive = true +} + +variable "op_virtual_environment_vault_name" { + description = "1Password vault name containing the virtual environment item" + type = string +} + +variable "op_virtual_environment_item_name" { + description = "1Password virtual environment item name" + type = string +} + +variable "op_ssh_vault_name" { + description = "1Password vault name containing the SSH key" + type = string +} + +variable "op_ssh_key_name" { + description = "1Password SSH key name" + type = string +} + +variable "virtual_environment_username" { + description = "Proxmox VE Username" + type = string + default = "root@pam" +} + +variable "virtual_environment_node" { + description = "Name of the Proxmox VE node" + type = string + default = "proxmox01" +} + +variable "virtual_environment_template_vm_id" { + description = "ID of the Proxmox VE template VM used for cloning" + type = number + default = 9000 +} + +variable "virtual_environment_os_disk_datastore_id" { + description = "ID of the Proxmox VE datastore used for the OS disk" + type = string + default = "ssd-samsung" +} + +variable "virtual_environment_data_disk_datastore_id" { + description = "ID of the Proxmox VE datastore used for the data disk" + type = string + default = "ssd-crucial" +} + +variable "nodes_gateway" { + description = "Gateway IP address for the K3s nodes" + type = string + default = "192.168.0.1" +} + +variable "nodes" { + description = "K3s nodes" + type = list(object({ + name = string + description = string + ip = string + memory = number + cores = number + username = string + password = string + })) + default = [] +}