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