My Journey to Kubernetes onto Bare Metal — Part 4: MetalLB

Richard Nunez
2 min readApr 29, 2020


Implementing MetalLB

Why I did what I did

This next guide will show you how I installed and configured MetalLB. Learn more about MetalLB. If you need MetalLB then you do not need my explanation, which will fall short of a proper introduction and lesson. TL;DR It will let you access your kubernetes services externally without needing to spend money an an external load-balancer or forwarder.

The way I configured my system was after days and weeks of experimenting different combinations of the underlying components (network connections, MetalLB, Traefik, Cert-Manager, and External-DNS. So this combination worked for me. There were plenty of guides on the internet to install and configure MetalLB but they were either out of date or structured to work with Nginx, which I preferred to use Traefik in its place.

Step 1

Just use the Manifest installation process with these commands:

kubectl apply -f
kubectl apply -f
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)

Step 2

Before you can start using MetalLB you must create allocate a pool of ip address to use that will be exposed to the internet. These must be real unused public IP address. Since my cluster will span both a public and privately exposed network I chose to create two pools:

apiVersion: v1
kind: ConfigMap
namespace: metallb-system
name: config
config: |
- name: private
protocol: layer2
- name: public
protocol: layer2

You will notice above that I have two pools, one for my internal private network (in the 192.168.x.x subnet) and then my public-facing IP address that I have from AT&T. There are some apps and service that I want to keep internal and others that I want exposed to the public.

You are done!

How to use MetalLB

We won’t be using MetalLB in this guide since we will be applying this to Traefik. But if you want to use it with any service then you must apply an annotation of “ <name of address pool>” from the configuration above. For me the only options are “private” or “public” since those are the names I assigned the IP address pool in the configuration file above. Below you see a sample service with using the metallb annotation.

apiVersion: v1
kind: Service
name: <your_service_name>
namespace: <namespaces goes here>
annotations: private

To see if it is working please list the services. The example below lists services for all namespaces.

$ kubectl get services --all-namespacesNAMESPACE NAME             TYPE         CLUSTER-IP     EXTERNAL-IP      PORT(S)
traefik traefik-internal LoadBalancer 80:31054/TCP,443:30631/TCP

Notice that you will finally have a value listed for “EXTERNAL-IP”. It should grab the first IP address from your pool address that you assigned. For me my first address was “” so that is what was assigned.


Part 5: Cert-Manager



Richard Nunez

A DevOps Engineer specializing in CI/CD and Containerization. Automate, Automate, Automate.