Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

K3s Cluster Module

Terraform Registry License

Terraform module to deploy a K3s Kubernetes cluster on Turing Pi 2.5 nodes running Armbian (or other Debian-based distributions).

This module connects to nodes via SSH, prepares them (packages, NVMe storage), and installs K3s using the official installation script.

Usage

Basic Cluster (SSH Key)

module "k3s" {
  source  = "jfreed-dev/modules/turingpi//modules/k3s-cluster"
  version = ">= 1.3.0"

  cluster_name = "my-cluster"

  control_plane = {
    host     = "192.168.1.101"
    ssh_user = "root"
    ssh_key  = file("~/.ssh/id_rsa")
  }

  workers = [
    {
      host     = "192.168.1.102"
      ssh_user = "root"
      ssh_key  = file("~/.ssh/id_rsa")
    },
    {
      host     = "192.168.1.103"
      ssh_user = "root"
      ssh_key  = file("~/.ssh/id_rsa")
    },
    {
      host     = "192.168.1.104"
      ssh_user = "root"
      ssh_key  = file("~/.ssh/id_rsa")
    }
  ]

  kubeconfig_path = "./kubeconfig"
}

Basic Cluster (SSH Password)

module "k3s" {
  source  = "jfreed-dev/modules/turingpi//modules/k3s-cluster"
  version = ">= 1.3.0"

  cluster_name = "my-cluster"

  control_plane = {
    host         = "192.168.1.101"
    ssh_user     = "root"
    ssh_password = var.ssh_password
  }

  workers = [
    {
      host         = "192.168.1.102"
      ssh_user     = "root"
      ssh_password = var.ssh_password
    }
  ]

  kubeconfig_path = "./kubeconfig"
}

variable "ssh_password" {
  type      = string
  sensitive = true
}

With NVMe Storage (for Longhorn)

module "k3s" {
  source  = "jfreed-dev/modules/turingpi//modules/k3s-cluster"
  version = ">= 1.3.0"

  cluster_name = "homelab"
  k3s_version  = "v1.31.4+k3s1"

  control_plane = {
    host     = "192.168.1.101"
    ssh_user = "root"
    ssh_key  = file("~/.ssh/id_rsa")
  }

  workers = [
    { host = "192.168.1.102", ssh_user = "root", ssh_key = file("~/.ssh/id_rsa") },
    { host = "192.168.1.103", ssh_user = "root", ssh_key = file("~/.ssh/id_rsa") },
    { host = "192.168.1.104", ssh_user = "root", ssh_key = file("~/.ssh/id_rsa") }
  ]

  # Enable NVMe storage for Longhorn
  nvme_storage_enabled = true
  nvme_device          = "/dev/nvme0n1"
  nvme_mountpoint      = "/var/lib/longhorn"
  nvme_filesystem      = "ext4"
  nvme_control_plane   = true

  # Longhorn prerequisites (enabled by default)
  install_open_iscsi = true
  install_nfs_common = true

  kubeconfig_path = "./kubeconfig"
}

Prerequisites

  1. Nodes pre-flashed with Armbian - Use the flash-nodes module to flash Armbian
  2. SSH access configured - SSH key or password authentication
  3. Network connectivity - Nodes must reach each other and the internet

Requirements

Name Version
terraform >= 1.0
local >= 2.0
null >= 3.0
random >= 3.0
tls >= 4.0

Providers

Name Version
local >= 2.0
null >= 3.0
random >= 3.0

Inputs

Name Description Type Default Required
cluster_name Name of the K3s cluster string n/a yes
control_plane Control plane node configuration
object({
host = string
ssh_user = string
ssh_key = optional(string)
ssh_password = optional(string)
ssh_port = optional(number, 22)
hostname = optional(string)
})
n/a yes
cluster_cidr CIDR for pod networking string "10.42.0.0/16" no
cluster_dns Cluster DNS service IP string "10.43.0.10" no
cluster_token Cluster token for node authentication. Auto-generated if not specified. string "" no
disable_local_storage Disable the built-in local-path storage provisioner bool false no
disable_servicelb Disable the built-in ServiceLB (Klipper) bool true no
disable_traefik Disable the built-in Traefik ingress controller bool true no
extra_agent_args Extra arguments for K3s agent list(string) [] no
extra_server_args Extra arguments for K3s server list(string) [] no
flannel_backend Flannel backend (vxlan, host-gw, wireguard-native, none) string "vxlan" no
install_nfs_common Install nfs-common for NFS storage support bool true no
install_open_iscsi Install open-iscsi for Longhorn (required for Longhorn) bool true no
k3s_version K3s version to install (e.g., v1.31.4+k3s1). Leave empty for latest stable. string "" no
kubeconfig_path Path to write kubeconfig file (optional) string null no
nvme_control_plane Configure NVMe on control plane node (in addition to workers) bool true no
nvme_device NVMe device path string "/dev/nvme0n1" no
nvme_filesystem Filesystem type for NVMe partition (ext4, xfs) string "ext4" no
nvme_mountpoint Mount point for NVMe storage string "/var/lib/longhorn" no
nvme_storage_enabled Enable NVMe storage configuration for Longhorn bool false no
service_cidr CIDR for service networking string "10.43.0.0/16" no
workers Worker node configurations
list(object({
host = string
ssh_user = string
ssh_key = optional(string)
ssh_password = optional(string)
ssh_port = optional(number, 22)
hostname = optional(string)
}))
[] no

Outputs

Name Description
api_endpoint Kubernetes API endpoint
cluster_name Cluster name
cluster_token Cluster token for joining nodes
control_plane_host Control plane host IP/hostname
k3s_version Installed K3s version
kubeconfig Kubeconfig for cluster access
kubeconfig_path Path to kubeconfig file (if written)
nvme_enabled Whether NVMe storage is configured
nvme_mountpoint NVMe mount point (if enabled)
worker_hosts Worker node host IPs/hostnames

Node Configuration Object

{
  host         = string           # IP or hostname
  ssh_user     = string           # SSH username
  ssh_key      = optional(string) # SSH private key content
  ssh_password = optional(string) # SSH password
  ssh_port     = optional(number) # SSH port (default: 22)
  hostname     = optional(string) # Custom hostname
}

K3s Configuration

By default, this module:

  • Disables Traefik - Use ingress-nginx addon instead
  • Disables ServiceLB - Use MetalLB addon instead
  • Installs open-iscsi - Required for Longhorn
  • Installs nfs-common - For NFS storage support

These defaults are optimized for use with the addon modules (MetalLB, Ingress-NGINX, Longhorn).

Using with Addons

After cluster creation, deploy addons using the kubeconfig output:

# K3s cluster
module "k3s" {
  source = "jfreed-dev/modules/turingpi//modules/k3s-cluster"
  # ... configuration
}

# Configure Kubernetes providers
provider "helm" {
  kubernetes {
    config_path = module.k3s.kubeconfig_path
  }
}

provider "kubectl" {
  config_path = module.k3s.kubeconfig_path
}

# MetalLB for LoadBalancer services
module "metallb" {
  source     = "jfreed-dev/modules/turingpi//modules/addons/metallb"
  depends_on = [module.k3s]
  ip_range   = "192.168.1.200-192.168.1.220"
}

# Ingress NGINX
module "ingress" {
  source          = "jfreed-dev/modules/turingpi//modules/addons/ingress-nginx"
  depends_on      = [module.metallb]
  loadbalancer_ip = "192.168.1.200"
}

# Longhorn storage (with NVMe)
module "longhorn" {
  source            = "jfreed-dev/modules/turingpi//modules/addons/longhorn"
  depends_on        = [module.k3s]
  default_data_path = "/var/lib/longhorn"
}

# Monitoring
module "monitoring" {
  source     = "jfreed-dev/modules/turingpi//modules/addons/monitoring"
  depends_on = [module.longhorn]

  grafana_admin_password = var.grafana_password
  storage_class          = "longhorn"
}

# Portainer
module "portainer" {
  source          = "jfreed-dev/modules/turingpi//modules/addons/portainer"
  depends_on      = [module.metallb]
  loadbalancer_ip = "192.168.1.201"
}

Differences from Talos

Feature K3s (Armbian) Talos
OS Armbian/Debian Talos Linux
Access SSH talosctl API
Updates apt + k3s script Image-based
Customization Full Linux Limited (secure)
NVMe Setup Partition + mount Machine config
Storage Default local-path None

Troubleshooting

SSH Connection Failed

  • Verify node is accessible: ssh root@<ip>
  • Check SSH key permissions: chmod 600 ~/.ssh/id_rsa
  • Ensure node has completed boot

K3s Installation Timeout

  • Check node internet connectivity
  • Verify DNS resolution on nodes
  • Review logs: journalctl -u k3s

Worker Not Joining

  • Verify control plane is ready
  • Check network connectivity between nodes
  • Review agent logs: journalctl -u k3s-agent

NVMe Not Detected

  • Verify device exists: lsblk
  • Check NVMe is properly seated
  • Device may be /dev/nvme0n1 or similar

License

Apache 2.0 - See LICENSE for details.