This guide explains how to deploy MetalLB, a load balancer for bare-metal Kubernetes clusters, and a sample application using Flux GitOps. The steps are based on a working example and provide instructions for configuration, deployment, and testing.

Prerequisites

  1. Flux Installed: Ensure Flux is installed and running in your Kubernetes cluster.
  2. Git Repository: A Git repository structured for Flux GitOps, e.g.,
    .
    <...>
    ├── clusters/
    │   └── production/
    │       ├── flux-system/
    │       │   └── sources/
    │       └── apps/
    ├── infrastructure/
    │   ├── networking/
    │   │   └── metallb/
    <...>
    
  3. Kubernetes Cluster: A bare-metal Kubernetes cluster with MetalLB-compatible networking.

1. Deploying MetalLB via Flux

Step 1: Create the MetalLB Namespace

Create a namespace for MetalLB in your Git repository:

File: clusters/production/flux-system/sources/metallb-namespace.yaml:

# File: clusters/production/flux-system/sources/metallb-namespace.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: metallb-system
  labels:
    # Overwrite or add the labels you need:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/enforce-version: v1.25

Step 2: Create the MetalLB HelmRepository

Define the Helm repository for MetalLB:

File: clusters/production/flux-system/sources/metallb-helmrepository.yaml:

# File: clusters/production/flux-system/sources/metallb-helmrepository.yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
  name: metallb
  namespace: flux-system
spec:
  interval: 1h
  url: https://metallb.github.io/metallb

Step 3: Create the MetalLB HelmRelease

Define the HelmRelease to install MetalLB:

File: clusters/production/flux-system/sources/metallb-helmrelease.yaml:

# File: clusters/production/flux-system/sources/metallb-helmrelease.yaml
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: metallb
  namespace: metallb-system
spec:
  interval: 1h
  releaseName: metallb
  targetNamespace: metallb-system
  chart:
    spec:
      chart: metallb
      sourceRef:
        kind: HelmRepository
        name: metallb
        namespace: flux-system
      version: 0.13.10
  values:
    controller:
      image:
        tag: v0.13.10
    crds:
      enabled: true
    speaker:
      image:
        tag: v0.13.10
      tolerations:
        - key: "node-role.kubernetes.io/master"
          operator: "Exists"
          effect: "NoSchedule"
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Exists"
          effect: "NoSchedule"
      securityContext:
        capabilities:
          add:
            - "NET_ADMIN"
            - "NET_RAW"
            - "SYS_ADMIN"
        privileged: true

Refer these files in resources section of clusters/production/flux-system/sources/kustomization.yaml:

# File: clusters/production/flux-system/sources/kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  # ...existing resources...
  - metallb-namespace.yaml
  - metallb-helmrepository.yaml
  - metallb-helmrelease.yaml

Step 4: Configure MetalLB IP Address Pool

Create the MetalLB configuration:

File: infrastructure/networking/metallb/metallb-config.yaml:

# File: infrastructure/networking/metallb/metallb-config.yaml
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default-address-pool
  namespace: metallb-system
spec:
  addresses:
    - xxx.xxx.xxx.90-xxx.xxx.xxx.99  # Replace with your IP range
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system
spec:
  ipAddressPools:
    - default-address-pool

Refer this file in resources section of infrastructure/networking/metallb/kustomization.yaml:

# File: infrastructure/networking/metallb/kustomization.yaml
---
resources:
  - metallb-config.yaml

Step 5: Add MetalLB in Flux

Create the MetalLB configuration in clusters/production/flux-system/metallb.yaml:

# File: clusters/production/flux-system/metallb.yaml
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: metallb
  namespace: flux-system
spec:
  interval: 10m
  path: ./infrastructure/networking/metallb
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: metallb-controller
      namespace: metallb-system

Refer it in clusters/production/flux-system/kustomization.yaml:

# File: clusters/production/flux-system/kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  # ...existing entries...
  - metallb.yaml

Step 6: Commit and Push Changes

git add -A
git commit -m "MetalLB deployment"
git push
# Reconcile
flux reconcile kustomization apps -n flux-system
flux reconcile kustomization metallb -n flux-system

Verification

  1. Check if all kustomizations are in a READY state:

    kubectl get kustomizations -A
    
  2. Verify the MetalLB namespace:

    kubectl get namespaces
    
  3. Check the Helm repository and release:

    kubectl get helmrepository -n flux-system
    kubectl get helmrelease metallb -n metallb-system
    
  4. Confirm deployments and IP pool:

    kubectl get deployments -n metallb-system
    kubectl get ipaddresspool -n metallb-system
    kubectl get l2advertisement -n metallb-system