MetalLB controls the cluster's network, so its security can't be ignored. This episode covers RBAC for the controller and speaker, hardening the namespace, restricting access to management and health check ports, and protecting MetalLB configuration from unauthorized changes.

MetalLB is an extraordinarily sensitive component: it decides which IPs are used, which routes are advertised to the network, and who announces IPs. A compromise on MetalLB could mean routing hijacking inside your own network. That's why security & access control isn't optional — it's a requirement for any serious cluster.
Episode 14 covers four layers of MetalLB security: RBAC permissions for the controller and speaker, hardening the namespace, restricting access to management and health check ports, and protecting configuration so only authorized people can change the cluster's network behavior.
Each MetalLB component has its own ServiceAccount and Role with least-privilege permissions. The controller needs access to Services, Endpoints, and MetalLB CRDs; the speaker needs access to nodes and Services; neither needs cluster admin.
Look at the permissions already installed:
kubectl get clusterrole | grep -i metallb
kubectl describe clusterrole metallb-system:controller
kubectl describe clusterrole metallb-system:speakerkubectl describe clusterrole metallb-system:controller shows the list of resources the controller can read or modify. kubectl describe clusterrole metallb-system:speaker shows the same for the speaker.
Make sure the pods run with the correct ServiceAccount, not default:
kubectl get pods -n metallb-system -o jsonpath='{.items[*].spec.serviceAccountName}'
kubectl auth can-i --list -n metallb-systemThe output of kubectl get pods -n metallb-system -o jsonpath='{.items[*].spec.serviceAccountName}' should show the dedicated MetalLB service account names. If default appears, there's a configuration problem that must be fixed immediately.
The metallb-system namespace must be a locked-down area. Anyone who can create or modify IPAddressPool, BGPPeer, and advertisements can change the cluster's network behavior. Use RBAC to restrict this:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: metallb-config-admin
namespace: metallb-system
rules:
- apiGroups:
- metallb.io
resources:
- ipaddresspools
- l2advertisements
- bgpadvertisements
- bgppeers
verbs:
- get
- list
- watch
- create
- update
- deleteThis metallb-config-admin Role grants full permissions on MetalLB CRDs only within the metallb-system namespace, without any other permissions. Bind it with a RoleBinding to the responsible team — for example platform engineering — and don't give this access to ordinary developers.
A recommended practice in shared environments is to split pool management per team. For example, team A can only manage the tim-a-pool pool, while team B only manages tim-b-pool, via a combination of Role and ResourceName in RBAC.
The speaker and controller expose endpoints on specific ports:
These ports should only be reachable from inside the cluster, not from the internet. Restrict them with a NetworkPolicy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: metallb-metrics-internal
namespace: metallb-system
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: metallb
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports:
- protocol: TCP
port: 7472This NetworkPolicy only allows traffic to port 7472 from the monitoring namespace (where Prometheus lives). All other sources are blocked. If your CNI supports NetworkPolicy (Calico, Cilium), this policy is very effective.
MetalLB health checks run via HTTP probes. Make sure these probes run and correctly flag unhealthy components:
kubectl get deployment metallb-controller -n metallb-system -o yaml | grep -A5 livenessProbekubectl get deployment metallb-controller -n metallb-system -o yaml | grep -A5 livenessProbe shows the controller's liveness probe configuration. A wrong probe can cause pods to restart constantly in production — important to check when tuning.
As discussed in episode 10, the validating webhook prevents invalid configurations from entering. But the webhook doesn't prevent authorized people from making unwanted changes. The second layer is GitOps: store all MetalLB configuration in a repository and apply it through a pipeline, not via manual kubectl apply from personal machines.
IPAddressPool, BGPPeer, or advertisements are deleted or modified.delete MetalLB resources — a wrong pool deletion can take down Services.Episode 14 completes security & access control: minimal RBAC for the controller and speaker, hardening the namespace, a NetworkPolicy for management and health check ports, and configuration protection via GitOps and audit.
Key takeaways:
kubectl auth can-i --list -n metallb-system checks permissions.metallb-system namespace must be restricted to authorized people only.In the next episode, episode 15, we'll discuss high availability & failover — leader election and failover in Layer 2, failover time and ARP behavior, then BGP high availability with multi-node ECMP, path monitoring, and handling failed peers.