Zeyang
3 min readJul 23, 2024

DevOps01: Setting Up a Local Kubernetes Cluster Using Terraform and Kind

When I want to run tests in a Kubernetes cluster, preparing the environment can be very challenging. Fortunately, we found that Kind is an easy-to-use tool for deploying Kubernetes clusters locally. This article will show you how to use Terraform and Kind to deploy a Kubernetes cluster on your local machine.

This is my github repo files:https://github.com/zeyangli/myiac/tree/main/k8s

1. Preparation

Install Docker

Install Terraform version 1.1.8 .

Install Kubectl (https://dl.k8s.io/release/v1.24.0/bin/linux/amd64/kubectl )

2. Write Kind resource

2.1. Define terraform providers

# providers
terraform {
required_providers {
kind = {
source = "tehcyx/kind"
version = "0.0.12"
}
null = {
source = "hashicorp/null"
version = "3.1.1"
}
}
}

provider "kind" {}

2.2. Define some variables

# define kubeconfig file path.
variable "kind_cluster_config_path" {
type = string
default = "~/.kube/config"
}

# screen output kubeconfig context
output "kubeconfig" {
value = kind_cluster.default.kubeconfig
}

2.3. Define kind_cluster configuration

resource "kind_cluster" "default" {
name = "devopscluster" # clusterName
node_image = "ccr.ccs.tencentyun.com/devopsvip/kind:v1.24.0" #kindest/node:v1.24.0 kind docker image
kubeconfig_path = pathexpand(var.kind_cluster_config_path) # kubeconfig
wait_for_ready = true # wait cluster ready

# kind
kind_config {
kind = "Cluster"
api_version = "kind.x-k8s.io/v1alpha4"

# Control node
node {
role = "control-plane"
kubeadm_config_patches = [
<<-EOT
kind: InitConfiguration
imageRepository: registry.aliyuncs.com/google_containers
networking:
serviceSubnet: 10.0.0.0/16
apiServerAddress: "0.0.0.0"
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
---
kind: KubeletConfiguration
cgroupDriver: systemd
cgroupRoot: /kubelet
failSwapOn: false
EOT
]
extra_port_mappings {
container_port = 80
host_port = 80
}
extra_port_mappings {
container_port = 443
host_port = 443
}
extra_port_mappings {
container_port = 6443
host_port = 6443
}
extra_mounts {
host_path = "./resolv.conf"
container_path = "/etc/resolv.conf"
}
}
# worker
node {
role = "worker"
# extra_mounts {
# host_path = "./resolv.conf"
# container_path = "/etc/resolv.conf"
# }
}
# worker
node {
role = "worker"
# extra_mounts {
# host_path = "./resolv.conf"
# container_path = "/etc/resolv.conf"
# }
}
}
}

depends_on = [kind_cluster.default]
}

2.4. Define ingress deploy commands

# null_resource to run some shell commands
resource "null_resource" "wait_for_instatll_ingress" {
triggers = {
key = uuid()
}

provisioner "local-exec" {
command = <<EOF
sleep 5
#kind load docker-image k8s.gcr.io/ingress-nginx/controller:v1.2.0 --name devopscluster
#kind load docker-image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1 --name devopscluster
kind load docker-image ccr.ccs.tencentyun.com/devopsvip/kube-webhook-certgen:v1.1.1 --name devopscluster
kind load docker-image ccr.ccs.tencentyun.com/devopsvip/controller:v1.2.0 --name devopscluster

kubectl create ns ingress-nginx
kubectl apply -f ingress.yaml -n ingress-nginx
printf "\nWaiting for the nginx ingress controller...\n"
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=90s
EOF
}

3. Pull docker images

docker pull ccr.ccs.tencentyun.com/devopsvip/kind:v1.24.0
docker pull ccr.ccs.tencentyun.com/devopsvip/kube-webhook-certgen:v1.1.1
docker pull ccr.ccs.tencentyun.com/devopsvip/controller:v1.2.0

4. Deploy

4.1. Init terraform environment

terraform init

4.2. Apply terraform resource

terraform apply --auto-approve

if deploy succsed, you can see the screen output.

5. Check Kubernetes cluster

kubectl get node
NAME STATUS ROLES AGE VERSION
devopscluster-control-plane Ready control-plane 2m53s v1.24.0
devopscluster-worker Ready <none> 2m19s v1.24.0
test-cluster-worker2 Ready <none> 2m20s v1.24.0
[root@zeyang-nuc-service k8s]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-fbh5n 0/1 Completed 0 5m41s
ingress-nginx-admission-patch-xttkh 0/1 Completed 0 5m41s
ingress-nginx-controller-7bd87766fb-lsv89 1/1 Running 0 5m41s

No responses yet