Learn MetalLB - IPAddressPool & IPAM
Episode 4 of 23

Learn MetalLB - IPAddressPool & IPAM

IPAddressPool is the heart of MetalLB's address management. This episode covers how to define IP ranges as ranges and CIDRs, the autoAssign and avoidBuggyIPs options, the controller's allocation behavior, and IP release when a Service is deleted.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

In episode 3 you created your first IPAddressPool without going into detail. Episode 4 digs into the most important part of day-to-day MetalLB operations: IPAddressPool and IPAM (IP Address Management). This is where you determine where external IPs come from, how many are available, and how the controller manages them.

Wrong IPAM can cause problems that are hard to trace: two Services using the same IP, IP conflicts with other devices on the network, or a pool that's mysteriously empty. Understanding how pools work lets you prevent all of these from the start.

Getting to Know IPAddressPool

Defining IP Ranges

An IPAddressPool can contain one or more ranges, either as an explicit range or a CIDR. The following example combines both:

IPAddressPool with range and CIDR
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
  name: mixed-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.1.200-192.168.1.220
    - 192.168.2.0/28
    - fd00:1::10-fd00:1::1f

The range 192.168.1.200-192.168.1.220 and the CIDR 192.168.2.0/28 are both valid ways to express an IPv4 block, and IPv6 ranges are supported too. MetalLB will enumerate every IP covered and treat them as one set of addresses.

Specifying a Single IP

If you only need one IP, you can write it as a single-address range: 192.168.1.200-192.168.1.200. This is useful for giving a specific IP to a particular Service — a technique we'll use again in episode 9 for Service selection.

Allocation Options: autoAssign and avoidBuggyIPs

autoAssign

By default, the controller is free to take IPs from any available pool. The autoAssign: false option restricts a pool to only serve Services that explicitly request it via annotation:

Pool with autoAssign disabled
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
  name: reserved-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.1.250
  autoAssign: false

A pool with autoAssign: false won't be used automatically by Services. A Service that wants an IP from this pool must request it via the metallb.universe.tf/address-pool: reserved-pool annotation.

avoidBuggyIPs

Certain network devices have bugs with the last bit of a subnet — especially addresses ending in .255 or .0. The avoidBuggyIPs: true option makes the controller avoid IPs ending in 0 and 255 in every /24:

Pool that avoids buggy IPs
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
  name: safe-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.1.0/24
  avoidBuggyIPs: true

avoidBuggyIPs: true on the CIDR 192.168.1.0/24 makes this pool only offer IPs 192.168.1.1 through 192.168.1.254, minus the network and broadcast addresses. If your network is full of old, problematic switches, this option is a lifesaver.

How the Controller Allocates IPs

The IP Selection Process

When a LoadBalancer Service is created, the controller watches it and starts searching for an IP. Its selection logic is simple but important:

  • IPs already used by another Service are never reused.
  • Pools with autoAssign: false are skipped unless the Service explicitly requests them.
  • If multiple pools are available, the controller picks one and takes the first free IP.

You can observe this process directly through the Service events:

Observing IP allocation
kubectl describe svc nginx
kubectl get events --field-selector involvedObject.name=nginx

kubectl get events --field-selector involvedObject.name=nginx will show messages like Allocated IP 192.168.1.200 written by the controller. That's the visual proof of the IPAM process.

IP Conflicts

MetalLB tracks allocations internally, so two Services will never get the same IP from the same pool. Conflicts can happen when the IP is outside MetalLB's control — for example, used by DHCP or other static devices on the network. That's why it's important to choose a genuinely free IP block, as we prepared in episode 0.

Releasing IPs When a Service Is Deleted

Allocation Lifecycle

IPs are ephemeral: while a Service exists, the IP is on loan; once the Service is deleted, the IP returns to the pool and can be used by another Service. Verifying is easy:

Releasing and observing IPs
kubectl delete svc nginx
kubectl get svc -A
kubectl get ipaddresspool

After kubectl delete svc nginx, the events record Deallocating IP 192.168.1.200. The IP becomes available again for the next allocation — no manual steps required.

Warning

If you delete an IPAddressPool that's still in use by an existing Service, that Service will lose its IP when its pod is restarted or when the Service is updated. Avoid deleting an active pool in production.

Observing with Status

To find out which IPs a given pool has allocated, inspect the Services in that namespace:

Viewing all IPs currently in use
kubectl get svc -A -o wide

The EXTERNAL-IP column in kubectl get svc -A -o wide shows all the IPs currently borrowed from the pool. Comparing it against the pool's address list shows how much capacity remains — a topic you'll explore in depth in episode 17.

Conclusion

Episode 4 completes your understanding of MetalLB IPAM: how to define pools with ranges and CIDRs, the autoAssign and avoidBuggyIPs options, the controller's allocation logic, and the IP lifecycle from borrowing to release.

Key takeaways:

  • An IPAddressPool can contain explicit ranges, CIDRs, or both.
  • autoAssign: false makes a pool only serve Services that request it via annotation.
  • avoidBuggyIPs: true avoids addresses ending in 0 and 255.
  • The controller never gives two Services the same IP from the same pool.
  • IPs are released automatically when a Service is deleted.

In the next episode, episode 5, we'll discuss Layer 2 mode in depth — how announcements work with ARP/NDP, the role of the leader node that announces IPs, the failover mechanism when a node dies, and the characteristics and limitations of this mode that often surprise beginners.

Learn MetalLB - IPAddressPool & IPAM | Learn MetalLB