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:
# expected output:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Teardown
Destroy the cluster
k3d cluster delete local-k8s
Conclusion
This post has gone over one of many ways to deploy a Kubernetes cluster to a local development environment. You can find an accompanying Github repository here for reference source