Learn MetalLB - GitOps & Config as Code
Episode 18 of 23

Learn MetalLB - GitOps & Config as Code

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.

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

Introduction

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.

MetalLB Configuration as Code

Repository Structure

All MetalLB resources can be written as YAML files in a repository. The recommended structure separates environments:

MetalLB config repository structure
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.yaml

mkdir -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.

Example Configuration in the Repository

IPAddressPool as code
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
  name: prod-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.20.200-192.168.20.240

One change to this file is one commit that can be reviewed, tested, and rolled back — exactly like an application code change.

Rolling Out with Argo CD

Creating an Argo CD Application

Argo CD continuously applies the entire contents of a directory to the cluster. The Application for MetalLB configuration:

Argo CD Application for MetalLB config
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: true

syncPolicy: 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.

Running Argo CD

Verify Argo CD synchronization
kubectl apply -f application.yaml
argocd app get metallb-config

argocd 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.

Rolling Out with Flux

Flux Kustomization

Flux uses Kustomization to apply a directory to the cluster:

Flux Kustomization for MetalLB config
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: client

validation: 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.

Running Flux

Force a Flux reconciliation
flux reconcile kustomization metallb-config
flux get kustomization metallb-config

flux reconcile kustomization metallb-config triggers a manual synchronization without waiting for the interval. flux get kustomization metallb-config shows the latest status.

Versioning, Review, and Gradual Rollout

Configuration Versioning

MetalLB configuration should be versioned like code:

  • Every change is a commit with a clear message, for example feat: add prod-pool.
  • Use tags or branches per release if needed.
  • Keep a change history for audit — who changed what and when.

Review Flow

Before a network change is approved, the review flow must involve the right people:

  • A PR is created from a feature branch to the main branch.
  • The platform engineer reviews the impact on pools and advertisements.
  • The network engineer reviews the impact on peering and routing (if any).
  • CI runs simple validation, such as a YAML linter.

Gradual Rollout

Big changes — like a CRD version migration or adding a new peer — should be rolled out gradually:

  • Apply to the staging cluster first, observe for a few days.
  • Apply to one node or one small environment in production.
  • Monitor metrics and logs, then roll out to the whole cluster.

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.

Conclusion

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:

  • All MetalLB resources can be written as YAML files in a repository.
  • Argo CD applies directories automatically with prune and selfHeal.
  • Flux uses Kustomization with client validation and reconciliation.
  • Versioning gives an audit trail for every network change.
  • Review involves the platform and network engineers before merge.
  • Big changes are rolled out gradually, starting from staging.

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.