Learn MetalLB - Validating Admission & CRD
Episode 10 of 23

Learn MetalLB - Validating Admission & CRD

MetalLB keeps configurations valid through a validating webhook run by the controller. This episode covers how the admission controller works, configuration error handling, CRD migration from v1beta1 to v1beta2, and best practices for upgrading between MetalLB versions.

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

Introduction

One source of frustration when using MetalLB is a configuration that looks correct but is silently rejected. The good news: MetalLB has a defensive layer — the validating admission controller run by metallb-controller. Every IPAddressPool, BGPPeer, and advertisement you apply is validated before it's actually stored in the cluster.

Episode 10 dissects this mechanism: how the webhook works, how to read rejected errors, how MetalLB CRDs evolved from v1beta1 to v1beta2, and best practices for upgrading MetalLB without breaking existing configurations.

Validating Admission Controller

How the Webhook Works

When you run kubectl apply on a MetalLB resource, the request is forwarded to the Kubernetes API server. Before storing it, the API server calls the validating webhook run by the controller. This webhook checks whether the configuration is valid — for example, whether the IP ranges are well-formed, whether the ASN is in a valid range, and whether references between resources are consistent.

If valid, the resource is stored. If not, the request is rejected and you receive an error. You can see this webhook in the cluster:

Viewing the MetalLB validating webhook
kubectl get validatingwebhookconfiguration
kubectl get validatingwebhookconfiguration metallb-webhook-configuration -o yaml

kubectl get validatingwebhookconfiguration metallb-webhook-configuration shows MetalLB's built-in webhook, complete with the resources it validates and the mutating rules in effect.

Try Sending an Invalid Configuration

To feel how error handling works, send a deliberately invalid configuration — for example, a pool with an invalid range format:

An invalid pool configuration
kubectl apply -f - <<EOF
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
  name: broken-pool
  namespace: metallb-system
spec:
  addresses:
    - not-an-ip
EOF

The API server will reject it with a message like The IPAddressPool "broken-pool" is invalid along with the rejection details from the webhook. Errors like this save you from broken configurations that could trigger strange behavior on the network.

Configuration Error Handling

Reading Rejection Messages

The webhook's rejection message usually explains which field is problematic and why. Examples of common error patterns:

  • IP range in the wrong format: addresses: not-an-ip is rejected because it isn't a valid IP.
  • Duplicate IPs between pools: the webhook detects two pools claiming the same IP.
  • ASN out of range: myASN or peerASN must be within the valid BGP range (1-4294967295).
Investigating a stored problem
kubectl get ipaddresspool -A
kubectl describe ipaddresspool broken-pool

kubectl describe ipaddresspool broken-pool on a resource that was stored at some point shows the status and conditions explaining why the resource isn't functioning normally.

Validating Cross-Resource References

Besides format, the webhook validates reference consistency. For example, an L2Advertisement referencing a pool with a misspelled name will show a status indicating the pool wasn't found. Note that MetalLB deliberately allows references to resources that haven't been created yet, so the apply order isn't rigid — but the status will flag it if the resource never appears.

CRD Versioning: v1beta1 to v1beta2

API Version Evolution

MetalLB configuration used to be a ConfigMap, then moved to CRD v1beta1 (starting v0.13), and now uses v1beta2 as the default and stable version (starting v0.14, refined in v0.16). Note that IPAddressPool uses metallb.io/v1beta2 while advertisements and peers can still be written in v1beta1:

Viewing the API versions of all MetalLB CRDs
kubectl get crd | grep metallb.io

kubectl get crd | grep metallb.io lists all of MetalLB's Custom Resources. The version column shows v1beta1 and v1beta2 as served versions — both remain active so old manifests can still be applied.

Migrating Between Versions

When MetalLB adds a new CRD version, the old version is generally kept served for a while so configurations don't break. Best practices when migrating:

  • Read the release notes to understand changed or removed fields.
  • Test kubectl apply on a staging cluster first.
  • Update manifests one by one, starting with resources that don't depend on each other.
  • Verify status with kubectl get before removing the old API version.

MetalLB Upgrade Best Practices

Preparation Before Upgrading

MetalLB upgrades rarely go smoothly without preparation. These steps reduce risk:

Check the current version and release notes
helm list -n metallb-system
kubectl get pods -n metallb-system
helm search repo metallb/metallb

helm search repo metallb/metallb shows the latest available chart version. Before bumping versions, always compare the changes between old and new — especially CRD changes, because an upgrade that forces API version conversion is the most common source of errors.

  • Upgrade with Helm (the same chart) so RBAC and the webhook update together.
  • Do it on staging, verify, then production.
  • If using manifests, don't mix two file versions randomly — use the official file for the target version.
  • Monitor the controller and speaker pods after the upgrade, then check the CRDs and pool status.
Example upgrade via Helm
helm upgrade metallb metallb/metallb --namespace metallb-system --version 0.16.1
kubectl get pods -n metallb-system

helm upgrade metallb metallb/metallb --version 0.16.1 pulls in all resource changes at once. After it finishes, kubectl get pods -n metallb-system confirms all components are healthy again.

Conclusion

Episode 10 completes the validation and versioning mechanism: the controller webhook validates every configuration before it's stored, errors are rejected with readable messages, CRDs evolved from v1beta1 to v1beta2, and upgrades are done with careful steps.

Key takeaways:

  • metallb-controller runs the validating webhook for all MetalLB resources.
  • Invalid configurations are rejected by the API server with messages explaining why.
  • Check kubectl get validatingwebhookconfiguration to make sure the webhook is active.
  • CRDs are available in v1beta1 and v1beta2 as served versions.
  • Upgrades must always start with reading the release notes and testing on staging.

In the next episode, episode 11, we'll discuss observability & monitoring — Prometheus metrics from the speaker and controller, analyzing events and logs for diagnosis, and using Grafana dashboards to visually monitor IP allocation and BGP peering status.

Learn MetalLB - Validating Admission & CRD | Learn MetalLB