How to Create a Kubernetes Cluster and Load Balancer for Local Development
Overview
This guide will show you one of many ways that you can set up and tear down a local Kubernetes cluster with a load balancer for use as a local development environment.
In this article, we will be leveraging Rancher's k3d to run a local Kubernetes cluster and installing MetalLB as a Load Balancer to our cluster. Some of the use cases and reasons for setting up an environment like this (but not limited to):
- You don't want to incur the cost of working with a Kubernetes cluster in the cloud
- Fast setup and teardown
- Full unrestricted access to your own Kubernetes cluster
- Rapid prototyping
- Any other reasons you can think of (which probably also suffice too as well)
Prerequisites
- Docker
- k3d (v4.4.6)
- jq
- kubectl
- lens (optional)
Setup
Create the Cluster and validate it's creation:
# create the k3d cluster
k3d cluster create local-k8s --servers 1 --agents 3 --k3s-server-arg --no-deploy=traefik --wait
# set kubeconfig to access the k8s context
export KUBECONFIG=$(k3d kubeconfig write local-k8s)
# validate the cluster master and worker nodes
kubectl get nodes
Determine your Load Balancer's ingress range by obtaining it's cidr block. This range will depend on the Docker network that your k3d cluster leverages. The script below will help determine and prescribe a suggested range.
# determine loadbalancer ingress range
cidr_block=$(docker network inspect k3d-local-k8s | jq '.[0].IPAM.Config[0].Subnet' | tr -d '"')
cidr_base_addr=${cidr_block%???}
ingress_first_addr=$(echo $cidr_base_addr | awk -F'.' '{print $1,$2,255,0}' OFS='.')
ingress_last_addr=$(echo $cidr_base_addr | awk -F'.' '{print $1,$2,255,255}' OFS='.')
ingress_range=$ingress_first_addr-$ingress_last_addr
Deploy the Load Balancer, which leverages MetalLB:
# deploy metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml
# configure metallb ingress address range
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- $ingress_range
EOF
Validation
Create an Nginx test deployment and expose via a Load Balancer. If the Load Balancer is working correctly, an external ip address should be assigned by Metallb.
# create a deployment (i.e. nginx)
kubectl create deployment nginx --image=nginx
# expose the deployments using a LoadBalancer
kubectl expose deployment nginx --port=80 --type=LoadBalancer
# obtain the ingress external ip
external_ip=$(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
# test the loadbalancer external ip
curl $external_ip
Expected output: