Notes
MetalLB Layer2와 BGP
bare-metal Kubernetes 환경에서 MetalLB가 VIP를 외부 네트워크에 노출하는 방식을 OSI 계층 관점에서 정리하고, Layer2 mode, BGP mode, 외부 L4 Load Balancer 구성의 차이를 비교한다.
- Published
- Updated
- Area
- Computer Networks
- Type
- concept
- Series
- Kubernetes Networking
- Category
- Notes
MetalLB의 위치
bare-metal 또는 k3s 같은 온프레미스 Kubernetes 환경에서는 Service type: LoadBalancer를 만들어도 AWS ELB, GCP Load Balancer, Azure Load Balancer 같은 cloud load balancer가 자동으로 생성되지 않는다.
이때 MetalLB는 Kubernetes LoadBalancer Service에 외부에서 접근 가능한 VIP(Virtual IP)를 할당하고, 해당 VIP를 네트워크에 알리는 역할을 한다.
중요한 구분은 다음과 같다.
MetalLB:
"이 VIP로 들어오는 트래픽을 어느 노드로 보내야 하는가?"
kube-proxy / CNI / Service:
"노드에 도착한 트래픽을 어느 Pod로 전달할 것인가?"
Ingress Controller:
"HTTP Host, path, TLS 기준으로 어느 Service로 보낼 것인가?"
즉, MetalLB는 보통 L7 reverse proxy도 아니고, 엄밀한 의미의 L4 Load Balancer도 아니다. MetalLB의 핵심 역할은 VIP를 외부 네트워크에 advertise하는 방식이다.
OSI 계층 관점에서 보기
| OSI Layer | 주요 개념 | Kubernetes/MetalLB와의 관계 |
|---|---|---|
| L1 Physical | 케이블, 전기 신호, NIC, 포트 | MetalLB가 직접 다루지 않음 |
| L2 Data Link | Ethernet, MAC, ARP, NDP, switching | MetalLB Layer2 mode가 주로 사용하는 계층 |
| L3 Network | IP, routing table, next-hop, BGP | MetalLB BGP mode가 주로 사용하는 계층 |
| L4 Transport | TCP, UDP, port, connection | Service port, NodePort, 외부 L4 Load Balancer와 관련 |
| L7 Application | HTTP, Host, path, TLS, gRPC | Traefik, NGINX Ingress, Envoy Gateway 등이 담당 |
MetalLB의 두 대표 mode는 이 표에서 다음 위치에 놓인다.
Layer2 mode:
ARP/NDP를 이용해 VIP -> 특정 노드 MAC 매핑을 알림
BGP mode:
BGP를 이용해 VIP prefix -> 노드 next-hop 경로를 라우터에 알림
Layer2 mode
핵심 개념
MetalLB의 Layer2 mode는 VIP를 실제로 특정 장비의 NIC에 고정으로 부여하는 방식이 아니라, 특정 노드가 ARP 또는 NDP 응답을 대신 수행하여 외부 네트워크가 해당 VIP를 그 노드의 MAC 주소로 보내도록 만드는 방식이다.
IPv4에서는 ARP가 사용되고, IPv6에서는 NDP가 사용된다.
예시를 위해 문서용 IP 대역을 사용하면 다음과 같다.
Client: 203.0.113.10
node-a:
Node IP: [REDACTED]
MAC: aa:aa:aa:aa:aa:aa
node-b:
Node IP: [REDACTED]
MAC: bb:bb:bb:bb:bb:bb
node-c:
Node IP: [REDACTED]
MAC: cc:cc:cc:cc:cc:cc
VIP:
203.0.113.240
203.0.113.240 VIP의 현재 leader가 node-a라고 하면, 흐름은 다음과 같다.
1. Client가 203.0.113.240:443으로 접속하려고 함
2. Client가 ARP 요청을 보냄
"Who has 203.0.113.240?"
3. node-a의 MetalLB speaker가 응답
"203.0.113.240 is at aa:aa:aa:aa:aa:aa"
4. Client의 ARP cache에 다음 매핑이 저장됨
203.0.113.240 -> aa:aa:aa:aa:aa:aa
5. 이후 Client는 Ethernet frame의 destination MAC을 node-a의 MAC으로 설정
6. 패킷이 node-a에 도착
7. node-a의 kube-proxy 또는 CNI datapath가 Kubernetes Service 규칙에 따라 Pod로 전달
그림으로 나타내면 다음과 같다.
Client
|
| ARP: Who has VIP?
v
node-a MetalLB speaker
|
| ARP Reply: VIP is at node-a MAC
v
Client ARP cache
|
| TCP 443 packet
v
node-a
|
| kube-proxy / Service
v
Pod on node-a / node-b / node-c
왜 Layer2 mode라고 부르는가
외부 클라이언트가 어떤 IP로 통신하려면 최종적으로 Ethernet frame의 destination MAC이 필요하다.
IP 통신 전 준비:
"이 IP의 MAC 주소가 무엇인가?"
ARP의 역할:
IP -> MAC 매핑 조회
MetalLB Layer2 mode는 이 지점에서 VIP에 대한 ARP/NDP 응답을 대신한다.
즉, 핵심은 다음과 같다.
VIP에 대한 routing 자체를 바꾸는 것이 아니라,
VIP -> leader node MAC
매핑을 ARP/NDP로 알려준다.
그래서 이 방식을 Layer2 mode라고 부른다.
VIP당 leader가 하나인 이유
같은 VIP에 대해 여러 노드가 동시에 ARP 응답을 하면 문제가 생긴다.
node-a: 203.0.113.240 is at aa:aa
node-b: 203.0.113.240 is at bb:bb
node-c: 203.0.113.240 is at cc:cc
이런 상황에서는 클라이언트와 스위치가 VIP의 MAC을 일관되게 판단하지 못한다. 결과적으로 ARP flux, MAC flap, 간헐적 연결 문제 등이 발생할 수 있다.
따라서 MetalLB Layer2 mode는 보통 VIP 하나당 하나의 speaker 노드가 ARP/NDP 응답을 맡는다.
VIP 203.0.113.240 -> node-a
VIP 203.0.113.241 -> node-b
VIP 203.0.113.242 -> node-c
여러 VIP를 사용하면 VIP별로 leader가 달라질 수 있으므로 서비스 단위 분산은 가능하다. 하지만 하나의 VIP에 대한 외부 진입점은 하나의 노드가 된다.
병목 지점
Layer2 mode에서 203.0.113.240:80, 203.0.113.240:443을 모두 하나의 ingress VIP로 사용한다면 외부 트래픽은 먼저 현재 leader 노드로 들어온다.
Client
-> VIP
-> leader node
-> kube-proxy
-> Pod
이때 병목 후보는 다음과 같다.
| 병목 후보 | 설명 |
|---|---|
| leader node NIC | VIP로 들어오는 ingress traffic이 한 노드의 NIC를 통과 |
| conntrack | connection tracking 부하 증가 가능 |
| kube-proxy | iptables/IPVS/eBPF datapath 처리량 영향 |
| CPU interrupt | 네트워크 패킷 처리로 인한 CPU 부하 |
| cross-node forwarding | leader 노드에 도착한 뒤 다른 노드의 Pod로 재전달될 수 있음 |
Layer2 mode는 간단하고 안정적이지만, 하나의 VIP에 대해 여러 노드가 동시에 ingress traffic을 받는 구조는 아니다.
장애 발생 시
기존 leader가 node-a였고 장애가 발생했다고 하자.
기존:
203.0.113.240 -> node-a MAC
장애 후:
203.0.113.240 -> node-b MAC
새로운 leader인 node-b는 네트워크에 Gratuitous ARP 또는 NDP update를 보내 VIP의 MAC 매핑을 갱신시킨다.
node-b:
203.0.113.240 is at bb:bb:bb:bb:bb:bb
주의할 점은 일부 클라이언트, 스위치, 방화벽 장비의 ARP cache 갱신이 지연될 수 있다는 것이다. 이 경우 failover 직후 짧은 연결 지연이 발생할 수 있다.
BGP mode
핵심 개념
MetalLB의 BGP mode는 ARP/NDP를 이용해 MAC 매핑을 조작하는 방식이 아니다.
대신 MetalLB speaker가 라우터 또는 L3 switch와 BGP peering을 맺고, VIP로 가는 route를 advertise한다.
node-a speaker <---- BGP ----> router
node-b speaker <---- BGP ----> router
node-c speaker <---- BGP ----> router
BGP mode에서 라우터는 다음과 같은 경로를 배울 수 있다.
203.0.113.240/32 via node-a
203.0.113.240/32 via node-b
203.0.113.240/32 via node-c
라우터가 ECMP(Equal-Cost Multi-Path)를 지원하면 같은 VIP에 대한 여러 next-hop을 동시에 사용할 수 있다.
Client A -> router -> node-a
Client B -> router -> node-b
Client C -> router -> node-c
즉 BGP mode의 핵심 장점은 외부 트래픽의 진입점 자체를 여러 노드로 분산할 수 있다는 점이다.
패킷 흐름 예시
Client
-> Router
-> ECMP hash 결과에 따라 node-a / node-b / node-c 중 하나
-> kube-proxy / CNI
-> Pod
라우터는 일반적으로 다음과 같은 값들을 기반으로 flow hash를 계산한다.
source IP
destination IP
source port
destination port
protocol
따라서 하나의 TCP connection 내부 패킷은 보통 같은 노드로 유지된다. 반면 connection이 여러 개면 서로 다른 노드로 분산될 수 있다.
Layer2 mode와의 차이
| 구분 | Layer2 mode | BGP mode |
|---|---|---|
| 주 계층 | L2 | L3 control plane |
| 핵심 기술 | ARP/NDP | BGP route advertisement |
| VIP당 외부 진입 노드 | 1개 | 여러 개 가능 |
| 분산 방식 | VIP별 leader | Router ECMP |
| 네트워크 장비 요구 | 일반 스위치/공유기에서도 가능 | BGP 가능한 라우터 또는 L3 switch 필요 |
| 장애 전환 | Gratuitous ARP/NDP | BGP route withdraw/update |
| 운영 난이도 | 낮음 | 중간 이상 |
| 확장성 | 제한적 | 상대적으로 좋음 |
BGP mode의 주의점
BGP mode는 강력하지만 네트워크 장비와 운영 지식이 필요하다.
확인해야 할 항목은 다음과 같다.
| 항목 | 확인 내용 |
|---|---|
| Router support | BGP peering 가능 여부 |
| ASN | MetalLB ASN, router ASN 설계 |
| ECMP | 여러 next-hop을 동시에 사용하는지 |
| Route policy | advertise할 prefix 제한 |
| Failure behavior | node 장애 시 route withdraw 동작 |
| Firewall | BGP session TCP 179 허용 여부 |
| Observability | BGP session 상태와 advertised route 모니터링 |
externalTrafficPolicy와의 관계
MetalLB mode만큼 중요한 설정이 externalTrafficPolicy다.
spec:
externalTrafficPolicy: Cluster
또는:
spec:
externalTrafficPolicy: Local
Cluster
externalTrafficPolicy: Cluster에서는 트래픽을 받은 노드가 전체 endpoint 중 하나로 전달할 수 있다.
Client
-> VIP
-> node-a
-> Pod on node-a / node-b / node-c
장점은 Pod 전체를 대상으로 분산할 수 있다는 점이다. 단점은 source IP가 보존되지 않거나 cross-node forwarding이 생길 수 있다는 점이다.
Local
externalTrafficPolicy: Local에서는 트래픽을 받은 노드의 local endpoint로만 전달한다.
Client
-> VIP
-> node-a
-> Pod on node-a only
장점은 source IP 보존과 불필요한 node 간 hop 감소다. 단점은 해당 Service의 Pod가 없는 노드는 트래픽을 처리할 수 없다는 점이다.
mode별 조합
| MetalLB mode | externalTrafficPolicy | 동작 | 특징 |
|---|---|---|---|
| Layer2 | Cluster | VIP leader 노드가 받은 뒤 전체 Pod로 전달 | 간단하지만 leader 노드가 ingress 병목 가능 |
| Layer2 | Local | VIP leader 노드의 local Pod로만 전달 | source IP 보존, 하지만 leader 노드의 Pod만 활성 처리 |
| BGP | Cluster | 여러 노드가 route를 advertise하고 각 노드가 전체 Pod로 전달 | 진입점 분산 가능, cross-node hop 가능 |
| BGP | Local | local endpoint가 있는 노드만 advertise하고 local Pod로 전달 | 운영상 가장 깔끔한 구조 중 하나, Pod 배치 균형 필요 |
BGP mode에서 externalTrafficPolicy: Local을 사용할 경우, local endpoint가 있는 노드만 route를 advertise하게 구성할 수 있어 트래픽 흐름이 단순해진다.
Client
-> Router ECMP
-> ingress pod가 있는 node
-> local ingress pod
-> backend Service
다만 이 경우 라우터의 분산 단위는 보통 Pod 단위가 아니라 노드 단위다. 예를 들어 node-a에 Pod 2개, node-b에 Pod 1개가 있다면 node 단위 50:50 분산 결과로 Pod 부하가 불균형해질 수 있다.
node-a:
pod-1: 25%
pod-2: 25%
node-b:
pod-1: 50%
따라서 podAntiAffinity, topologySpreadConstraints, DaemonSet 형태 배치 등을 함께 고려해야 한다.
외부 L4 Load Balancer와의 비교
MetalLB와 외부 L4 Load Balancer는 역할이 다르다.
외부 L4 Load Balancer는 VIP를 직접 소유하고 TCP/UDP connection을 여러 backend node로 분산한다.
Client
-> External L4 Load Balancer VIP
-> node-a:NodePort
-> node-b:NodePort
-> node-c:NodePort
예시는 다음과 같다.
VIP: 203.0.113.240:443
Backends:
node-a:[REDACTED_NODEPORT]
node-b:[REDACTED_NODEPORT]
node-c:[REDACTED_NODEPORT]
비교하면 다음과 같다.
| 방식 | VIP 소유 주체 | 분산 위치 | 장점 | 단점 |
|---|---|---|---|---|
| MetalLB Layer2 | Kubernetes node | VIP별 leader | 단순함, 홈랩/소규모에 적합 | VIP당 한 노드 병목 |
| MetalLB BGP | Router가 route 학습 | Router ECMP | 진입점 분산 가능 | BGP 장비와 운영 지식 필요 |
| External L4 LB | LB 장비/소프트웨어 | LB가 TCP/UDP 분산 | 성숙한 운영 기능, health check, policy 가능 | 별도 장비/VM/운영 비용 필요 |
일반적인 운영 구성
홈랩 또는 소규모 k3s
가장 현실적인 구성은 다음과 같다.
MetalLB Layer2
+ Traefik 또는 NGINX Ingress
+ VIP 1개 또는 소수
+ 내부 DNS
+ 관리 서비스는 VPN 또는 내부망 전용
예시 구조:
Client
-> VIP:443
-> Traefik
-> Kubernetes Service
-> Pod
권장 방향:
| 항목 | 권장 구성 |
|---|---|
| Public ingress | 80은 443 redirect, 실제 서비스는 443 중심 |
| Admin UI | 내부망 또는 VPN only |
| VIP pool | DHCP 범위와 겹치지 않는 별도 대역 |
| 관리 서비스 | Nexus, Longhorn, Grafana, ArgoCD 등은 외부 공개 지양 |
| 인증 | SSO, basic auth, IP allowlist, VPN 등 추가 보호 |
VIP:80과 VIP:443을 노출하는 것 자체가 위험한 것은 아니다. 위험은 보통 다음에서 발생한다.
관리용 서비스가 인증 없이 외부 공개됨
기본 계정 또는 약한 비밀번호 사용
Ingress rule이 지나치게 넓음
내부 서비스가 public Host로 노출됨
TLS 설정이 부실함
따라서 80/443은 ingress 입구로 사용하되, 어떤 Service를 외부에 노출할지 엄격히 제한해야 한다.
중간 규모 사내망
사내망에서는 두 가지 선택지가 있다.
선택지 A: Layer2 + 서비스별 VIP 분산
VIP A -> Ingress
VIP B -> Registry
VIP C -> Object Storage API
VIP D -> Monitoring Internal
이 방식은 BGP 없이도 서비스별로 leader가 달라질 수 있어 어느 정도 분산 효과를 얻을 수 있다.
단, 하나의 VIP에 대한 ingress traffic은 여전히 한 노드에 먼저 들어온다.
선택지 B: BGP 가능한 라우터 도입
라우터나 L3 switch가 BGP와 ECMP를 지원한다면 MetalLB BGP mode를 사용할 수 있다.
Router
BGP peer node-a
BGP peer node-b
BGP peer node-c
VIP
advertised by node-a/node-b/node-c
이 경우 ingress VIP 하나에 대해서도 여러 노드가 동시에 진입점이 될 수 있다.
프로덕션 온프레미스
프로덕션에서는 보통 다음 요소를 함께 고려한다.
1. 이중화된 router 또는 L4 Load Balancer
2. MetalLB BGP 또는 외부 L4 LB
3. Ingress Controller 다중 replica
4. externalTrafficPolicy: Local 검토
5. Pod anti-affinity 또는 topology spread
6. TLS 인증서 자동화
7. 관리 UI의 VPN/SSO/IP allowlist 보호
8. NetworkPolicy로 namespace 간 접근 제한
9. BGP session, route advertisement, ingress traffic 모니터링
10. 장애 시 failover 검증
프로덕션에 가까운 구조는 다음과 같다.
Client
-> Firewall / Router / L4 LB
-> Kubernetes node
-> Ingress Controller
-> Service
-> Pod
BGP mode를 사용한다면 다음 구조가 자연스럽다.
Client
-> Router ECMP
-> node with local ingress endpoint
-> Ingress Controller
-> Backend Service
예시 설정
MetalLB Layer2 예시
아래 예시는 실제 내부 IP를 사용하지 않고 문서용 주소로 표현했다. 실제 환경에서는 DHCP 범위와 겹치지 않는 내부 대역을 사용해야 한다.
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: example-pool
namespace: metallb-system
spec:
addresses:
- 203.0.113.240-203.0.113.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example-l2
namespace: metallb-system
spec:
ipAddressPools:
- example-pool
MetalLB BGP 예시
실제 ASN, router IP, node IP는 환경에 따라 달라지므로 아래 값은 예시로만 봐야 한다.
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: bgp-pool
namespace: metallb-system
spec:
addresses:
- 203.0.113.240/28
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
name: router-peer
namespace: metallb-system
spec:
myASN: 64500
peerASN: 64501
peerAddress: "[REDACTED_ROUTER_IP]"
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-advertisement
namespace: metallb-system
spec:
ipAddressPools:
- bgp-pool
Ingress용 LoadBalancer Service 예시
apiVersion: v1
kind: Service
metadata:
name: ingress-controller
namespace: ingress-system
annotations:
metallb.io/loadBalancerIPs: 203.0.113.240
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: ingress-controller
ports:
- name: http
port: 80
targetPort: 8000
protocol: TCP
- name: https
port: 443
targetPort: 8443
protocol: TCP
externalTrafficPolicy: Local은 source IP 보존과 트래픽 경로 단순화에 유리하지만, ingress pod가 배치된 노드만 트래픽을 처리할 수 있다는 점을 고려해야 한다.
검증 포인트
MetalLB를 구성한 뒤에는 다음을 확인해야 한다.
| 검증 항목 | 확인 방법 |
|---|---|
| LoadBalancer IP 할당 | kubectl get svc -A |
| MetalLB speaker 상태 | kubectl get pods -n metallb-system |
| Layer2 ARP 응답 | client 또는 같은 L2 network에서 ARP cache 확인 |
| BGP session 상태 | router 또는 FRR에서 BGP neighbor 확인 |
| VIP 접근성 | curl -vk https://<VIP> |
| source IP 보존 | ingress access log 또는 application log 확인 |
| failover | leader node drain/shutdown 후 VIP 접근성 확인 |
| 부하 분산 | 여러 connection에서 node별 ingress traffic 관찰 |
| 보안 노출면 | 외부에서 80/443 외 불필요한 port 접근 차단 확인 |
예시 명령:
kubectl get svc -A
kubectl get pods -n metallb-system -o wide
kubectl describe svc -n ingress-system ingress-controller
Layer2 mode라면 클라이언트 측에서 ARP cache를 확인한다.
arp -a
BGP mode라면 router 또는 FRR 쪽에서 neighbor와 route를 확인한다.
show bgp summary
show bgp ipv4 unicast
주의할 점
80/443 노출 자체보다 중요한 것
VIP:80과 VIP:443을 여는 것 자체는 일반적인 운영 방식이다. 문제는 그 뒤에 어떤 서비스가 붙어 있는지다.
위험한 예시는 다음과 같다.
Longhorn UI public exposure
Kubernetes Dashboard public exposure
Grafana public exposure without SSO
Nexus admin UI public exposure
MinIO console public exposure
ArgoCD public exposure without strong auth
권장 구조는 다음과 같다.
public:
80 -> 443 redirect
443 -> Ingress
internal only:
admin UI
storage UI
registry admin
monitoring
dashboard
Layer2 mode의 한계
Layer2 mode는 단순하고 편하지만, 하나의 VIP에 대해 active ingress node가 하나다.
VIP 203.0.113.240 -> node-a
따라서 트래픽이 커지면 다음을 고려한다.
서비스별 VIP 분산
BGP mode 전환
외부 L4 Load Balancer 도입
Ingress Controller 배치 최적화
BGP mode의 운영 부담
BGP mode는 확장성이 좋지만 운영 부담이 있다.
BGP session 관리
ASN 설계
route policy
ECMP 확인
장애 시 route withdraw 검증
라우터 설정 백업
BGP mode를 도입하기 전에는 라우터가 ECMP를 실제로 지원하는지, 그리고 여러 next-hop을 기대한 방식으로 사용하는지 확인해야 한다.
선택 기준
| 환경 | 추천 |
|---|---|
| 단일 노드 또는 매우 작은 홈랩 | MetalLB Layer2 |
| 3~5대 k3s 홈랩 | MetalLB Layer2 + VIP 분산 |
| BGP 가능한 라우터가 있는 사내망 | MetalLB BGP 검토 |
| 트래픽이 큰 온프레미스 | MetalLB BGP + ECMP 또는 External L4 LB |
| 강한 운영 통제와 health check가 필요한 환경 | External L4 LB |
| 관리 UI가 많은 환경 | Ingress + VPN/SSO/IP allowlist |
요약
MetalLB를 이해할 때 핵심은 다음이다.
Layer2 mode:
ARP/NDP를 이용해 VIP -> 특정 노드 MAC 매핑을 알린다.
VIP 하나당 진입점은 하나의 leader node다.
단순하지만 큰 트래픽에서는 병목이 될 수 있다.
BGP mode:
BGP를 이용해 VIP route를 라우터에 advertise한다.
ECMP를 통해 여러 node가 동시에 진입점이 될 수 있다.
확장성은 좋지만 BGP 가능한 네트워크 장비와 운영 지식이 필요하다.
External L4 Load Balancer:
LB가 VIP를 소유하고 TCP/UDP connection을 node:port로 분산한다.
성숙한 운영 기능을 제공하지만 별도 장비 또는 소프트웨어 운영이 필요하다.
k3s 기반 홈랩이나 소규모 사설망에서는 우선 다음 구성이 현실적이다.
MetalLB Layer2
+ Ingress Controller
+ VIP 1개 또는 서비스별 VIP 분산
+ 관리 서비스는 내부망/VPN 전용
이후 네트워크 트래픽이 커지거나 라우터가 BGP/ECMP를 안정적으로 지원한다면 다음 단계로 확장한다.
MetalLB BGP
+ ECMP
+ externalTrafficPolicy: Local
+ ingress pod의 노드별 균등 배치