Terraforming Linode LKE!
by Stefan Krantz
Terraform is an open-source infrastructure-as-code (IaC) tool that allows you to define, provision, and manage infrastructure resources such as servers, databases, networks, and cloud services in a declarative manner.
With Terraform, you can create a description of your desired infrastructure configuration in a simple and human-readable syntax, known as HashiCorp Configuration Language (HCL), or JSON. Then, Terraform will apply the configuration to create, modify, or delete resources based on the desired state.
Terraform is particularly useful in modern cloud computing environments where infrastructure is becoming increasingly dynamic and complex, and resources are provisioned and de-provisioned on-demand. It enables teams to manage infrastructure as code, apply version control, and automate the provisioning process, making it easier to maintain infrastructure and reduce manual errors. Terraform supports multiple cloud providers, including Amazon Web Services (AWS), Google Cloud Platform (GCP) and Linode.
This guide will walk you through step-by-step launching a Linode Kubernetes Engine (LKE) with Terraform.
Tools needed for this guide
1. Download and Install Terraform:
- Mac/Linux: Head over to Terraform installation guide
- Windows / Powershell:
mkdir c:\terraform cd c:\terraform curl.exe -LO "https://releases.hashicorp.com/terraform/1.5.0/terraform_1.5.0_windows_amd64.zip" Expand-Archive C:\Terraform\terraform_1.5.0_windows_amd64.zip mv C:\Terraform\terraform_1.5.0_windows_amd64\terraform.exe c:\terraform\terraform.exe rm C:\Terraform\terraform_1.5.0_windows_amd64.zip -force rm C:\Terraform\terraform_1.5.0_windows_amd64 -force $env:Path += ';C:\terraform'
2. Generate Linode token and save it in a secure place
3. Download and Install kubectl
- Linux:
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl
- MacOS:
brew install kubernetes-cli
(note: if you do not have brew, head over to brew)
- Windows / PowerShell:
mkdir c:\kubectl cd c:\kubectl curl.exe -LO "https://dl.k8s.io/release/v1.27.2/bin/windows/amd64/kubectl.exe" $env:Path += ';C:\kubectl'
Terraform definition files
- Create a directory on your local machine that you feel comfortable with, ie:
$ mkdir tf-linode $ cd tf-linode
Create the following files in the folder
- provider.tf:
terraform {
required_providers {
linode = {
source = "linode/linode"
version = "1.29.4"
}
}
}
//Use the Linode Provider
provider "linode" {
token = var.token
}
- variables.tf:
variable "token" {
description = "Your Linode API Personal Access Token. (required)"
}
variable "k8s_version" {
description = "Kubernetes version"
}
variable "region" {
description = "Linode Region"
}
- terraform.tfvars:
k8s_version = "1.27"
region = "se-sto"
(note: List of available kubernetes versions can be found here) (list of regions can be found through API or CLI)
- main.tf
resource "linode_lke_cluster" "my-cluster" {
label = "lke-cluster"
k8s_version = var.k8s_version
region = var.region
pool {
type = "g6-standard-2"
count = 1
}
# Prevent the count field from overriding autoscaler-created nodes
lifecycle {
ignore_changes = [
pool.0.count
]
}
}
//Export this cluster's attributes
output "kubeconfig" {
value = linode_lke_cluster.my-cluster.kubeconfig
sensitive = true
}
output "api_endpoints" {
value = linode_lke_cluster.my-cluster.api_endpoints
}
output "status" {
value = linode_lke_cluster.my-cluster.status
}
output "id" {
value = linode_lke_cluster.my-cluster.id
}
output "pool" {
value = linode_lke_cluster.my-cluster.pool
}
(note: we are using the g6-standard-2 instance type, but the list of instance types are available through the API or CLI)
Lets run some terraform!
- Start with setting your TF_VAR_token Environment variable
Mac/Linux:$ export TF_VAR_token=your-secret-linode-token-created-at-the-start-of-this-guide
Windows/Powershell:
$Env:TF_VAR_token="your-secret-linode-token-created-at-the-start-of-this-guide"
- Execute a Init
$ terraform init
- Execute a Plan
$ terraform plan
- Execute an Apply
$ terraform apply
- Create kubeconfig configuration:
Mac/Linux:$ terraform output -raw kubeconfig | base64 -d > lke-cluster-config.yaml
Windows/Powershell:
terraform output -raw kubeconfig | %{[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($_))} > lke-cluster-config.yaml
Test connection to kubernetes:
- Set KUBECONFIG environment variable (Make sure to run these commands where you have your TF files and the lke-cluster-config.yaml file)
Mac/Linux:
$ export KUBECONFIG=$(pwd)/lke-cluster-config.yaml
Windows/Powershell:
$Env:KUBECONFIG = "$(pwd)\lke-cluster-config.yaml"
- Get node list
$ kubectl get nodes
If successful, output you would see will be similar to this, showing 3 active nodes:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
lke103403-154758-643e56400ab1 Ready <none> 5m26s v1.25.4
lke103403-154758-643e56406fd7 Ready <none> 5m28s v1.25.4
lke103403-154758-643e5640d15b Ready <none> 5m46s v1.25.4
Whats next?
Now that you have a cluster running, you can explore what to use it for! For example, you might explore the world of Helm here on packaged software ready to run in LKE!
You might want to wrap your cluster in a cloud firewall?
create file
- firewall.tf
resource "linode_firewall" "my-cluster" { label = "my-cluster-firewall" inbound { label = "kubelet" action = "ACCEPT" protocol = "TCP" ports = "10250" ipv4 = ["192.168.128.0/17"] } inbound { label = "wireguard" action = "ACCEPT" protocol = "UDP" ports = "51820" ipv4 = ["192.168.128.0/17"] } inbound { label = "calico" action = "ACCEPT" protocol = "TCP" ports = "179" ipv4 = ["192.168.128.0/17"] } inbound { label = "nodeports" action = "ACCEPT" protocol = "TCP" ports = "30000-32767" ipv4 = ["192.168.128.0/17"] } inbound { label = "ipencap" action = "ACCEPT" protocol = "ipencap" ipv4 = ["192.168.128.0/17"] } inbound_policy = "DROP" outbound_policy = "ACCEPT" linodes = linode_lke_cluster.my-cluster.pool.0.nodes.*.instance_id }
(note: Keep in mind that recycling nodes in an LKE cluster will cause the nodes to be deleted and replaced. Node recycle is required during K8s version upgrades, which will be necessary at least once per year. If you recycle the nodes in your LKE cluster, the list of Linodes in the Firewall will need to be updated either manually or by re-running terraform apply.)
- Execute an Apply one more time
$ terraform apply
Stay tuned as I will add links to follow-up posts on specific usecases for LKE!
All The best! Stefan
tags: