MetalLB configuration should not be managed through manual kubectl apply. This episode covers managing IPAddressPool, advertisement, and BGPPeer as code, rolling them out with Argo CD and Flux, configuration versioning, review flow, and gradual rollout.

In episode 14 we mentioned that GitOps is the final protection layer for MetalLB configuration. Episode 18 covers this thoroughly: how to manage all MetalLB resources as code in a repository, roll them out via Argo CD or Flux, handle versioning, run a review flow, and apply changes gradually.
Why does GitOps matter for MetalLB? Because MetalLB resources control your cluster's network. A small mistake — a wrong pool, a peer with the wrong ASN, an advertisement referencing the wrong thing — can impact production immediately. With GitOps, every change goes through review, an audit trail is preserved, and rollback is a single command.
All MetalLB resources can be written as YAML files in a repository. The recommended structure separates environments:
mkdir -p metallb-config/overlays/production
touch metallb-config/ipaddresspool.yaml
touch metallb-config/l2advertisement.yaml
touch metallb-config/bgpadvertisement.yaml
touch metallb-config/bgppeer.yamlmkdir -p metallb-config/overlays/production creates the folder structure for base configuration and per-environment overlays. These files are the source of truth — no configuration is created outside the repository.
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
name: prod-pool
namespace: metallb-system
spec:
addresses:
- 192.168.20.200-192.168.20.240One change to this file is one commit that can be reviewed, tested, and rolled back — exactly like an application code change.
Argo CD continuously applies the entire contents of a directory to the cluster. The Application for MetalLB configuration:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: metallb-config
namespace: argocd
spec:
project: platform
source:
repoURL: https://github.com/org/metallb-config
path: overlays/production
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: metallb-system
syncPolicy:
automated:
prune: true
selfHeal: truesyncPolicy: automated: prune: true, selfHeal: true makes Argo CD delete resources that disappeared from the repository and revert manual changes back to the repository state. With this, a manual kubectl apply against MetalLB resources is automatically "undone" by Argo CD.
kubectl apply -f application.yaml
argocd app get metallb-configargocd app get metallb-config shows the synchronization status. After a new commit to the repository, Argo CD automatically applies the changes and shows a status of Synced.
Flux uses Kustomization to apply a directory to the cluster:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: metallb-config
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: flux-system
path: ./clusters/production/metallb
prune: true
validation: clientvalidation: client makes Flux validate the YAML before applying it, catching syntax errors early. With prune: true, resources that no longer exist in the repository are removed as well.
flux reconcile kustomization metallb-config
flux get kustomization metallb-configflux reconcile kustomization metallb-config triggers a manual synchronization without waiting for the interval. flux get kustomization metallb-config shows the latest status.
MetalLB configuration should be versioned like code:
feat: add prod-pool.Before a network change is approved, the review flow must involve the right people:
Big changes — like a CRD version migration or adding a new peer — should be rolled out gradually:
Info
The per-environment pool separation from episode 9 pairs perfectly with GitOps: the only difference between staging and production is files in different folders, and all changes follow the same review flow.
Episode 18 completes GitOps & config as code: all MetalLB resources as code in a repository, automated rollout with Argo CD or Flux, versioning and review flow, and gradual rollout of changes.
Key takeaways:
In the next episode, episode 19, we'll discuss performance & troubleshooting — diagnostics via kubectl get svc, describe svc, events, and speaker logs, checking BGP routes on the router, and handling common problems such as IPs not being assigned, two Services sharing an IP, and upgrading from v0.15 to v0.16.