MetalLB는 Kubernetes 환경에서 LoadBalancer 서비스를 제공하는 오픈소스 네트워크 로드 밸런서이다. 기본적으로 Kubernetes의 LoadBalancer 타입 서비스는 클라우드 환경(GCP, AWS, Azure 등)에서만 동작하는데, MetalLB를 사용하면 온프레미스(베어메탈) 환경에서도 LoadBalancer 서비스를 사용할 수 있다.
Kubernetes API를 감시하며 LoadBalancer 서비스가 생성되었을 때 적절한 외부 IP를 할당.
Layer 2 모드: 특정 노드가 외부 IP를 직접 통지하는 방식 (ARP/NDP 활용).
BGP 모드: MetalLB가 라우터와 BGP 세션을 맺고 외부 네트워크에 IP를 통지.
strictARP true로 변경한다.
kubectl edit configmap -n kube-system kube-proxy
vagrant@master:~$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.4/config/manifests/metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/servicel2statuses.metallb.io created
serviceaccount/controller created
serviceaccount/speaker created
role.rbac.authorization.k8s.io/controller created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/controller created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
configmap/metallb-excludel2 created
secret/metallb-webhook-cert created
service/metallb-webhook-service created
deployment.apps/controller created
daemonset.apps/speaker created
validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created
가용 노드 IP를 확인한다.
vagrant@master:~$ k get no -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready control-plane 13d v1.28.15 192.168.56.10 <none> Ubuntu 20.04.6 LTS 5.4.0-189-generic containerd://1.7.25
slave1 Ready <none> 13d v1.28.15 192.168.56.101 <none> Ubuntu 20.04.6 LTS 5.4.0-189-generic containerd://1.7.25
slave2 Ready <none> 13d v1.28.15 192.168.56.102 <none> Ubuntu 20.04.6 LTS 5.4.0-189-generic containerd://1.7.25
slave3 NotReady <none> 13d v1.28.15 192.168.56.103 <none> Ubuntu 20.04.6 LTS 5.4.0-189-generic containerd://1.7.25
slave4 Ready <none> 13d v1.28.15 192.168.56.104 <none> Ubuntu 20.04.6 LTS 5.4.0-189-generic containerd://1.7.25
MetalLB가 사용할 IP 범위를 설정한다.
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: mypool-01
namespace: metallb-system
spec:
addresses:
- 192.168.56.101-192.168.56.104
vagrant@master:~$ k apply -f mypool-01.yml
ipaddresspool.metallb.io/mypool-01 created
Layer 2 모드는 ARP(IPv4) 또는 NDP(IPv6)를 사용하여 특정 노드가 외부 IP를 광고한다. L2Advertisement가 있어야 MetalLB가 IP를 네트워크에 알리고, 트래픽을 특정 노드로 라우팅할 수 있다. 만약 L2Advertisement를 설정하지 않으면, MetalLB는 Layer 2 모드에서 LoadBalancer 서비스를 동작시키지 않는다.
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
namespace: metallb-system
name: example
spec:
ipAddressPools:
- mypool-01
nodeSelectors:
- matchLabels:
kubernetes.io/hostname: slave1
- matchLabels:
kubernetes.io/hostname: slave2
vagrant@master:~$ k apply -f l2a.yml
l2advertisement.metallb.io/example created
vagrant@master:~$ k get svc -n nginx-controller
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-ingress-nginx-controller LoadBalancer 10.110.48.246 192.168.56.102 80:31565/TCP,443:32482/TCP 47m
k edit ing mynginx 로 확인해 보니 하단 status에 IP가 부여된 것을 알 수 있다. 이제 노드 IP로 브라우저에서 화면 확인이 가능하다.
...
spec:
ingressClassName: nginx
rules:
- host: nginx.mydomain
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: Prefix
status:
loadBalancer:
ingress:
- ip: 192.168.56.101
hosts 파일에 내부 도메인명을 등록하여 인그레스에서 호스팅 기반으로 라우팅 하게 한다.
sudo vi /etc/hosts
192.168.56.101 nginx.mydomain
vagrant@master:~$ ping nginx.mydomain
PING nginx.mydomain (192.168.56.101) 56(84) bytes of data.
64 bytes from nginx.mydomain (192.168.56.101): icmp_seq=1 ttl=64 time=1.44 ms
64 bytes from nginx.mydomain (192.168.56.101): icmp_seq=2 ttl=64 time=0.697 ms
vagrant@master:~$ k get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
mynginx nginx nginx.mydomain 192.168.56.101 80 12d
vagrant@master:~$ curl nginx.mydomain
<H1>hello</H1>
윈도우에서 C:\Windows\System32\drivers\etc\hosts 파일을 수정하면 브라우저에서 확인이 가능하다.
192.168.56.101 nginx.mydomain
