목차

Kubernetes Service - MetalLB

  • 온프레미스 클러스터는 Load Balancer를 구매하지 않는 한 부하분산 기능 및 외부연결용 IP 제공하는 리소스가 필요
  • MetalLB는 Bare Metal 환경(가상화 하지 않고 사용하는 고성능 물리 서버)에서 사용 할 수 있는 Load Balancer 기능을 제공(CNCF 오픈소스 프로젝트)
  • MetalLB는 네트워크 로드 밸런서를 통해 “외부 IP 주소 풀"을 사용하여 온프레미스 및 VM등의 가상 환경 클러스터에서 외부 서비스 접근 가능

  • 온프레미스 환경에서 Service “type:LoadBalancer"의 EXTERNAL-IP <pending> 할당
  • Load Balancer IP로 전달되는 트래픽을 Node로 전달 하면 MetalLB의 역할은 끝남
  • 제공되는 서비스 IP(EXTERNAL-IP)는 ping 작동 안되며 서비스에 대한 동작은 제공된 IP를 통해 애플리케이션에 액세스하여 확인 가능
  • Layer2 mode (링크)
    • 클러스터 노드 중 하나(리더 노드)가 외부에서 접속 가능한 IP의 ARP request를 네트워크 인터페이스에서 할당처리
      • ARP(Address Resolution Protocol)? IP주소를 MAC주소와 매칭 시키기 위한 프로토콜
    • 구성이 단순하여 대용량 처리에 부하가 심하여 테스트용으로 권장
  • BGP mode (링크)
    • 고가용성이 구성가능하여 운영환경에서 주로 사용
  • Controller(Deployment)
    • 구성된 IP pool에서 로드 밸런싱을 수행할 EXTERNAL_IP 주소를 할당하는 역할
  • Speaker(DaemonSet)
    • Layer2 or BGP모드를 통해 할당된 IP를 알리는 역할 수행
      • speak pod는 node IP를 사용
  • 서비스 계정(컨트롤러 및 스피커)
    • 서비스 계정은 컨트롤러 및 스피커 구성요소 작동에 필요한 RBAC 사용 권한이 포함
  • 사용할 IP 주소의 대역 설정을 통해 IP제공
  • 설치 후 필수 → “EXTERNAL_IP 대역”, “설정 모드” 지정을 위한 configmap 배포
  • Node NIC에 IP를 바인딩 하지 않고 로컬 네트워크의 ARP 요청에 응답하여 컴퓨터의 MAC주소를 클라이언트에게 제공하는 방식으로 작동
  • LoadBalancer 생성 → MetalLB L2 Controller는 APIserver를 통해 EXTERNAL-IP를 리더 Speaker pod에 할당 → Speaker pod는 소유하고 있다는 것을 ARP를 이용해 모든 노드 Speak Pod에 전파

  • Node앞에 위치해 각 Node들로 트래픽을 분산하는역할
  • L4 LoadBalancer가 생성되고 ClusterIP서비스 및 NodePort 서비스 가 암시적으로 생성됨
  • NodePort(30000~32767)서비스 위에 적용
  • Public으로 사용 가능한 IP주소 및 DNS주소를 제공을 통해 Private IP 주소 및 NodePort포트로 클러스터의 Node에 트래픽을 Load Balancing 하고 전달
  • 웹 애플리케이션이나 API와 같이 높은 트래픽 양을 처리해야 하는 애플리케이션에 유용
  • 클라우드 환경이 아닌 온프레미스(VM)환경에서 LoadBalancer를 사용할경우 Public주소를 제공 할 수 있는 MetalLB(bare metal load balancer)모듈을 설치해주어야 한다.
#설정
$ kubectl edit configmap -n kube-system kube-proxy
apiVersion: v1
data:
...
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      strictARP: true #false -> true로 변경


#설치
#아래의 코드가 작동하지 않으면
#https://metallb.universe.tf/installation/
#Installation By Manifest
#To install MetalLB, apply the manifest:
#여기서 주소 복사하여 설치
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.4/config/manifests/metallb-native.yaml

#확인
#Pod IP와 Node IP가 같은 것을 확인
$ kubectl get po -n metallb-system -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
controller-756c6b677-5p8rl   1/1     Running   0          25s   10.109.131.6   k8s-node2    <none>           <none>
speaker-ddps6                0/1     Running   0          25s   10.10.10.90    k8s-master   <none>           <none>
speaker-jw4n7                0/1     Running   0          25s   10.10.10.92    k8s-node2    <none>           <none>
speaker-tjsks                0/1     Running   0          25s   10.10.10.91    k8s-node1    <none>           <none>

$ kubectl get no -o wide
NAME         STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
k8s-master   Ready    control-plane   3d22h   v1.28.8   10.10.10.90   <none>        Ubuntu 22.04.4 LTS   6.5.0-26-generic     containerd://1.6.28
k8s-node1    Ready    <none>          3d22h   v1.28.8   10.10.10.91   <none>        Ubuntu 22.04.4 LTS   5.15.0-101-generic   containerd://1.6.28
k8s-node2    Ready    <none>          3d22h   v1.28.8   10.10.10.92   <none>        Ubuntu 22.04.4 LTS   5.15.0-101-generic   containerd://1.6.28

ip-pool.yaml

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.10.10.192/26
  # 10.10.10.192 ~ 10.10.10.255

l2-pool.yaml

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: network-l2-lb
  namespace: metallb-system
spec:
  ipAddressPools:
  - ip-pool
  #ip pool 파일 만들어서 추가 가능
$ kubectl apply -f ip-pool.yaml

$ kubectl apply -f l2-pool.yaml

#확인
$ kubectl get all -n metallb-system
NAME                             READY   STATUS    RESTARTS   AGE
pod/controller-756c6b677-5p8rl   1/1     Running   0          39m
pod/speaker-ddps6                1/1     Running   0          39m
pod/speaker-jw4n7                1/1     Running   0          39m
pod/speaker-tjsks                1/1     Running   0          39m

NAME                              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/metallb-webhook-service   ClusterIP   10.102.2.6   <none>        443/TCP   39m

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/speaker   3         3         3       3            3           kubernetes.io/os=linux   39m

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/controller   1/1     1            1           39m

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/controller-756c6b677   1         1         1       39m

#테스트
$ kubectl create deployment metallb-deploy --image=traefik/whoami --replicas=3 --port=80

$ kubectl expose deployment metallb-deploy --name=metallb-deploy-svc --type=LoadBalancer --port=80 --target-port=80

$ kubectl get events -w