Preface

In this article I am not going to be going through all the ports you need to configure on your firewalls, for ease of following this guide I recommend disabling the firewall. That being said, you should never do that for production! I want to focus on the k8s stuff here, so decided to skip this for the sake of brevity.

Flannel Setup

First we are going to set up the network stack. There are lots of different choices, but I went with Flannel due to the ease of setup. You just need to apply the file from the URL. If you want to change the default subnet from 10.244. 0.0/16 you will need to download the file first and edit it. That being said, for most people that shouldn’t be required.

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

We then want to check if the flannel pods are running. You should see this:

kubectl get pods -A

If all went well, we can move onto the next part.

MetalLB

MetalLB is a locally hostable firewall. When you use cloud services, they often have their own offerings, but if you are running in a home lab, this is a good option.

We need to edit the config map first. Run this command, and you will be dropped into a text editor:

kubectl edit configmap -n kube-system kube-proxy

You are looking for a like with ipvs. Change the option strictARP to true.

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true

We can now install MetalLB by running this command:

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml

We will then want to check it by running:

kubectl get pods -A

Check that all the metallb-system are showing as running.

We will now want to create a file called ipaddresses.yaml with this as the contents:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - X.X.X.X-X.X.X.X
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system

You will want to replace the X.X.X.X to an IP that won’t be used by another device on your network. I recommend setting up a reserved range that DHCP can’t use. You will have to figure that stuff out by your self, as it is different from device to device. Also, I only allocated a range of 5 IPs, but we also will only be using on IP for this tutorial. We then want to apply it by running:

kubectl apply -f ipaddresses.yaml

Nginx Service

Now we want to create a file called nginx.yaml. This is just a container that runs the latest version of Nginx.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: Always
        ports:
          - containerPort: 80

We are also going to need a service, so create a file called nginx_service.yaml.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx-service
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None

We can now run::

kubectl apply -f nginx.yaml
kubectl apply -f nginx_service.yaml

Now when we run kubectl get services -A we should see: And if we navigate to the EXTERNAL-IP listed, we should see:

You now have a supper simple load balanced website. While it isn’t the best setup, it is a starting point for your home lab.

If you are interested on how to deploy a K8s stack with Terraform and Ansible, you might want to have a look at my previous blog article HERE