[Retry, k8s] 14. 서비스 API - LoadBalancer (MetalLB)

Date:     Updated:

카테고리:

태그:

[Retry, k8s] 14. 서비스 API - LoadBalancer (MetalLB)



🔔 LoadBalancer

  • LoadBalancer 서비스는 쿠버네티스 클러스터 외부의 로드 밸런서에 외부 통신이 가능한 가상 IP를 할당할 수 있다.

  • 외부 로드 밸런서를 사용하려면 쿠버네티스 클러스터가 구축된 인프라가 이 구조에 맞도록 설계되어 있어야 하는데, 현재는 GCP/AWS/애저(Azure)/OpenStack을 비롯한 클라우드 프로바이더가 LoadBalancer 서비스를 사용할 수 있는 환경을 제공하고 있다.

  • NodePort/ExternalIP에서는 하나의 쿠버네티스 노드에 할당된 IP 주소로 통신하기 때문에 그 노드가 단일 장애점(SPOF)이 되어 버리지만, LoadBalancer에서는 쿠버네티스 노드와 별도로 외부 로드 밸런서를 사용하기 때문에 노드 장애가 발생해도 크게 문제가 없다.

  • 구조는 NodePort 서비스를 생성하고 클러스터 외부의 로드 밸런서에서 쿠버네티스 노드로 밸런싱을 하는 형태로, k8s 클러스터 노드에 장애가 발생한 경우 그 노드에 트래픽을 전송하지 않음으로써 자동으로 복구하게 되어 있다.


🔔 MetalLB

https://metallb.universe.tf/

  • Kubernetes 사용 시 AWS, GCP, Azure 와 같은 클라우드 플랫폼에서는 자체적으로 로드 벨런서(Load Balancer)를 제공해 주지만, 온프레미스 클러스터에서는 로드 벨런싱 기능을 제공하는 모듈을 추가적으로 설치해야 한다.

  • MetalLB는 온프레미스 환경에서 쿠버네티스의 로드밸런서 서비스를 제공하는 프로젝트이다.

  • MetaLB는 L2 네트워크(ARP/NDP)와 L3 네트워크(BGP) 두가지 방식으로 로드 밸런서를 구현할 수 있다.

방식 설명
L2 네트워크(ARP/NDP) 방식 ㆍARP 요청에 응답하여 서비스 IP와 노드의 MAC 주소를 알려주는 방식

ㆍ설정이 간단하지만 네트워크 장비와 호환되어야 하고, 같은 브로드캐스트 도메인에 있어야함

ㆍ라우팅 제어가 불가능
L3 네트워크(BGP) 방식 ㆍBGP 방식은 외부 BGP 라우터와 세션을 맺고 서비스 IP에 대한 라우팅 정보를 교환하는 방식

ㆍ설정이 복잡하지만 네트워크 장비와 독립적

ㆍ라우팅 제어가 가능하고, 서비스 IP가 변경되면 BGP 업데이트 메시지를 통해 라우팅 정보를 갱신함


🔔 NodePort / (Cloud) LoadBalancer / (MetalLB) LoadBalancer동작 차이

(1) NodePort

  1. 사용자가 워크 노드에 있는 포트에 접속

  2. 접속 한 이후에 해당 워크 노드가 서비스로 이를 바인딩

  3. 서비스가 현재 노드의 상태 등의 기준으로 노드에 연결 시킴

222

(2) (Cloud) LoadBalancer

223

(3) (MetalLB) LoadBalancer

  • MetalLB은 “컨트롤러”와 “스피커”라는 두 가지 구성 요소로 이루어져 있다.

  • 컨트롤러는 작동 방식과 EXTERNAL-IP를 정의하고 관리하며, 스피커는 네트워크 정보를 광고하고 수집하여 각 파드의 경로를 제공한다.

224


🔔 MetalLB 설치

https://metallb.universe.tf/installation/

(1) strict ARP mode 활성화

kubectl edit configmap -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true  # <- false에서 true로 변경

(2) Manifest를 이용해 MetalLB 설치

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml

(3) IP Address Pool + L2Advertisement 설정

$ cat <<EOF > my-network.yaml 
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.219.190-192.168.219.199

---

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: mt-network-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool
EOF

(4) MetalLB 동작 확인

cat <<EOF > test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: almighty
  labels:
    app: almighty
spec:
  containers:
  - name: almighty
    image: docker.io/andrewloyolajeong/almighty:0.2.4

---

apiVersion: v1
kind: Service
metadata:
  name: almighty
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: almighty
  ports:
    - name: myweb
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: yourweb
      protocol: TCP
      port: 8081
      targetPort: 8081
EOF
$ kubectl get all
NAME                                     READY   STATUS    RESTARTS   AGE
pod/almighty                             1/1     Running   0          4m9s

NAME                      TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                         AGE
service/almighty          LoadBalancer   10.96.105.251    192.168.219.190   8080:31468/TCP,8081:31823/TCP   4m9s
service/kubernetes        ClusterIP      10.96.0.1        <none>            443/TCP                         4h36m

$ curl 192.168.219.190:8080

 Hello from example application. (written by Andrew)

$ curl 192.168.219.190:8081
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>


🔔 LoadBalancer 서비스 생성

설정 개요
spec.ports[].port LoadBalancer에 할당되는 가상 IP와 ClusterIP에서 수신할 포트 번호
spec.ports[].targetPort 목적지 컨테이너 포트 번호
spec.ports[].nodePort 모든 쿠버네티스 노드 IP 주소에서 수신할 포트 번호
cat <<EOF > sample-lb.yaml
apiVersion: v1
kind: Service
metadata:
  name: sample-lb
spec:
  type: LoadBalancer
  ports:
  - name: "http-port"
    protocol: "TCP"
    port: 8080
    targetPort: 80
    nodePort: 30082
  selector:
    app: sample-app
EOF
$ kubectl get service sample-lb
NAME        TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)          AGE
sample-lb   LoadBalancer   10.96.194.169   192.168.219.191   8080:32659/TCP   5s


$ curl -s http://192.168.219.191:8080
Host=192.168.219.191  Path=/  From=sample-deployment-7f47966499-k7vk7  ClientIP=10.40.0.0  XFF=

$ curl -s http://192.168.219.191:8080
Host=192.168.219.191  Path=/  From=sample-deployment-7f47966499-82lld  ClientIP=10.40.0.0  XFF=

$ curl -s http://192.168.219.191:8080
Host=192.168.219.191  Path=/  From=sample-deployment-7f47966499-llctj  ClientIP=10.40.0.0  XFF=

12


🔔 로드밸런서에 할당되는 가상 IP 정적 지정

cat <<EOF > sample-lb-fixip.yaml
apiVersion: v1
kind: Service
metadata:
  name: sample-lb-fixip
spec:
  type: LoadBalancer
  loadBalancerIP: 192.168.219.195
  ports:
  - name: "http-port"
    protocol: "TCP"
    port: 8080
    targetPort: 80
  selector:
    app: sample-app
EOF
$ kubectl get service sample-lb-fixip
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)          AGE
sample-lb-fixip   LoadBalancer   10.109.42.211   192.168.219.195   8080:30202/TCP   11s


🔔 로드 밸런서 방화벽 정책 설정

  • 외부 로드 밸런서에서 접속 제어가 구현되지 않은 쿠버네티스 환경에서 이 loadBalancerSourceRanges를 설정하면, 쿠버네티스 노드 측의 iptables를 사용하여 접속 제어 처리가 이루어진다.
apiVersion: v1
kind: Service
metadata:
  name: sample-lb-fw
spec:
  type: LoadBalancer
  ports:
  - name: "http-port"
    protocol: "TCP"
    port: 8080
    targetPort: 80
  selector:
    app: sample-app
  loadBalancerSourceRanges:
  - 10.0.0.0/8


KUBERNETES 카테고리 내 다른 글 보러가기

댓글 남기기