본문 바로가기
K8s/Advanced Network

[KANS3] 5. MetalLB + IPVS

by okms1017 2024. 10. 6.
728x90

✍ Posted by Immersive Builder  Seong

 

0. LoadBalancer

LoadBalancer 타입

로드밸런서 타입은 서비스를 외부로 노출하는 역할을 합니다. 쿠버네티스는 로드밸런서를 직접 제공하지 않으므로 L4 장비 또는 클라우드 사업자의 로드밸런서 서비스를 통합하여 구현합니다. 온프레미스 환경에서는 Citrix, F5 등 별도의 네트워크 장비 없이 소프트웨어 기반으로 로드밸런서를 구현할 수 있습니다. 대표적으로 OpenELB, MetalLB, LoxiLB 등이 있습니다. 

 

동작 방식

[ 클라우드 환경 ]

 

  1. Client > CSP LB > NodePort > Pods : LB 단과 NodePort 이후 iptables 단에서 부하분산이 2번 발생합니다. 
  2. Client > CSP LB > Pods : LB에서 직접 파드로 부하분산하며, LB 컨트롤러가 파드의 IP를 LB에 전달합니다. ex) VPC CNI

 

[ 온프레미스 환경 ]

 

  1. Client > L4 Dev > NodePort > Pods : 별도의 장비가 필요한 부분 외에 클라우드 환경의 1번 동작 방식과 동일합니다. ex) Citrix, F5 
  2. Client > L4 Dev > Pods : 별도의 장비가 필요한 부분 외에 클라우드 환경의 2번 동작 방식과 동일합니다. 
  3. Client > SW LB > Pods : 가상의 LB를 통해 각 서비스로 전달합니다. ex) OpenELB, Metal LB

 

* 단점 

- LB 타입 서비스 생성 시마다 LB 리소스가 생성되므로 자원 활용이 비효율적임 => HTTP의 경우 Ingress 사용 

- 도메인 기반 라우팅, TLS 종료 등 HTTP/HTTPS 프로토콜 처리에 부족함 => Ingress 도입 필요 

 

** LB 타입 서비스를 꼭 사용해야만 하는 이유는 무엇일까 ?

- 클라우드 환경(AWS,GCP,Azue)에서 제공하는 네이티브 로드밸런서 기능을 통해 외부 트래픽을 효율적으로 처리함

- 외부 트래픽을 쿠버네티스 클러스터로 라우팅할 때 특정 IP 또는 도메인 주소로 단순화

- Ingress가 처리하지 못하는 TCP/UDP/SCTP 프로토콜을 처리함 

- 내부 IP 노출, 포트 제한 및 고정, 다중 연결포인트 등 NodePort 의 단점을 보완

 

1. MetalLB

MetalLB 란?

MetalLB는 BareMetalLoadBalancer의 약자로 소프트웨어 기반의 로드밸런서 구현체입니다. 

MetalLB는 온프레미스 환경에서 사용 가능한 서비스로, L2 모드와 BGP 모드 두 가지가 있습니다. 

 

  • L2 모드 

LB 타입 서비스를 생성할 때 Speaker 파드 중 리더를 선출하고 해당 External IP에 대한 요청을 리더 파드가 위치한 노드로만 전달하는 방식입니다. 노드로 전달된 요청은 다시 iptables 분산룰에 의해 목적지 파드로 전달됩니다. 리더 파드는 GARP(Gratuitous ARP) 프로토콜을 통해 자신의 External IP에 대한 선점 여부를 다른 멤버 파드들에게 전파하고 사용하지 못하도록 합니다. 만약, 리더 파드에 장애가 발생하면 나머지 멤버 파드 중 자동으로 리더를 재선출합니다. 

 

MetalLB - L2 Mode (CloudNet@)

[ 제약사항 ]

 

  1.  single-node bottlenecking : 서비스가 1개일 경우, 리더 파드가 존재하는 노드로만 서비스 접근 트래픽이 유입되어 부하가 집중됩니다. 
  2. potentially slow failover : 리더 파드(노드) 장애 시, 리더를 재선출하고 GARP 전파 및 갱신이 완료되기까지 약 20~60초 다운타임이 발생합니다. 

 

  • BGP 모드 

스피커 파드가 BGP 프로토콜을 통해 서비스의 External IP를 전파하고, 외부에서 라우터를 통해 ECMP 라우팅으로 부하 분산 접속하는 방식입니다. ECMP(Equal-Cost Multi-Path) 라우팅은 동일한 비용(메트릭)을 가진 경로가 다수 존재할 때, 해당 경로들로 트래픽을 분산하여 라우팅합니다. BGP 모드는 규모가 있고 클라이언트 IP를 보존해야 하는 환경, 장애 시 빠른 절체가 필요하고 네트워크 팀 협조가 가능한 환경에서 사용하는 것을 권장합니다.  

 

MetalLB - BGP Mode (CloudNet@)

 

MetalLB 호환성 

  • 대부분의 클라우드 플랫폼(AWS, Azure, GCP)과 호환되지 않습니다. 
  • 일부 CNI(ex.Calico, Weave)와 연동 이슈가 있습니다. 

Network Addon Compatibility

 

L2 모드 구성 및 확인 

[ 파드 배포 ] 

 

1번, 2번 워커노드에 각각 웹 파드를 하나씩 배포합니다. 

 

# web-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: webpod1
  labels:
    app: webpod
spec:
  nodeName: myk8s-worker
  containers:
  - name: container
    image: traefik/whoami
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: webpod2
  labels:
    app: webpod
spec:
  nodeName: myk8s-worker2
  containers:
  - name: container
    image: traefik/whoami
  terminationGracePeriodSeconds: 0

 

 

 

[ MetalLB 설치 ]

 

Kubernetes manifests로 MetalLB를 설치합니다. 

 

# MetalLB 설치(Prometheus 포함)
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/refs/heads/main/config/manifests/metallb-native-prometheus.yaml

# MetalLB 설치(Prometheus 미설치)
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/refs/heads/main/config/manifests/metallb-native.yaml

 

모든 노드에 Speaker 파드가 데몬셋으로 배포됩니다. 

 

데몬셋으로 배포되는 Speaker 파드는 호스트 네트워크(172.18.0.0/24)를 사용합니다.

그리고 metalLB 컨트롤러는 디플로이먼트로 배포됩니다. 

 

L2 모드와 BGP 모드를 위한 CRD가 제공됩니다. 

 

서비스의 External IP로 사용할 IP 대역을 지정해야 합니다. 

 

# metallb-svc-ippool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: my-ippool
  namespace: metallb-system
spec:
  addresses:
  - 172.18.255.200-172.18.255.250

 

그리고 설정한 IP 대역을 L2 모드가 사용할 수 있도록 허용해야 합니다. 

 

# l2-advertise.yaml 

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-l2-advertise
  namespace: metallb-system
spec:
  ipAddressPools:
  - my-ippool

 

 

[ LB 타입 서비스 배포 ] 

 

웹 파드를 대상으로 하는 서비스를 3개 배포합니다. 

 

# web-svc.yaml 

apiVersion: v1
kind: Service
metadata:
  name: svc1
spec:
  ports:
    - name: svc1-webport
      port: 80
      targetPort: 80
  selector:
    app: webpod
  type: LoadBalancer  
---
apiVersion: v1
kind: Service
metadata:
  name: svc2
spec:
  ports:
    - name: svc2-webport
      port: 80
      targetPort: 80
  selector:
    app: webpod
  type: LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
  name: svc3
spec:
  ports:
    - name: svc3-webport
      port: 80
      targetPort: 80
  selector:
    app: webpod
  type: LoadBalancer

 

각 서비스에 External IP(172.18.255.200~202)와 NodePort(30548,30641,30879)가 할당된 모습입니다. 

 

서비스 이벤트 로그를 확인해보면 External IP 별로 리더 Speaker 파드가 배포된 노드를 확인할 수 있습니다. 

svc1, svc2를 담당하는 리더 파드가 위치한 노드는 1번 워커노드(myk8s-worker)이고, svc3을 담당하는 리더 파드가 위치한 노드는 3번 워커노드(myk8s-worker3)입니다. 

 

외부 클라이언트에서 각 서비스로 arp 요청을 보낸 후 neighbor 장비의 Mac 주소를 확인합니다. 

svc1(172.18.255.200), svc2(172.18.255.201)에 대한 요청은 myk8s-worker(172.18.0.3, 02:42:ac:12:00:03)으로 전달되고, svc3(172.18.255.202)에 대한 요청은 myk8s-worker3(172.18.0.2, 02:42:ac:12:00:02)로 전달됨을 알 수 있습니다. 

 

 

[ 서비스 접속 테스트 ] 

 

이제 외부 클라이언트는 클러스터 노드의 IP가 아닌 서비스의 External IP를 통해서 내부 어플리케이션에 접속합니다. 

 

여러 번 반복 접속을 시도하였을 때, 부하가 웹 파드(webpod1,webpod2)에 고루 분산됩니다. 

 

LoadBalancer 타입은 NodePort와 ClusterIP를 포함하므로 클러스터 내부에서 접속도 가능합니다. 

 

 

[ IPTables 정책 확인 ] 

 

PREROUTING ▶ KUBE-SERVICES ▶ KUBE-EXT-* ▶ KUBE-SVC-* ▶ KUBE-SEP-* ▶KUBE-POSTROUTING

  • PREROUTING

  • KUBE-SERVICES

  • KUBE-EXT-DLGPAL4ZCYSJ7UPR

  • KUBE-SVC-DLGPAL4ZCYSJ7UPR

  • KUBE-SEP-6L26EVW6JDANNGAB

  • KUBE-SEP-M3FYXQ5CIRDIPFIK

  • KUBE-POSTROUTING

 

Fail-Over 테스트 

[ 장애 재현 ] 

 

리더 파드가 존재하는 1번 워커노드(myk8s-worker)를 중지합니다. 

 

지속적으로 반복 접속을 시도하여 모니터링합니다. 접속이 불안정한 상태가 약 40초 간(18:17:08 ~ 18:17:45) 지속되고나서 안정화되었습니다. 

 

svc1, svc2를 담당하는 리더 파드가 재선출되어 각각 myk8s-worker2와 myk8s-worker3 노드의 Speaker 파드로 지정되었습니다. 

 

 

[ 장애 원복 ] 

 

1번 워커노드(myk8s-worker)를 정상화합니다. 

 

연결 실패 현상 없이 변경된 리더 파드가 원복됩니다. => 다운타임 발생 여부는 로그 확인 필요

 

※ externalTrafficPolicy:Local 

MetalLB L2 모드에서 Client IP를 보존하기 위해 externalTrafficPolicy:Local로 설정하면 리더 노드에 어플리케이션 파드가 존재하지 않을 시 장애가 발생합니다. (비권장) 

반면, MetalLB BGP 모드에서는 ECMP 라우팅을 통한 부하분산이 되므로 해당 설정을 적극 권장합니다. 

 


2. IPVS

IPVS Proxy 모드

IPVS 프록시 모드는 리눅스 커널에서 제공하는 L4 로드밸런서인 IPVS가 서비스 프록시 역할을 수행하는 모드입니다. 

패킷 로드밸런싱 처리 시, IPVS가 IPTables 보다 높은 성능을 보여줍니다. IPTables 모드와 유사하게 netfilter를 사용하지만, Hash Table을 기본 데이터 구조로 사용하고 커널 영역에서 동작합니다. 이는 IPVS 모드의 kube-proxy가 IPTables 모드의 kube-proxy보다 지연 시간이 짧은 트래픽을 리다이렉션하고, 프록시 규칙을 동기화할 때 성능이 훨씬 향상됨을 의미합니다. 다른 프록시 모드와 비교하였을 때, IPVS 모드는 높은 네트워크 트래픽 처리량도 지원합니다. 

 

IPVS 분산 알고리즘 

IPVS Proxy 모드는 rr, wrr, lc, wlc, lblc, lblcr, dh, sh, sed, nq 등 다양한 알고리즘을 지원합니다.

 

rr Round Robin 실제 서버에 한 번씩 번갈아가며 접속하는 방식 
wrr Weighted Round Robin 라운드 로빈 방식에서 실제 서버에 가중치를 주어 가중치가 높은 서버에 더 자주 접속하는 방식
lc Least Connection 가장 접속이 적은 실제 서버로 더 많은 요청을 배분하는 방식
wlc Weighted Least Connection Least Connection 방식에 가중치를 주어 특정 서버에 더 많은 작업을 할당하는 방식
lblc Locality based Least Connection 클라이언트의 위치를 고려하여 가장 적은 연결을 처리중인 서버로 할당하는 방식
lblcr Locality Based Least Connection with Replication LBLC 방식에 복제 기능을 추가하여 클라이언트가 요청한 데이터가 해당 서버에 없을 경우 다른 서버로부터 복제하여 요청을 처리하는 방식 
dh Destination Hashing 목적지 IP를 기준으로 해쉬 함수를 적용하여 배분하는 방식
sh Source Hashing 소스 IP를 기준으로 해쉬 함수를 적용하여 배분하는 방식
sed Shortest Expected Delay 예상 지연이 가장 짧은 서버에 들어오는 작업을 할당하는 방식
nq Never Queue 들어오는 작업을 유휴 서버에 할당하는 방식 

 

IPSET

IPTables로 5000건 이상의 룰셋이 등록 되었을 때 시스템의 성능이 급격하게 떨어지는 반면, 룰을 줄이기 위해 IP들의 집합으로 관리하는 방법입니다. 

 

set name members usage
KUBE-CLUSTER-IP All Service IP + port masquerade for cases that masquerade-all=true or clusterCIDR specified
KUBE-LOOP-BACK All Service IP + port + IP masquerade for resolving hairpin issue
KUBE-EXTERNAL-IP Service External IP + port masquerade for packets to external IPs
KUBE-LOAD-BALANCER Load Balancer ingress IP + port masquerade for packets to Load Balancer type service
KUBE-LOAD-BALANCER-LOCAL Load Balancer ingress IP + port with externalTrafficPolicy=local accept packets to Load Balancer with externalTrafficPolicy=local
KUBE-LOAD-BALANCER-FW Load Balancer ingress IP + port with loadBalancerSourceRanges Drop packets for Load Balancer type Service with loadBalancerSourceRanges specified
KUBE-LOAD-BALANCER-SOURCE-CIDR Load Balancer ingress IP + port + source CIDR accept packets for Load Balancer type Service with loadBalancerSourceRanges specified
KUBE-NODE-PORT-TCP NodePort type Service TCP port masquerade for packets to NodePort(TCP)
KUBE-NODE-PORT-LOCAL-TCP NodePort type Service TCP port with externalTrafficPolicy=local accept packets to NodePort Service with externalTrafficPolicy=local
KUBE-NODE-PORT-UDP NodePort type Service UDP port masquerade for packets to NodePort(UDP)
KUBE-NODE-PORT-LOCAL-UDP NodePort type service UDP port with externalTrafficPolicy=local accept packets to NodePort Service with externalTrafficPolicy=local

 

IPVS Proxy 모드 구성 정보 

kube-proxy 컨피그맵의 모드를 ipvs로 변경합니다. scheduler에 아무값도 설정되어 있지 않으면 기본 라운드 로빈 방식을 사용합니다. 그리고 MetalLB의 동작을 위해서 "stricARP:true"로 설정합니다. "stricARP:true"는 ARP 패킷을 보다 엄격하게 처리한다는 의미입니다. IPVS 모드에서 strict ARP가 활성화되면, 노드의 인터페이스는 자신에게 할당된 IP 주소에 대해서만 ARP 응답을 보내게 됩니다. 이는 IPVS로 로드밸런싱할 때 ARP 패킷이 잘못된 인터페이스로 전달되는 문제를 방지합니다. 이 설정은 특히 클러스터 내에서 여러 노드가 동일한 IP를 가지는 VIP(Virtual IP)를 사용하는 경우 중요합니다. 

 

IPVS 프록시 모드로 구성하면 모든 노드에 kube-ipvs0 dummy 인터페이스가 생성됩니다. 

Primary IP와 Secondary IP를 가지고, 모든 노드의 인터페이스 정보가 동일합니다. 

 

해당 IP 주소는 API Service와 CoreDNS Service의 CLUSTER-IP 입니다. 

즉, 앞으로 서비스를 생성할 때 kube-ipvs0 인터페이스에 정보가 추가될 것임을 예상할 수 있습니다. 

 

IPVS에 의한 분산 테이블 정보는 하기 명령어로 확인할 수 있습니다. 

$ ipvsadm -Ln

 

 

ClusterIP 서비스 구성 및 확인 

테스트용 파드 및 ClusterIP 타입 서비스를 생성하고 구성정보를 확인합니다. 

 

예상한 바와 같이, kube-ipvs0 인터페이스에 svc-clusterip에 대한 CLUSTER-IP 정보가 추가된 모습입니다. 

 

모든 노드에서 동일한 IPVS 분산 테이블 정보를 확인할 수 있습니다. 목적지는 서비스에 연결된 목적지 파드 3개이며 라운드 로빈(rr) 방식이 적용됩니다. 패킷은 Soure.IP가 마스커레이딩 변환되어 전달됩니다. 그 외에도 분산 테이블에서 트래픽 가중치(weight), In/Out 패킷 수와 처리 속도 정보를 확인할 수 있습니다.  

 

실제로 라운드 로빈 분산이 되는지 부하 테스트를 수행합니다. 

100번의 반복 접속을 시도하였을 때, 부하가 33.3% 비율로 고루 분산됩니다. 

 

분산 테이블의 상단은 패킷의 수와 처리량을 보여주며, 하단은 패킷 처리 속도를 보여줍니다. 

참고로 부하를 중단하면 하단 테이블의 패킷 처리 속도는 모두 0으로 리셋됩니다. 

 

마지막으로 IPTables 규칙을 확인합니다. IPSET(KUBE-CLUSTER-IP)을 사용하여 IPTables의 규칙 수는 단 2개입니다. 

만일 IPSET을 구성하지 않는다면 IPTables의 규칙 수는 10개(2*5)로 늘어나게 됩니다. kube-proxy는 IPTables를 위에서부터 차례대로 조회하므로 IPSET을 사용하여 규칙 수를 줄인다면 그만큼 네트워크 성능을 향상시킬 수 있습니다. 

 

 


[출처] 

1) CloudNet@, KANS 실습 스터디 

2) https://kubernetes.io/blog/2018/07/09/ipvs-based-in-cluster-load-balancing-deep-dive/

 

IPVS-Based In-Cluster Load Balancing Deep Dive

Editor’s note: this post is part of a series of in-depth articles on what’s new in Kubernetes 1.11 Introduction Per the Kubernetes 1.11 release blog post , we announced that IPVS-Based In-Cluster Service Load Balancing graduates to General Availability

kubernetes.io

728x90

'K8s > Advanced Network' 카테고리의 다른 글

[KANS3] 7. Service Mesh: Istio  (0) 2024.10.20
[KANS3] 6. Ingress + Gateway API  (0) 2024.10.13
[KANS3] 4. Service ClusterIP + NodePort  (3) 2024.09.29
[KANS3] 3. Calico CNI + Mode  (0) 2024.09.22
[KANS3] 2. Pause 컨테이너 + Flannel CNI  (4) 2024.09.08