CNAP 클라우드 플랫폼 GitOps 대시보드를 직접 체험해보세요  —  실시간 CI/CD, 모니터링, 보안 관제를 한 곳에서     CNAP 클라우드 플랫폼 GitOps 대시보드를 직접 체험해보세요  —  실시간 CI/CD, 모니터링, 보안 관제를 한 곳에서     CNAP 클라우드 플랫폼 GitOps 대시보드를 직접 체험해보세요  —  실시간 CI/CD, 모니터링, 보안 관제를 한 곳에서     CNAP 클라우드 플랫폼 GitOps 대시보드를 직접 체험해보세요  —  실시간 CI/CD, 모니터링, 보안 관제를 한 곳에서    

MetalLB

Kubernetes 클러스터에서 LoadBalancer 타입 서비스에 외부 IP를 할당하는 소프트웨어 로드밸런서입니다.

  • 버전: 0.14.9
  • 네임스페이스: metallb-system
  • 의존성: 없음

1. 개요

MetalLB는 베어메탈/로컬 환경(Kind 등)에서 클라우드 LoadBalancer를 대체합니다. L2 모드와 BGP 모드를 지원하며, 지정된 IP 대역에서 LoadBalancer 서비스에 IP를 할당합니다.

  • L2 모드: ARP를 이용해 IP를 광고. 설정이 단순하며 별도 라우터 없이 동작
  • BGP 모드: 라우터와 BGP 피어링을 맺어 IP를 광고. ECMP 라우팅으로 트래픽을 여러 노드에 분산 가능

2. 사전 요구사항

L2 모드

kube-proxystrictARP가 활성화되어야 합니다.

kubectl get configmap kube-proxy -n kube-system -o yaml | \
  sed -e "s/strictARP: false/strictARP: true/" | \
  kubectl apply -f - -n kube-system

적용 확인:

kubectl get configmap kube-proxy -n kube-system -o yaml | grep strictARP
# strictARP: true

BGP 모드

BGP를 지원하는 라우터(또는 소프트 라우터)가 필요합니다. strictARP 설정은 필요하지 않습니다.


3. 디렉터리 구조

metallb/
├── Makefile
├── helm/
│   └── values.yaml                        # Helm 렌더링 파라미터 (Prometheus 연동)
└── kustomize/
    ├── base/
    │   ├── kustomization.yaml
    │   ├── resources/
    │   │   ├── metallb.yaml               # IPAddressPool, L2/BGP 리소스 정의
    │   │   └── generated/                 # make manifests 결과물 (자동 생성)
    │   └── patches/
    │       └── metallb-specker.yaml        # Speaker DaemonSet 리소스 설정
    └── overlays/
        └── dev/
            └── kustomization.yaml         # 이미지 태그 고정

4. 배포

4.1 Namespace 생성

make namespace

4.2 패키지 준비

Helm 템플릿으로 매니페스트를 생성합니다.

make manifests

4.3 배포 설정

L2 모드: metallb.yaml

kustomize/base/resources/metallb.yamladdresses 항목을 환경에 맞게 수정합니다.

Kind 환경에서는 Docker 네트워크 대역을 먼저 확인합니다.

docker network inspect kind | grep Subnet
# kustomize/base/resources/metallb.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
  - <서브넷 대역 내 IP 범위>  # 예: 192.168.0.220-192.168.0.230
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2-network
  namespace: metallb-system
spec:
  ipAddressPools:
    - ip-pool

BGP 모드: metallb.yaml

L2 모드 대신 BGP를 사용할 경우 metallb.yaml을 아래와 같이 정의합니다.

BGP 모드의 장점:

  • 트래픽 분산: ECMP(Equal-Cost Multi-Path) 라우팅으로 L2 모드의 단일 노드 병목 해소
  • 확장성: 대규모 클러스터에서 수백 개의 서비스 IP를 효율적으로 광고 가능
  • 페일오버 속도: 노드 장애 시 BGP가 자동으로 경로를 재계산하므로 L2 ARP 방식보다 빠른 복구

주의: BGP 모드는 BGP를 지원하는 라우터(또는 소프트 라우터)가 반드시 필요합니다. 라우터 없이는 피어링을 맺을 수 없어 IP 광고가 동작하지 않습니다.

# kustomize/base/resources/metallb.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
  - <할당할 IP 범위>  # 예: 10.0.0.220-10.0.0.230
  autoAssign: true
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: bgp-peer
  namespace: metallb-system
spec:
  myASN: 64500          # 클러스터(로컬) ASN
  peerASN: 64501        # 라우터(피어) ASN
  peerAddress: <라우터 IP>  # 예: 192.168.1.1
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: bgp-advertisement
  namespace: metallb-system
spec:
  ipAddressPools:
    - ip-pool

Kind 환경: Kind는 실제 BGP 라우터가 없으므로 BGP 모드 테스트는 별도의 소프트 라우터(예: GoBGP, FRR) 컨테이너가 필요합니다. 로컬 개발 환경에서는 L2 모드를 권장합니다.

helm/values.yaml

helm/values.yamlmake manifests 시 Helm 렌더링에 사용합니다. Prometheus ServiceMonitor·PrometheusRule을 활성화하고 prometheus: main 레이블로 수집 대상을 지정합니다.

# helm/values.yaml
prometheus:
  serviceMonitor:
    enabled: true
    speaker:
      additionalLabels:
        prometheus: main
    controller:
      additionalLabels:
        prometheus: main
  prometheusRule:
    enabled: true
    additionalLabels:
      prometheus: main

patches/metallb-specker.yaml

Speaker DaemonSet의 컨테이너별 리소스를 오버라이드합니다.

컨테이너CPU request/limitMemory request/limit
speaker50m / 200m64Mi / 128Mi
frr50m / 200m64Mi / 128Mi
reloader10m / 100m32Mi / 64Mi
frr-metrics10m / 100m32Mi / 64Mi

4.4 배포 실행

make preview  # 적용 전 매니페스트 확인
make apply    # 클러스터에 적용

참고: make apply 시 CRD 또는 Webhook 관련 에러가 발생하면 Troubleshooting을 참조합니다.


5. 설치 후 검증

L2 모드

IPAddressPool과 L2Advertisement가 정상 등록되었는지 확인합니다.

kubectl get ipaddresspool,l2advertisement -n metallb-system

예상 결과:

NAME                              AUTO ASSIGN   AVOID BUGGY IPS   ADDRESSES
ipaddresspool.metallb.io/ip-pool  true          false             ["192.168.0.220-192.168.0.230"]

NAME                                   IPADDRESSPOOLS   IPADDRESSPOOL SELECTORS   INTERFACES
l2advertisement.metallb.io/l2-network  ["ip-pool"]

BGP 모드

BGPPeer와 BGPAdvertisement가 정상 등록되었는지 확인합니다.

kubectl get bgppeer,bgpadvertisement -n metallb-system

BGP 세션이 정상이면 kubectl get bgppeer 출력에서 STATUSEstablished로 표시됩니다.

공통

LoadBalancer 서비스에 IP가 할당되는지 확인합니다.

kubectl get svc -A --field-selector spec.type=LoadBalancer

EXTERNAL-IP 컬럼에 <pending> 대신 IP 주소가 표시되면 정상입니다.


6. Troubleshooting

6.1 CRD가 아직 등록되지 않음

make apply 시 CRD 관련 에러가 발생합니다. 잠시 후 make apply를 재시도합니다.

6.2 Webhook Pod가 아직 준비되지 않음

make applymetallb-webhook-configuration 에러가 발생합니다. 모든 Pod가 Ready 상태가 된 후 make apply를 재시도합니다.

kubectl wait --for=condition=ready pod --all -n metallb-system --timeout=120s
make apply

6.3 strictARP 미설정 또는 IP 풀 범위 오류 (L2)

LoadBalancer 서비스가 <pending> 상태입니다.

  • 사전 요구사항의 strictARP 설정 확인
  • metallb.yaml의 IP 범위가 실제 네트워크 대역 내에 있는지 확인

6.4 BGP 세션이 Established가 되지 않음

kubectl get bgppeer -n metallb-system에서 STATUSEstablished가 아닌 경우:

  • peerAddress가 실제 라우터 IP와 일치하는지 확인
  • myASN / peerASN이 라우터 설정과 일치하는지 확인
  • 클러스터 노드와 라우터 간 네트워크 연결(방화벽, 포트 179) 확인

참고 자료