3 minutes
Terranetes
Deploying Kubernetes is usually a massive headache. You either suffer through opaque, hundred-line Ansible playbooks that fail halfway through, or you bind yourself to complex, vendor-locked managed services like EKS or GKE.
If you are running on your own hardware or open cloud platforms like OpenStack, your options are even worse. You are left managing state across multiple detached tools: one to spin up the VMs, another to compile PKI certificates, and a third to bootstrap the cluster.
To fix this fragmented nightmare, I built Terranetes (which eventually evolved into its own GitHub organization). It is a complete, declarative Kubernetes bootstrap installer written entirely in native HashiCorp Configuration Language (HCL/Terraform).
graph TD
User[Terraform Apply] -->|k8s Schema Variable| Core[Core Module: core/kubernetes]
Core -->|1. Generate PKI & Certs| Ign[Ignition Generator]
Core -->|2. CoreOS Ignition Configs| Ign
Core -->|3. Manifests: Calico, Canal| Ign
Core --> Provider[Provider Module: providers/openstack]
Provider -->|Provisions VMs, Net, LBaaSv2| Infra[OpenStack / Cloud Infrastructure]
Ign -->|Injects Ignition Payloads| Infra
Separating compile from provision
The key design breakthrough of Terranetes is the complete decoupling of cluster compilation from cloud provisioning.
The Core Module (./core/kubernetes) is completely cloud-agnostic. It takes a single, rich HCL declarative variable specifying your Kubernetes version, CNI plugin choice (Canal, Calico, or Weavenet), nodes, and storage classes. It then runs in-memory to generate all the PKI certs, etcd configs, and CoreOS Ignition payloads.
module "k8s" {
source = "./core/kubernetes"
k8s = var.k8s
}
module "openstack" {
source = "./providers/openstack"
k8s = module.k8s.k8s
ignition = module.k8s.ignition
admin = module.k8s.admin
}
The Provider Module (./providers/openstack) takes the generated static assets from the Core module. It provisions the virtual network, subnets, routers, security groups, OpenStack LBaaSv2 load balancers, and virtual machines. It then injects the custom Ignition boot-configurations straight into the provisioning API.
Everything in a single state file
Because everything is orchestrated by Terraform, you dont need to keep track of external states or configuration drifts. If you scale up your compute worker array in the HCL schema, Terraform automatically compiles the new Ignition files, provisions the additional virtual machines, attaches the security groups, and registers them to the load balancer in a single run.
variable "k8s" {
default = {
version = "1.14.3"
pubkeys = ["ssh-ed25519 AAAAC3..."]
cni = {
type = "canal"
version = "latest"
}
nodes = [
{ labels = ["master"] },
{ labels = ["compute"] },
{ labels = ["compute"] }
]
network = {
cidr = "192.168.123.0/24"
dhcp = true
fip = true
}
}
}
This single-state approach makes teardowns or recreations incredibly simple. When you run terraform destroy, it cleanly prunes every CNI bridge, virtual network, VM instance, and PKI secret without leaving orphaned assets polluting your cloud account.
It is a beautifully modular way to look at Kubernetes bootstrapping, and it proves that Terraform is more than capable of managing complex system lifecycles.
- Codebase & Contributing: Terranetes on Github
Related Content:
- Rebuilding the Looking Glass: Stateless, High-Performance Network Diagnostics at Scale May 23
- cline-vertex-gw May 20
- Zero Trust in GKE: Envoy, OPA, and Workload Identity May 6
- Oubliette: Clarifying the Protection Bounds and UDP Reflection May 2
- Exploiting TCP Handshake Quirks for IP Verification Apr 18