This episode guides you through installing MetalLB two ways: the metallb.yaml manifest and the Helm chart. After installing, you verify the controller and speaker pods, then create the initial configuration with your first IPAddressPool and L2Advertisement.

You'll now prove all the theory from episode 2. Episode 3 walks you through the real setup and installation of MetalLB: choosing between a manifest or a Helm chart, installing, verifying that the controller and speaker are running, then creating the initial configuration with an IPAddressPool and the first advertisement.
By the end of this episode, your cluster will have a functioning MetalLB foundation — ready to accept the first LoadBalancer Service in episode 7. Getting the installation right here will spare you from a whole host of strange problems in the episodes ahead.
Before running any commands, repeat the verification from episode 0:
kubectl get nodes
kubectl get svc -AMake sure all nodes are Ready and there are no conflicting Services. Note down the IP block you've prepared again — in this series we use 192.168.1.200 through 192.168.1.250.
MetalLB offers two official installation paths:
metallb-native.yaml file that can be applied directly with kubectl.metallb/metallb chart, which is easier to version and upgrade.Both produce the same resources. Choose based on your team's workflow; this series will show both.
The manifest path is the simplest. Download the resource file and apply it directly:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.16.1/config/manifests/metallb-native.yamlkubectl apply -f against the official manifest URL creates the metallb-system namespace, all CRDs, RBAC, the controller Deployment, and the speaker DaemonSet all at once. Always use a version tag (here v0.16.1), not the main branch, so the install is reproducible.
Wait a few seconds, then check the pod status:
kubectl get pods -n metallb-system
kubectl get deployment -n metallb-system
kubectl get daemonset -n metallb-systemThe controller should show status Running with ready count 1/1 (or 2/2 if you've configured HA), and the speaker should be Running on every node. If any pod is in CrashLoopBackOff, inspect the logs with kubectl logs — episode 19 covers this kind of troubleshooting.
Teams already using Helm usually pick this path:
helm repo add metallb https://metallb.github.io/metallb
helm repo update
helm install metallb metallb/metallb --namespace metallb-system --create-namespacehelm repo add metallb https://metallb.github.io/metallb registers the official MetalLB repository, and the helm install command creates a release named metallb in the metallb-system namespace. Verify with helm list -n metallb-system and kubectl get pods -n metallb-system.
The MetalLB chart provides values to customize images, controller replicas, resource limits, and tolerations. Version upgrades are also far more controlled:
helm upgrade metallb metallb/metallb --namespace metallb-system --version 0.16.1helm upgrade metallb metallb/metallb --version 0.16.1 will show a diff of the changes before executing, so you know exactly what's changing.
Installing MetalLB doesn't mean anything without configuration. The first resource to create is the IPAddressPool:
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250Without an advertisement, allocated IPs won't be announced to the network. For Layer 2 mode, create an L2Advertisement that references the pool:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: first-advert
namespace: metallb-system
spec:
ipAddressPools:
- first-poolApply both resources and verify:
kubectl apply -f ipaddresspool.yaml
kubectl apply -f l2advertisement.yaml
kubectl get ipaddresspool
kubectl get l2advertisementkubectl get ipaddresspool should show the pool with a ready status, and kubectl get l2advertisement should show the advertisement referencing that pool. At this point, MetalLB is ready to use.
Tip
Creating the pool first and then the advertisement is a good habit, but it's not actually mandatory — an advertisement can reference a pool that doesn't exist yet because MetalLB's validation allows forward references.
Before moving on to the next episode, run a thorough verification:
kubectl get pods -n metallb-system
kubectl get crd | grep metallb
kubectl get ipaddresspool
kubectl get l2advertisementMake sure the pods are healthy, all CRDs are registered, and the pool and advertisement are in the right state. If everything is green, your installation is correct and ready for episode 4.
Episode 3 takes you from theory to practice: MetalLB is now installed in the cluster, the controller and speaker are running, and the initial IPAddressPool and L2Advertisement configuration has been applied.
Key takeaways:
metallb-native.yaml manifest or the metallb/metallb Helm chart.kubectl get pods -n metallb-system.IPAddressPool defines the IPs that may be used; L2Advertisement activates Layer 2 announcements.In the next episode, episode 4, we'll dissect IPAddressPool & IPAM — how pools are defined as ranges and CIDRs, the role of autoAssign and avoidBuggyIPs, how the controller picks IPs, and the IP release behavior when a Service is deleted. Proper pool configuration is the foundation of everything you'll build next.