Bare-metal Kubernetes clusters lack cloud provider load balancer integration, creating challenges for exposing services externally. MetalLB bridges this gap by providing native load balancer capabilities for on-premises deployments. This comprehensive guide demonstrates enterprise-grade MetalLB implementation with advanced BGP routing, Layer 2 failover, multi-protocol support, and production monitoring strategies for mission-critical infrastructure.

Executive Summary

Cloud-native applications deployed on bare-metal infrastructure require sophisticated load balancing solutions that match cloud provider capabilities while offering greater control and cost efficiency. MetalLB provides enterprise-grade load balancer functionality for Kubernetes clusters running on physical hardware, supporting both Layer 2 (ARP/NDP) and Layer 3 (BGP) protocols. This implementation guide covers advanced deployment patterns, high availability configurations, security hardening, and operational best practices for production environments.

Understanding MetalLB Architecture

Core Components and Protocols

MetalLB operates through two main components working in concert:

  1. Controller: Watches for LoadBalancer services and assigns IP addresses from configured pools
  2. Speaker: Announces assigned IP addresses using Layer 2 (ARP/NDP) or Layer 3 (BGP) protocols

Protocol Comparison

Layer 2 Mode:

  • Uses ARP (IPv4) and NDP (IPv6) for IP address announcement
  • Simple configuration with minimal network infrastructure requirements
  • Single-node traffic concentration (no true load balancing)
  • Suitable for smaller deployments and development environments

BGP Mode:

  • Integrates with network routers using Border Gateway Protocol
  • True load balancing across multiple nodes
  • Enhanced failover capabilities and traffic distribution
  • Requires BGP-capable network infrastructure
  • Enterprise-grade scalability and performance

Infrastructure Prerequisites

Network Architecture Planning

Design network topology to support MetalLB deployment:

# Network topology example
Network: 10.0.0.0/16
├── Management VLAN: 10.0.1.0/24
│   ├── Kubernetes Masters: 10.0.1.10-19
│   └── Management Services: 10.0.1.20-30
├── Worker VLAN: 10.0.2.0/24
│   ├── Worker Nodes: 10.0.2.10-50
│   └── Storage Nodes: 10.0.2.51-60
└── Load Balancer VLAN: 10.0.3.0/24
    ├── MetalLB L2 Pool: 10.0.3.100-150
    └── MetalLB BGP Pool: 10.0.3.200-250

Router Configuration for BGP Mode

Configure network routers to peer with MetalLB:

! Cisco IOS/IOS-XE example
router bgp 65000
 bgp router-id 10.0.1.1
 bgp log-neighbor-changes
 neighbor METALLB_PEERS peer-group
 neighbor METALLB_PEERS remote-as 65001
 neighbor METALLB_PEERS fall-over bfd
 neighbor METALLB_PEERS maximum-routes 100

 ! Add each Kubernetes node as BGP peer
 neighbor 10.0.2.10 peer-group METALLB_PEERS
 neighbor 10.0.2.11 peer-group METALLB_PEERS
 neighbor 10.0.2.12 peer-group METALLB_PEERS

 address-family ipv4
  neighbor METALLB_PEERS activate
  neighbor METALLB_PEERS route-map METALLB_IN in
  neighbor METALLB_PEERS route-map METALLB_OUT out
 exit-address-family

route-map METALLB_IN permit 10
 match ip address prefix-list METALLB_PREFIXES
 set local-preference 100

route-map METALLB_OUT deny 10

ip prefix-list METALLB_PREFIXES seq 5 permit 10.0.3.200/29 le 32

Enterprise MetalLB Installation

Helm Chart Deployment

Deploy MetalLB with comprehensive enterprise configuration:

# metallb-values.yaml
speaker:
  enabled: true
  image:
    repository: quay.io/metallb/speaker
    tag: v0.13.12
    pullPolicy: IfNotPresent

  resources:
    requests:
      cpu: 100m
      memory: 100Mi
    limits:
      cpu: 500m
      memory: 256Mi

  nodeSelector:
    node-role.kubernetes.io/worker: "true"

  tolerations:
  - key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule

  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/arch
            operator: In
            values: ["amd64", "arm64"]

  frr:
    enabled: true
    image:
      repository: quay.io/frrouting/frr
      tag: "9.0.2"

  runtimeClassName: ""

  secretName: memberlist
  logLevel: info

  # Security context
  securityContext:
    runAsNonRoot: true
    runAsUser: 65534
    fsGroup: 65534

  # Enable Prometheus metrics
  prometheus:
    enabled: true
    port: 7472
    metricsPort: 7472

controller:
  enabled: true
  image:
    repository: quay.io/metallb/controller
    tag: v0.13.12
    pullPolicy: IfNotPresent

  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 512Mi

  nodeSelector:
    node-role.kubernetes.io/control-plane: "true"

  tolerations:
  - key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule
  - key: node-role.kubernetes.io/control-plane
    operator: Exists
    effect: NoSchedule

  securityContext:
    runAsNonRoot: true
    runAsUser: 65534
    fsGroup: 65534

  logLevel: info

# Configure for multiple replicas
replicaCount:
  controller: 2

# Network policy configuration
networkPolicy:
  enabled: true

# Service monitor for Prometheus
serviceMonitor:
  enabled: true
  namespace: monitoring
  labels:
    app.kubernetes.io/name: metallb
  annotations: {}
  interval: 30s
  scrapeTimeout: 10s

Install using Helm:

# Add MetalLB Helm repository
helm repo add metallb https://metallb.github.io/metallb
helm repo update

# Create dedicated namespace
kubectl create namespace metallb-system

# Label namespace for monitoring
kubectl label namespace metallb-system name=metallb-system

# Install MetalLB
helm install metallb metallb/metallb \
  --namespace metallb-system \
  --values metallb-values.yaml \
  --wait \
  --timeout 300s

# Verify installation
kubectl get pods -n metallb-system
kubectl get daemonset -n metallb-system
kubectl get deployment -n metallb-system

CRD-Based Configuration

Configure MetalLB using Custom Resource Definitions for enhanced flexibility:

# Layer 2 Address Pool Configuration
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: layer2-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.0.3.100-10.0.3.150
  autoAssign: true
  avoidBuggyIPs: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: layer2-advertisement
  namespace: metallb-system
spec:
  ipAddressPools:
  - layer2-pool
  nodeSelectors:
  - matchLabels:
      kubernetes.io/os: linux
# BGP Address Pool Configuration
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: bgp-pool-production
  namespace: metallb-system
spec:
  addresses:
  - 10.0.3.200/29
  - 10.0.3.208/29
  - 10.0.3.216/29
  autoAssign: true
  avoidBuggyIPs: true
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: router-1
  namespace: metallb-system
spec:
  myASN: 65001
  peerASN: 65000
  peerAddress: 10.0.1.1
  sourceAddress: 10.0.2.10
  routerID: 10.0.2.10
  holdTime: "90s"
  keepaliveTime: "30s"
  passwordSecret:
    name: bgp-auth
    key: password
  bfdProfile: default-bfd
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: production-advertisement
  namespace: metallb-system
spec:
  ipAddressPools:
  - bgp-pool-production
  peers:
  - router-1
  communities:
  - "65000:100"  # Production traffic
  localPref: 100
  aggregationLength: 32
  aggregationLengthV6: 128

Advanced BGP Configuration

Implement sophisticated BGP policies for traffic engineering:

apiVersion: metallb.io/v1beta1
kind: BFDProfile
metadata:
  name: default-bfd
  namespace: metallb-system
spec:
  receiveInterval: 150
  transmitInterval: 150
  detectMultiplier: 3
  echoMode: true
  minimumTtl: 254
---
apiVersion: metallb.io/v1beta1
kind: Community
metadata:
  name: production-community
  namespace: metallb-system
spec:
  communities:
  - name: "high-priority"
    value: "65000:100"
  - name: "backup-path"
    value: "65000:200"
  - name: "no-export"
    value: "65535:65281"
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: core-router-primary
  namespace: metallb-system
spec:
  myASN: 65001
  peerASN: 65000
  peerAddress: 10.0.1.1
  sourceAddress: 10.0.2.10
  routerID: 10.0.2.10
  holdTime: "180s"
  keepaliveTime: "60s"
  passwordSecret:
    name: bgp-auth-primary
    key: password
  bfdProfile: default-bfd
  nodeSelectors:
  - matchLabels:
      metallb.io/bgp-node: "primary"
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: core-router-secondary
  namespace: metallb-system
spec:
  myASN: 65001
  peerASN: 65000
  peerAddress: 10.0.1.2
  sourceAddress: 10.0.2.11
  routerID: 10.0.2.11
  holdTime: "180s"
  keepaliveTime: "60s"
  passwordSecret:
    name: bgp-auth-secondary
    key: password
  bfdProfile: default-bfd
  nodeSelectors:
  - matchLabels:
      metallb.io/bgp-node: "secondary"

High Availability and Redundancy

Multi-Zone Deployment

Configure MetalLB for multi-zone high availability:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: zone-a-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.0.3.100-10.0.3.120
  serviceAllocation:
    priority: 100
    serviceSelectors:
    - matchLabels:
        metallb.io/zone: "zone-a"
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: zone-b-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.0.3.130-10.0.3.150
  serviceAllocation:
    priority: 90
    serviceSelectors:
    - matchLabels:
        metallb.io/zone: "zone-b"
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: zone-aware-advertisement
  namespace: metallb-system
spec:
  ipAddressPools:
  - zone-a-pool
  - zone-b-pool
  nodeSelectors:
  - matchExpressions:
    - key: topology.kubernetes.io/zone
      operator: In
      values: ["zone-a", "zone-b"]
  interfaces:
  - "eth0"
  - "ens192"

Load Balancer Classes

Implement service differentiation using LoadBalancer classes:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: internal-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.0.3.100-10.0.3.130
  serviceAllocation:
    priority: 100
    namespaces:
    - default
    - applications
    serviceSelectors:
    - matchLabels:
        metallb.io/class: "internal"
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: external-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.100-192.168.1.130
  serviceAllocation:
    priority: 100
    serviceSelectors:
    - matchLabels:
        metallb.io/class: "external"
---
# Example service using internal class
apiVersion: v1
kind: Service
metadata:
  name: internal-app
  labels:
    metallb.io/class: "internal"
  annotations:
    metallb.io/address-pool: "internal-pool"
spec:
  type: LoadBalancer
  loadBalancerClass: "metallb.io/internal"
  selector:
    app: internal-app
  ports:
  - port: 80
    targetPort: 8080

Security Configuration

Network Policies

Implement comprehensive network security:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: metallb-controller-policy
  namespace: metallb-system
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/component: controller
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 7472  # Metrics port
    - protocol: TCP
      port: 9443  # Webhook port
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: TCP
      port: 6443  # Kubernetes API
  - to: []
    ports:
    - protocol: TCP
      port: 53   # DNS
    - protocol: UDP
      port: 53   # DNS
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: metallb-speaker-policy
  namespace: metallb-system
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/component: speaker
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 7472  # Metrics port
  - ports:
    - protocol: TCP
      port: 179   # BGP
    - protocol: TCP
      port: 7946  # Memberlist
    - protocol: UDP
      port: 7946  # Memberlist
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: TCP
      port: 6443  # Kubernetes API
  - to: []
    ports:
    - protocol: TCP
      port: 179   # BGP
    - protocol: TCP
      port: 53    # DNS
    - protocol: UDP
      port: 53    # DNS
    - protocol: TCP
      port: 7946  # Memberlist
    - protocol: UDP
      port: 7946  # Memberlist

BGP Authentication

Secure BGP peering with authentication:

# Create BGP authentication secrets
kubectl create secret generic bgp-auth-primary \
  --from-literal=password='secure-bgp-password-primary' \
  --namespace=metallb-system

kubectl create secret generic bgp-auth-secondary \
  --from-literal=password='secure-bgp-password-secondary' \
  --namespace=metallb-system

# Label secrets for proper management
kubectl label secret bgp-auth-primary \
  app.kubernetes.io/managed-by=metallb \
  --namespace=metallb-system

kubectl label secret bgp-auth-secondary \
  app.kubernetes.io/managed-by=metallb \
  --namespace=metallb-system

Pod Security Context

Implement security hardening:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: metallb-speaker-hardened
  namespace: metallb-system
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
        runAsGroup: 65534
        fsGroup: 65534
        seccompProfile:
          type: RuntimeDefault
        supplementalGroups: []

      containers:
      - name: speaker
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
            - ALL
            add:
            - NET_RAW      # Required for ARP/NDP
            - NET_ADMIN    # Required for BGP socket binding

        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: memberlist
          mountPath: /etc/ml_secret_key
          readOnly: true
        - name: frr-sockets
          mountPath: /var/run/frr

      volumes:
      - name: tmp
        emptyDir:
          medium: Memory
      - name: memberlist
        secret:
          secretName: memberlist
      - name: frr-sockets
        emptyDir:
          medium: Memory

Monitoring and Observability

Prometheus Monitoring

Configure comprehensive metrics collection:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: metallb-controller
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
    - metallb-system
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
    scrapeTimeout: 10s
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: metallb-speaker
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
    - metallb-system
  selector:
    matchLabels:
      app.kubernetes.io/component: speaker
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
    scrapeTimeout: 10s
    metricRelabelings:
    - sourceLabels: [__name__]
      regex: 'metallb_.*'
      targetLabel: __name__
      replacement: '${1}'

Grafana Dashboard

Create comprehensive monitoring dashboard:

{
  "dashboard": {
    "title": "MetalLB Load Balancer Monitoring",
    "tags": ["metallb", "load-balancer", "networking"],
    "templating": {
      "list": [
        {
          "name": "namespace",
          "type": "query",
          "query": "label_values(up{job=\"metallb-controller\"}, namespace)",
          "current": {
            "value": "metallb-system"
          }
        }
      ]
    },
    "panels": [
      {
        "title": "Controller Status",
        "type": "stat",
        "targets": [
          {
            "expr": "up{job=\"metallb-controller\", namespace=\"$namespace\"}",
            "legendFormat": "Controller Instances"
          }
        ]
      },
      {
        "title": "Speaker Status",
        "type": "stat",
        "targets": [
          {
            "expr": "up{job=\"metallb-speaker\", namespace=\"$namespace\"}",
            "legendFormat": "Speaker Instances"
          }
        ]
      },
      {
        "title": "BGP Session Status",
        "type": "graph",
        "targets": [
          {
            "expr": "metallb_bgp_session_up{namespace=\"$namespace\"}",
            "legendFormat": "{{peer}} - {{instance}}"
          }
        ]
      },
      {
        "title": "IP Pool Utilization",
        "type": "graph",
        "targets": [
          {
            "expr": "metallb_ip_addresses_in_use_total{namespace=\"$namespace\"} / metallb_ip_addresses_total{namespace=\"$namespace\"} * 100",
            "legendFormat": "{{pool}} - Utilization %"
          }
        ]
      },
      {
        "title": "Service Allocations",
        "type": "table",
        "targets": [
          {
            "expr": "metallb_allocator_addresses_in_use{namespace=\"$namespace\"}",
            "format": "table",
            "instant": true
          }
        ]
      }
    ]
  }
}

Alerting Rules

Implement comprehensive alerting:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: metallb-alerts
  namespace: monitoring
spec:
  groups:
  - name: metallb
    rules:
    - alert: MetalLBControllerDown
      expr: up{job="metallb-controller"} == 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "MetalLB Controller is down"
        description: "MetalLB Controller instance {{ $labels.instance }} has been down for more than 5 minutes."

    - alert: MetalLBSpeakerDown
      expr: up{job="metallb-speaker"} == 0
      for: 2m
      labels:
        severity: warning
      annotations:
        summary: "MetalLB Speaker is down"
        description: "MetalLB Speaker instance {{ $labels.instance }} has been down for more than 2 minutes."

    - alert: MetalLBBGPSessionDown
      expr: metallb_bgp_session_up == 0
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "MetalLB BGP session down"
        description: "BGP session to peer {{ $labels.peer }} from {{ $labels.instance }} has been down for more than 1 minute."

    - alert: MetalLBIPPoolExhausted
      expr: (metallb_ip_addresses_in_use_total / metallb_ip_addresses_total) > 0.9
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "MetalLB IP pool nearly exhausted"
        description: "IP pool {{ $labels.pool }} is {{ $value | humanizePercentage }} utilized."

    - alert: MetalLBHighServiceAllocations
      expr: rate(metallb_allocator_addresses_allocated_total[5m]) > 0.1
      for: 2m
      labels:
        severity: info
      annotations:
        summary: "High MetalLB service allocation rate"
        description: "MetalLB is allocating addresses at a rate of {{ $value }} per second."

Production Use Cases and Patterns

Multi-Tier Application Deployment

Deploy applications with sophisticated load balancing requirements:

# Frontend LoadBalancer with external access
apiVersion: v1
kind: Service
metadata:
  name: web-frontend-lb
  annotations:
    metallb.io/address-pool: "external-pool"
    metallb.io/loadBalancerIPs: "192.168.1.100"
    metallb.io/allow-shared-ip: "web-frontend"
  labels:
    metallb.io/class: "external"
spec:
  type: LoadBalancer
  loadBalancerClass: "metallb.io/external"
  externalTrafficPolicy: Local
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  selector:
    app: web-frontend
    tier: frontend
  ports:
  - name: https
    port: 443
    targetPort: 8443
    protocol: TCP
  - name: http
    port: 80
    targetPort: 8080
    protocol: TCP
---
# API Gateway with internal access
apiVersion: v1
kind: Service
metadata:
  name: api-gateway-lb
  annotations:
    metallb.io/address-pool: "internal-pool"
    metallb.io/allow-shared-ip: "api-services"
  labels:
    metallb.io/class: "internal"
spec:
  type: LoadBalancer
  loadBalancerClass: "metallb.io/internal"
  externalTrafficPolicy: Cluster
  selector:
    app: api-gateway
    tier: api
  ports:
  - name: api
    port: 8080
    targetPort: 8080
    protocol: TCP
  - name: grpc
    port: 9090
    targetPort: 9090
    protocol: TCP

Database Load Balancing

Configure load balancing for database services:

apiVersion: v1
kind: Service
metadata:
  name: postgresql-primary-lb
  annotations:
    metallb.io/address-pool: "internal-pool"
    metallb.io/loadBalancerIPs: "10.0.3.110"
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: postgresql
    role: primary
  ports:
  - name: postgresql
    port: 5432
    targetPort: 5432
    protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql-readonly-lb
  annotations:
    metallb.io/address-pool: "internal-pool"
    metallb.io/loadBalancerIPs: "10.0.3.111"
spec:
  type: LoadBalancer
  externalTrafficPolicy: Cluster
  selector:
    app: postgresql
    role: replica
  ports:
  - name: postgresql
    port: 5432
    targetPort: 5432
    protocol: TCP

Advanced Troubleshooting

Diagnostic Commands

Comprehensive troubleshooting toolkit:

#!/bin/bash
# metallb-diagnostics.sh

echo "=== MetalLB Component Status ==="
kubectl get pods -n metallb-system -o wide
kubectl get daemonset -n metallb-system
kubectl get deployment -n metallb-system

echo -e "\n=== MetalLB Configuration ==="
kubectl get ipaddresspool -n metallb-system -o yaml
kubectl get bgppeer -n metallb-system -o yaml
kubectl get l2advertisement -n metallb-system -o yaml
kubectl get bgpadvertisement -n metallb-system -o yaml

echo -e "\n=== LoadBalancer Services ==="
kubectl get svc --all-namespaces -o wide | grep LoadBalancer

echo -e "\n=== BGP Session Status ==="
kubectl exec -n metallb-system daemonset/metallb-speaker -- vtysh -c "show bgp summary"

echo -e "\n=== Speaker Logs ==="
kubectl logs -n metallb-system -l app.kubernetes.io/component=speaker --tail=50

echo -e "\n=== Controller Logs ==="
kubectl logs -n metallb-system -l app.kubernetes.io/component=controller --tail=50

echo -e "\n=== Network Connectivity Tests ==="
for node in $(kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'); do
    echo "Testing connectivity to node $node"
    nc -zv $node 179  # BGP port
done

Common Issues Resolution

BGP Session Failures:

# Check BGP peer configuration
kubectl describe bgppeer -n metallb-system

# Verify network connectivity
kubectl exec -n metallb-system daemonset/metallb-speaker -- \
  nc -zv 10.0.1.1 179

# Check BGP authentication
kubectl get secret bgp-auth -n metallb-system -o yaml

# Monitor BGP protocol messages
kubectl exec -n metallb-system daemonset/metallb-speaker -- \
  vtysh -c "debug bgp neighbor 10.0.1.1"

Layer 2 Advertisement Issues:

# Check ARP table
kubectl exec -n metallb-system daemonset/metallb-speaker -- \
  ip neigh show

# Monitor ARP traffic
kubectl exec -n metallb-system daemonset/metallb-speaker -- \
  tcpdump -i eth0 arp

# Verify interface configuration
kubectl exec -n metallb-system daemonset/metallb-speaker -- \
  ip addr show eth0

Performance Optimization

Optimize MetalLB for high-performance environments:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: metallb-speaker-optimized
spec:
  template:
    spec:
      priorityClassName: system-node-critical
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet

      containers:
      - name: speaker
        resources:
          requests:
            cpu: 200m
            memory: 200Mi
          limits:
            cpu: 1000m
            memory: 512Mi
        env:
        - name: METALLB_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: METALLB_HOST
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: FRR_CONFIG_FILE
          value: /etc/frr/frr.conf
        - name: FRR_LOGGING_LEVEL
          value: informational

      nodeSelector:
        metallb.io/speaker: "enabled"

      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
        operator: Exists
      - effect: NoSchedule
        key: node-role.kubernetes.io/control-plane
        operator: Exists
      - effect: NoExecute
        key: node.kubernetes.io/not-ready
        operator: Exists
        tolerationSeconds: 60

Conclusion

MetalLB provides enterprise-grade load balancing capabilities for bare-metal Kubernetes deployments, offering flexibility and control that surpasses cloud provider solutions. This implementation guide demonstrates comprehensive deployment patterns that ensure high availability, security, and performance for production workloads.

Key advantages of this MetalLB implementation include:

  • Protocol Flexibility: Support for both Layer 2 and BGP protocols
  • High Availability: Multi-zone deployments with intelligent failover
  • Security: Network policies, authentication, and security contexts
  • Observability: Comprehensive monitoring and alerting
  • Scalability: BGP-based load distribution across multiple nodes
  • Cost Efficiency: Eliminate cloud provider load balancer costs

Regular monitoring, capacity planning, and network testing ensure optimal performance and reliability. Consider implementing additional features such as service mesh integration, advanced traffic policies, and automated scaling based on your specific requirements.

The patterns demonstrated here provide a solid foundation for implementing sophisticated networking solutions in bare-metal Kubernetes environments, enabling organizations to maintain cloud-native capabilities while retaining full control over their infrastructure.