Creating an Efficient and Lightweight Kubernetes Cluster on Linux with K3D, MetalLB, and Nginx Ingress

vishal acharya
5 min readAug 26, 2023

--

  1. Prerequisites
  2. Cluster Creation
  3. Enhancing with MetalLB Load Balancer
  4. Efficient Access with Nginx Ingress Controller
  5. Managing Your Cluster: Starting, Stopping, and Deleting

Prerequisites

Before diving into the setup, ensure that you have a basic understanding of Kubernetes concepts and have Docker installed on your Linux machine.

Cluster Creation

curl -sLS https://get.arkade.dev | sudo sh
arkade get k3d
sudo mv /home/vishal/.arkade/bin/k3d /usr/local/bin/

The process of setting up and initializing the cluster using the provided command.

k3d cluster create k8-lab --api-port 6550 --agents 1 --k3s-arg "--disable=traefik@server:0" --k3s-arg "--disable=servicelb@server:0" --no-lb --wait

Ensure that kubectl is Installed on Your System

arkade get kubectl
sudo mv /home/vishal/.arkade/bin/kubectl /usr/local/bin/

Enhancing with MetalLB Load Balancer

In Kubernetes, when you’re running on bare metal cluters, you won’t find the default network load balancer functionality. This means you’re limited to using Service types like ClusterIP or NodePort, and LoadBalancer won’t be available. But don’t worry, MetalLB comes to the rescue! It lets you have the load balancer service type even in bare metal Kubernetes setups.

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.3/manifests/namespace.yaml

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.3/manifests/metallb.yaml

The commands mentioned above will establish a fresh namespace called ‘metallb-system’ within your Kubernetes cluster. This namespace is specifically designed for MetalLB. It will then proceed to deploy essential resources such as cluster roles and bindings, pod security policies, and the deployment itself for MetalLB

Configure MetalLB

sudo apt install jq -y

cidr_block=$(docker network inspect <check docker network> | jq '. [0].IPAM.Config[0].Subnet' | tr -d '"')

by this command docker netwrok ls

it’s look like k3d-k8lab put that value

When you run the command docker network ls, you'll see a list of Docker networks. Look for the one labeled 'k3d-k8lab'. You'll need to use the name of this network in the subsequent steps

cidr_block=$(docker network inspect k3d-k8-lab | jq '. [0].IPAM.Config[0].Subnet' | tr -d '"')

base_addr=${cidr_block%???}

first_addr=$(echo $base_addr | awk -F'.' '{print $1,$2,$3,240}' OFS='.')

range=$first_addr/29

Create a configmap

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- $range
EOF

The configuration provided above has the capacity to create a maximum of 8 load balancers

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx

kubectl apply -f deployment.yaml

The outcome you can expect is as follows:

nginx                      LoadBalancer   10.43.223.116   172.18.0.242   80:32017/TCP                  17s

If you no longer require Nginx after testing, you can proceed to delete it.

kubectl delete -f deployment.ymal

Efficient Access with Nginx Ingress Controller

Let’s now proceed with the installation of the Nginx Ingress Controller

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress- nginx/controller-v1.0.4/deploy/static/provider/aws/deploy.yaml

Wait for the controller pod to be fully initialized.

The outcome you can expect is as follows:

NAME                                            READY   STATUS      RESTARTS        AGE
pod/ingress-nginx-admission-patch-chdhx 0/1 Completed 1 4d1h
pod/ingress-nginx-admission-create-5hzs5 0/1 Completed 0 4d1h
pod/ingress-nginx-controller-6787d6dccf-8kmnh 1/1 Running 2 (3h13m ago) 4d1h
NAME                                         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
service/ingress-nginx-controller-admission ClusterIP 10.43.186.33 <none> 443/TCP 4d1h
service/ingress-nginx-controller LoadBalancer 10.43.5.93 172.18.0.240 80:32324/TCP,443:31487/TCP 4d1h
service/aks-helloworld-one ClusterIP 10.43.124.141 <none> 80/TCP 4d1h
service/aks-helloworld-two ClusterIP 10.43.222.87 <none> 80/TCP 4d1h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 4d1h
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-6787d6dccf 1 1 1 4d1h
NAME COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-patch 1/1 11s 4d1h
job.batch/ingress-nginx-admission-create 1/1 11s 4d1h

Now, open the load balancer IP in your browser

The outcome you can expect is as below:

Next, let’s expose the application using the Nginx load balancer

Deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: hello-world.info # Specify the host
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80

Add a host entry in your laptop or desktop’s hosts file, linking the load balancer’s IP with the specified domain

sudo nano /etc/hosts

and add like this

172.18.0.240 hello-world.info

The Load Balancer IP and Your Ingress-Inserted Domain and you can add Manny domain entries as per requirement

Managing Your Cluster: Starting, Stopping, and Deleting

K3d cluster can be stopped when not in use and can be started again.

To list K3d clusters: k3d cluster list

To stop a running cluster k3d cluster stop k8-lab

To start a stopped cluster k3d cluster start k8-lab

To delete a cluster k3d cluster delete k8-lab

Throughout this guide, we embarked on a journey to construct a nimble and resource-conscious Kubernetes cluster using K3d, skillfully supplemented by the prowess of MetalLB and Nginx Ingress Controller. By prioritizing simplicity without compromising capabilities, we’ve unveiled a realm of opportunities for development, testing, and deployment. As you navigate the dynamic terrain of container orchestration, remember that the potential of lightweight solutions can catalyze boundless innovation and productivity. Armed with this newfound streamlined knowledge, you’re now poised to embrace the efficiency of your customized Kubernetes environment and embark on your containerization pursuits with renewed confidence

Hope you enjoyed it see you again.

--

--