MetalLB consists of two main components: the metallb-controller, which allocates IPs from a pool, and the metallb-speaker, which announces IPs on each node. This episode explains the end-to-end workflow and the roles of the IPAddressPool, L2Advertisement, BGPAdvertisement, and BGPPeer CRDs.

Now that you understand MetalLB's history, it's time to lift the hood. Episode 2 explains MetalLB's core concepts and main architecture: which components run in the cluster, what each one does, and how they work together to turn a LoadBalancer Service into an IP reachable from outside.
MetalLB's architecture is actually simple — there are only two main binaries: metallb-controller and metallb-speaker. But understanding both roles is crucial, because almost all troubleshooting in the upcoming episodes (especially episodes 7 and 19) boils down to the questions "has the controller allocated the IP?" or "has the speaker announced the IP?"
The controller runs as a single Deployment (usually replicated to two for high availability) and is responsible for the management side:
IPAddressPool.The controller is the brain that makes allocation decisions. It never touches network traffic itself — it only records "this IP belongs to this Service".
The speaker runs as a DaemonSet — one pod on every node — and is responsible for the data plane side:
The speaker is the muscle that talks to the network. If the controller decides the IP, the speaker is the one that tells the network the IP lives here.
kubectl get pods -n metallb-systemAfter installation (episode 3), the output will show one or two metallb-controller pods and one metallb-speaker pod per node.
Here's the sequence that happens when you create a Service of type LoadBalancer:
spec.type: LoadBalancer and specify the port.IPAddressPool.status.loadBalancer.ingress[0].ip.kubectl get svc nginx
kubectl describe svc nginxIn kubectl describe svc nginx, you'll see LoadBalancer Ingress in the Status section and Events recording the controller's IP allocation. These two places are the starting point of every diagnosis.
Since v0.13, MetalLB configuration is no longer a ConfigMap, but Custom Resource Definitions (CRDs). There are four main CRDs you'll encounter constantly:
Defines the set of IPs the controller may use, either as a range or as a CIDR:
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250These two determine how IPs are announced. L2Advertisement is for Layer 2 mode, and BGPAdvertisement is for BGP mode. Advertisements are covered in full in episodes 5, 6, and 8.
Defines the router that becomes the peering partner in BGP mode, complete with ASN, peer address, and parameters such as hold time.
To get familiar with the architecture, make these three commands a habit:
kubectl get deployment -n metallb-system
kubectl get daemonset -n metallb-system
kubectl get crd | grep metallbkubectl get deployment -n metallb-system shows the controller, kubectl get daemonset -n metallb-system shows the speaker, and the CRD grep command shows all of MetalLB's Custom Resources. The speaker count always equals the node count — that's why the speaker is designed as a DaemonSet.
Separating the controller and speaker isn't arbitrary. A single controller ensures no duplicate IP allocations: only one brain decides who gets which IP. Meanwhile, speakers spread across every node ensure announcement is always close to the network: each node is ready to announce IPs without depending on a single central point.
Episode 2 opens up MetalLB's architecture: the controller allocates IPs, the speaker announces them, and the four CRDs form its configuration language. You also understand the end-to-end workflow from Service to external traffic.
Key takeaways:
status.loadBalancer.ingress and can be seen with kubectl describe svc.In the next episode, episode 3, we'll do the setup and installation of MetalLB — comparing installation via the metallb.yaml manifest and via Helm chart, verifying the controller and speaker pods, then creating the initial configuration with an IPAddressPool and the first advertisement. It's time to start typing!