MetalLB는 Cloud가 아닌 환경에서 Loadbalancer를 사용할 수 있는 솔루션입니다.
L2 및 BGP 모드를 지원하고 있으며, 무료로 사용 가능합니다.
이유는 Service의 Loadbalancer 타입에 있습니다.
해당 타입을 사용하기 위해서는 반드시 CSP의 LB가 필요합니다.
클러스터의 외부와 통신하기 위해서는 LB가 없이도 Nodeport 타입을 설정하면 통신이 가능합니다.
그러나, Nodeport 타입을 사용하면 <Node IP>:<Nodeport>와 같이 IP에 Port를 붙혀야 정상적으로 시스템이 인식합니다.
MetalLB의 L2모드는 모드 명 처럼, 2계층 통신을 사용합니다. 클러스터에 구성 시, speaker라는 daemonset이 생성되며, 노드마다 배포된 파드는 LB의 외부IP(ExternalIP)를 2가지 방법을 통해 제어합니다.

어떻게 리더 speaker 파드를 실행하는 노드로 ExternalIP 패킷이 전송되도록 할 수 있는 것일까요?
해답은 GARP 프로토콜에 있습니다.
먼저, GARP 프로토콜은 자신의 IP가 네트워크 망에서 자기 IP에 해당하는 MAC 주소를 알리는 ARP Reply(ARP 프로토콜 방식)없이 브로드캐스트를 하는 것입니다.
<흐름 순서 정리>
1. 리더 speaker 파드가 External IP를 가짐
External IP → MAC 주소 (Speaker Pod가 있는 노드의 NIC MAC)MetalLB 또한 iptables를 활용합니다.
리더 speaker 파드가 실행되는 노드의 External IP로 패킷이 접근하면, 해당 노드의 iptables 규칙에 의해 각 노드의 파드로 분산되어 패킷이 전달됩니다.

가장 큰 첫 번째 단점은 리더 speaker 파드를 가진 노드에 대한 부하도가 증가하는 것입니다.
GARP를 통해 모든 External IP로 접근하는 패킷을 리더 speaker 파드로 전달하기에, 당연한 수순입니다.
두 번째 단점은 가용성 부족입니다. 리더 speaker에 대한 장애 발생 시, 네트워크 순단이 생길 수 밖에 없는 구조이고, 새로운 리더가 선출되기 전까지 통신되지 않습니다.
실습을 위한 전제 조건이 있는데, VM을 클러스터링 맺은 경우 같은 서브넷 대역에 존재해야합니다.
MetalLB 설치
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
Layer2 모드 설정(configmap or CRD)
IP Address Pool과 L2Advertisement 리소스를 생성합니다.
# metallb-config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: my-pool
namespace: metallb-system
spec:
addresses:
- 192.168.0.240-192.168.0.250 # 이 IP 대역은 클러스터 외부와 충돌 없어야 함
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2
namespace: metallb-system
spec: {}
# nginx-lb.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
kubectl get svc nginx-lb 