연재 시리즈

쿠버네티스 네트워크 스터디 5주차 - MetalLB L2모드 동작원리 이해

악분 2022. 2. 17. 21:49
반응형

스터디 목차

 

안녕하세요. 이 글은 facebook 쿠버네티스 그룹에서 올라온 "쿠버네티스 네트워크 스터디" 5주차 내용을 정리했습니다.

스터디 모집글: https://www.facebook.com/groups/k8skr/posts/3202691746679143

 

1. 5주차 세번째 주제

5주차 세번째 주제는 MetalLB L2모드 동작이해입니다.

 

2. MetalLB등장 배경

MetalLB는 로드밸런서(LoadBalancer)서비스 타입과 관계가 있는 솔루션입니다.

 

로드밸런서 서비스 타입은 공식문서(https://kubernetes.io/ko/docs/concepts/services-networking/service/#publishing-services-service-types)에서 소개되어 있는 것 처럼, 클라우드에서 제공하는 외부 로드밸런서가 필요합니다.

 

클라우드가 아닌 일반 환경에서 로드밸런서를 사용할 수 없습니다. 네트워크 구성에 문제는 없지만 서비스 운영에 불편한점이 있는데요!

가장 큰 불편한점은 ingress controller 접속 방법입니다. ingress controller은 서비스 타입이 로드밸런서를 사용하지 않으면 <노드IP>:<nodeport>로 접근해야 합니다. 마치 google.com을 접속하기 위해 google.com:32000 을 입력하는 것처럼요

google.com:<nodeport>

 

3. MetalLB

클라우드가 아닌 환경에서 LoadBalancer를 사용하기 위한 여러가지 솔루션이 등장했습니다. 많이 알려진 솔루션 중 무료로 사용할 수 있는 오픈소스가 바로 MetalLB입니다.

 

MetalLB는 2가지 모드를 지원합니다. 이 글에서는 L2모드를 설명합니다.

  • L2
  • BGP

 

4. L2 모드

4.1 동작원리

L2모드는 2계층 통신을 이용합니다.

 

각 노드마다 speaker라는 데몬셋이 생성됩니다. speaker데몬셋이 생성한 pod가 로드밸런서 ExternalIP를 2가지 방법으로 관리합니다.

① 리더 sepaker pod를 선출

② GARP프로토콜을 이용하여 speaker pod를 실행하는 노드로 ExternalIP 패킷이 오도록 설정

 

 

리더 speaker pod이 실행하는 노드로 패킷이 오면, 해당 노드에서 iptables규칙에 따라서 분산되어 패킷이 pod로 전달됩니다. 노드까지 패킷이 도착하면 이후 과정은 nodeport동작과 비슷합니다. NodePort SNAT이 적용되어 출발지(클라이언트)IP가 sepaker pod로 전달된 노드IP로 변경됩니다.

출처: 스터디 공유자료

 

4.2 speaker pod IP

speaker pod의 네트워크 네임스페이스는 host모드로 동작하여 pod IP는 노드 IP를 갖습니다. 

 

4.3 external IP를 관리하는 spaker pod탐색

arpping을 이용하여 어떤 speaker pod가 external IP를 관리하는지 찾을 수 있습니다.

아래 예제는 arpping을 이용하여 nginx ingress controller 서비스를 담당하는 speaker pod를 찾았습니다. 192.168.0.66는 worker2번 노드입니다.

 

5. L2모드 단점

첫 번째 단점은, 특정 노드에 부하가 발생할 수 있습니다.  특정 external IP에 짧은 시간에 많은 트래픽이 발생하면 external IP가 관리하는 노드에 트래픽이 전달됩니다.

두 번째 단점은 speaker 리더 pod가 알수없는 이유로 죽는다면 일시적인 네트워크 장애가 발생합니다. 새로운 리더를 선출하기 위해 잠시 장애가 발생했던 external IP로 일시적으로 통신되지 않습니다.

 

6. 실습

6.1 실습환경

스터디에 공유한 vagrantfile을 활용하여 실습환경을 구축했습니다.

출처: 스터디 공유자료

 

6.2 MetalLB설치

설치과정은 2단계로 진행됩니다.

 

① 공식문서(https://metallb.universe.tf/installation/)에 있는 yaml파일을 설치합니다.

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

 

② metalLB가 관리하는 externalIP주소를 설정합니다.

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.10.200-192.168.10.210

 

MetalbLB리소스는 metallb-system 네임스페이스에 설치됩니다.

 kubectl get all -n metallb-system

 

6.3 pod와 로드밸런서 타입 서비스 생성

출발지 IP와 도착지 IP를 출력하는 도커 이미지를 사용하여 pod3개를 생성했습니다. 그리고 각 pod에 해당하는 로드밸런서타입 서비스를 생성했습니다.

apiVersion: v1
kind: Pod
metadata:
  name: webpod1
  labels:
    app: webpod1
spec:
  containers:
  - name: container
    image: traefik/whoami
    ports:
      - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc1
spec:
  ports:
    - name: svc1-webport
      port: 80
      targetPort: 80
  selector:
    app: webpod1
  type: LoadBalancer
---
apiVersion: v1
kind: Pod
metadata:
  name: webpod2
  labels:
    app: webpod2
spec:
  containers:
  - name: container
    image: traefik/whoami
    ports:
      - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc2
spec:
  ports:
    - name: svc2-webport
      port: 80
      targetPort: 80
  selector:
    app: webpod2
  type: LoadBalancer
---
apiVersion: v1
kind: Pod
metadata:
  name: webpod3
  labels:
    app: webpod3
spec:
  containers:
  - name: container
    image: traefik/whoami
    ports:
      - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc3
spec:
  ports:
    - name: svc3-webport
      port: 80
      targetPort: 80
  selector:
    app: webpod3
  type: LoadBalancer

 

서비스를 조회하면 로드밸런서타입 서비스 3개가 보입니다.

kubectl get svc

 

로드밸런서 IP를 한개 선택하여 http GET요청을 하면 통신이 잘되는 것을 확인할 수 있습니다.

 

 

6.4 클러스터 외부에서 로드밸런서IP 호출

클러스터 외부에 있는 k8s-pc에서 webpod1 로드밸런서 IP인 192.168.10.200을 호출할 겁니다. k8s-pc는 enp0s8인터페이스를 사용합니다.

출처: 스터디 공유자료

 

응답을 보면 출발지 IP가 k8s-pc가 아닙니다. 192.1689.10.200을 관리하는 speaker leader pod가 controlaplane노드에 있어서, 출발지 IP가 controlplane 노드에 있는 calico 네트워크 인터페이스로 변경되었습니다.

# webpod1에 HTTP GET을 요청하는 명령어
curl --interface enp0s8 -s 192.168.10.200 | egrep 'Hostname|RemoteAddr|Host:'

출처: 스터디공유자료

반응형