A simple, clean OpenTofu template for deploying Kubernetes clusters on Linode (LKE) with optional monitoring.
- Simple & Clean: Flat structure with direct OpenTofu commands
- Cost Optimized: Start with ~$24/month for a single-node cluster
- Secure: Built-in firewall rules and network policies
- Production Ready: Autoscaling, HA control plane options
- Monitoring Included: Optional Prometheus, Grafana, and metrics-server
- OpenTofu or Terraform 1.6+
- kubectl
- Linode API token
- Linode CLI (optional)
# Option 1: Configure linode-cli (recommended)
linode-cli configure
# Option 2: Set environment variable
export LINODE_TOKEN='your-token-here'cd infrastructure
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your preferencescd infrastructure
# Initialize
tofu init
# Review the plan
tofu plan
# Deploy cluster with monitoring
tofu apply# Extract kubeconfig
tofu output -raw kubeconfig | base64 -d > kubeconfig.yaml
# Set environment variable
export KUBECONFIG=./kubeconfig.yaml
# Test connection
kubectl cluster-info
kubectl get nodesThe template includes an optional monitoring module that deploys:
- kube-prometheus-stack: Prometheus + Grafana + Alertmanager + Node Exporter + Kube State Metrics
- metrics-server: For
kubectl topcommands and HPA
After deployment completes (4-5 minutes), access Grafana:
# Get any node's IP address
kubectl get nodes -o wide
# Access Grafana via NodePort
# URL: http://<node-ip>:30300
# Default credentials: admin / adminOr use port-forwarding:
kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 3000:80
# Open http://localhost:3000Control monitoring via terraform.tfvars:
# Enable/disable monitoring components
monitoring_enable_prometheus_stack = true
monitoring_enable_metrics_server = true
# Grafana settings
monitoring_grafana_service_type = "NodePort" # or "ClusterIP", "LoadBalancer"
monitoring_grafana_nodeport = 30300
monitoring_grafana_admin_password = "admin" # Change for production!
# metrics-server settings
monitoring_metrics_server_insecure_tls = true # Set false for productionGet monitoring information:
tofu output monitoring_namespace
tofu output monitoring_grafana_nodeport
tofu output monitoring_components
tofu output -raw monitoring_access_instructionsAll configuration is done through infrastructure/terraform.tfvars.
project_name = "my-project"
environment = "dev"
cluster_name = "my-cluster"
region = "us-east"
k8s_version = "1.34"node_pools = [
{
type = "g6-standard-1" # ~$24/month per node
count = 3
autoscaler = {
min = 1
max = 3
}
}
]Available Node Types:
g6-standard-1: 1 vCPU, 2GB RAM (~$24/month) - Dev/testingg6-standard-2: 2 vCPU, 4GB RAM (~$36/month) - Small productiong6-standard-4: 4 vCPU, 8GB RAM (~$72/month) - Production
control_plane_ha = true # Adds ~$60/month for HA control planefirewall_enabled = true
firewall_allowed_ips = ["your.ip.address/32"] # Restrict access
firewall_inbound_policy = "DROP"| Configuration | Monthly Cost |
|---|---|
| Dev (1 node, g6-standard-1) | ~$24 |
| Small Prod (2 nodes, g6-standard-2) | ~$72 |
| Prod HA (3 nodes, g6-standard-2, HA control plane) | ~$168 |
LKE control plane (non-HA) is free. Prices subject to change.
# Initialize and deploy
tofu init
tofu plan
tofu apply
# Get outputs
tofu output
tofu output -raw kubeconfig | base64 -d > kubeconfig.yaml
# Destroy
tofu destroy.
├── README.md
├── CLAUDE.md # Claude Code instructions
├── LICENSE
├── infrastructure/
│ ├── main.tf # Main infrastructure
│ ├── variables.tf # Variable definitions
│ ├── outputs.tf # Output definitions
│ ├── terraform.tfvars.example # Example configuration
│ └── modules/
│ └── monitoring/ # Optional monitoring module
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── docs/ # Additional documentation
Design Philosophy:
- Simple, flat structure with minimal nesting
- Direct OpenTofu commands - no Makefile needed
- Single tfvars.example file
- Optional monitoring module for observability
- Restrict firewall access: Change
firewall_allowed_ipsfrom0.0.0.0/0to your IP - Token security: Never commit
LINODE_TOKENorterraform.tfvarsto git - State file: Contains sensitive data - store securely (consider remote state)
- Grafana password: Change
monitoring_grafana_admin_passwordfor production - metrics-server TLS: Set
monitoring_metrics_server_insecure_tls = falsefor production
- Architecture - Design decisions and cluster architecture
- Cost Analysis - Detailed cost breakdown
- Operations - Management and troubleshooting
- Examples - Sample workloads
MIT