해당 내용은 책 <컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커>에 나오는 내용이며 이는 개인적으로 공부하기 위해서 게시하는 글임을 알립니다.
커피 중독자되는 중…
온프레미스에서 로드밸런서를 제공하는 MetalLB
노드포트는 굉장히 심플하다. 현실적으로 노드포트가 서비스하는 방식은 굉장히 효율이 떨어진다. 아래 사진을 참고해보자.
-
사용자가 워크 노드에 있는 포트에 먼저 접속을 한다. (순서도 1번 참고)
-
접속을 한 이후에 해당 워크 노드가 서비스로 이를 바인딩 해준다 (순서도 2번 참고)
-
서비스가 현재 있는 상태를 봐 가면서 노드에 연결을 해주게 된다.(순서도 3번 참고)
즉 비효율적으로 사용자가 서비스에 접근해서 서비스가 바로 파드에 접근하는 게 아니라 사용자가 워크 노드 포트에 꼭 접속을 해서 이를 서비스로 보내준 다음에 서비스가 파드에 보내주는 구조이기 때문에 효율성이 떨어진다. 그리고 다른 문제는 워크 노드가 죽었다면 접속해야 되는 사용자에 있는 IP가 변경이 된다 그렇다면 이것은 대표 IP라는 컨셉이 떨어지기 때문에 사용자가 IP를 알아야된다. 이부분은 사실 제대로 서비스를 하기에는 부족한 부분이 있다. 그래서 프로덕션에서는 노드포트를 이용해서 서비스를 하진 않고 테스트용으로 노드포트를 사용한다.
그래서 쿠버네티스에서는 로드 밸런서(LoadBalancer)라는 서비스 타입을 제공해 간단한 구조로 파드를 외부에 노출하고 부하를 분산한다. 아래 사진을 참고하여 위의 사진과 구조를 비교해보자.
노드포트의 구조와 비교해봤을 때 매우 단순하다. 이는 클라우드 환경에서 동작하는 방식이다. 사용자가 클라우드 노드밸러스 타입에 접근한지는 모른다 즉 보여지지 않지만 거기에 접근해서 바로 Load Balancer 서비스의 External IP(그림의 노란색 부분)에 접근한 이후에 바로 내부에 있는 파드로 연결해주게 된다. 굉장히 간결하게 동작을 한다.
온프레미스에서 로드밸러서를 사용하려면 로드밸러서를 이미 구현해 둔 서비스업체의 도움을 받아 쿠버네티스 클러스터 외부에 구현해야 한다.
온프레미스에서 로드밸런서를 사용하려면 내부에 로드밸런서 서비스를 받아주는 구성이 필요한데, 이를 지원하는 것이 MetalLB이다. MetalLB는 베어메탈(bare metal, 운영체제가 설치되지 않은 하드웨어)로 구성된 쿠버네티스에서도 로드밸런서를 사용할 수 있게 고안된 프로젝트이다. MetalLB는 특별한 네트워크 설정이나 구성이 있는 것이 아니라 기존의 L2 네트워크(ARP/NDP)와 L3 네트워크(BGP)로 로드밸런서를 구현한다. 그러므로 네트워크를 새로 배워야 할 부담이 없으며 연동하기도 매우 쉽다.
온프레미스 환경의 로드밸런서의 구조를 아래 사진으로 본다.
MetalLB 서비스는 위와 같이 동작하는데 기존의 봤던 클라우드 로드 밸런스와 굉장히 유사하다. 사용자가 서비스에 접근을 해서(순서도 1번) 서비스가 파드에 그대로 포워딩(순서도 2번)해주는 구조이다. 점선으로 표시한 부분은 MetalLB 컨트롤러와 MetalLB 스피커에서 자동으로 관리해주는 부분이다. 이것들이 자동으로 관리해줘서 로드 밸런스의 서비스가 파드에 접속할 수 있게 되는 것이다.
아래 사진은 특정 레이어에 따른 로드밸런싱을 하는 방법 들이다.
이 책에서는 MetalLB의 L2 네트워크로 로드밸런서를 구현한다.
MetalLB 컨트롤러는 작동 방식(Protocol, 프로토콜)을 정의하고 EXTERNAL-IP를 부여해 관리한다. MetalLB 스피커(speaker)는 정해진 작동 방식(L2/ARP, L3/BGP)에 따라 경로를 만들 수 있도록 네트워크 정보를 광고하고 수집해 각 파드의 경로를 제공한다. 이때 L2는 스피커 중에서 리더를 선출해 경로 제공을 총괄한다.
- 디플로이먼트를 이용해 2종류(lb-hname-pods, lb-ip-pods)의 파드를 생성한다. 그리고 scale 명령으로 파드를 3개로 늘려 노드당 1개씩 파드가 배포되게 한다.
kubectl create deployment lb-hname-pods --image=sysnet4admin/echo-hname
kubectl scale deployment lb-hname-pods --replicas=3
kubectl create deployment lb-ip-pods --image=sysnet4admin/echo-ip
kubectl scale deloyment lb-ip-pods --replicas=3
- 2종류의 파드가 3개씩 총 6개가 배포됐는지 확인한다.
kubectl get pods
- 인그레스와 마찬가지로 사전에 정의된 오브젝트 스펙으로 MetalLB를 구성한다. 이렇게 하면 MetalLB에 필요한 요소가 모두 설치되고 독립적인 네임스페이스(metallb-system)도 함께 만들어진다.
kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.4/metallb.yaml
- 배포된 MetalLB의 파드가 5개(controller 1개, speaker 4개)인지 확인하고, IP와 상태도 확인한다. 스피커는 각 노드마다 설치가 된다. 컨트롤러 같은 경우는 한 개가 설치되는데 여기 있는 기능들을 관리해주는 기능을 한다. 즉 MetalLB와 관련된 파드들을 deploy했다. 이제 여기에 MetalLB가 L2 통신을 할 수 있도록 거기에 있는 IP라던가 세팅 값을 넣어주는 것들을 배포하도록 하겠다.
kubectl get pods -n metallb-system -o wide
- 인그레스와 마찬가지로 MetalLB도 설정을 적용해야 하는데, 다음 방법으로 적용한다. 이때 오브젝트는 ConfigMap을 사용한다. ConfigMap은 설정이 정의된 포맷이라고 생각하면 된다.
파일의 구성을 보자
metallb-l2config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: nginx-ip-range
protocol: layer2
addresses:
- 192.168.1.11-192.168.1.13
하나 하나 살펴보자
metallb-l2config.yaml
#apiVersion: API 버전을 명시한다
#이 오브젝트를 생성하기 위해 사용하고 있는 쿠버네티스 API 버전이 어떤 것인지
#명시한다.
apiVersion: v1
#어떤 종류의 오브젝트를 생성하고자 하는지 명시한다.
kind: ConfigMap
#이름 문자열, UID, 그리고 선택적인 네임스페이스를 포함하여
#오브젝트를 유일하게 구분지어 줄 데이터이다.
#서비스 이름(name)은 config이다.
metadata:
#ConfigMap이 위치하는 네임스페이스를
#metallb-system로 한다.
namespace: metallb-system
name: config
data:
config: |
#metallb의 세부 설정
address-pools:
- name: nginx-ip-range
#metallb에서 제공하는 로드밸런서의 동작 방식이다. 즉 L2 방식이다.
protocol: layer2
#metallb에서 제공하는 로드밸러서의 External 주소이다.
#이 범위 안에서 External 주소를 부여한다.
addresses:
- 192.168.1.11-192.168.1.13
- ConfigMap이 생성됐는지 kubectl get configmap -n metallb-system 명령으로 확인한다.
kubectl get configmap -n metallb-system
- -o yaml 옵션을 주고 다시 실행해 MetalLB의 설정이 올바르게 적용됐는지 확인한다.
kubectl get configmap -n metallb-system -o yaml
- 모든 설정이 완료됐으니 이제 각 디플로이먼트(lb-hname-pods, lb-ip-pods)를 로드밸런서 서비스로 노출한다.
kubectl expose deployment lb-hname-pods --type=LoadBalancer --name=lb-hname-svc --port=80
kubectl expose deployment lb-ip-pods --type=LoadBalancer --name=lb-ip-svc --port=80
- 생성된 로드밸런서 서비스별로 CLUSTER-IP와 EXTERNAL-IP가 잘 적용됐는지 확인한다. 특히 EXTERNAL-IP에 ConfigMap을 통해 부여한 IP를 확인한다. 외부와 통신할 수 있는 EXTERNAL-IP가 부여된 것을 볼 수 있다.
kubectl get services
- EXTERNAL-IP가 잘 작동하는지도 확인해 본다. 호스트 노트북(또는 PC)에서 브라우저를 띄우고 192.168.1.11로 접속한다. 배포된 파드 중 하나의 이름이 브라우저에 표시되는지 확인한다.
- 192.168.1.12를 접속해 파드에 요청 방법과 IP가 표시되는지 확인한다.
삭제 작업
kubectl delete deployment lb-hname-pods
kubectl delete deployment lb-ip-pods
kubectl delete service lb-hname-svc
kubectl delete service lb-ip-svc
기존의 노드포트에서 사용했을 때 인터넷 브라우저로 접근하려면 ip와 노드포트를 적어줘야 했었는데 만약에 해당 노드가 죽게 된다면 이 ip로 접근을 할 수 없었다. 그래서 실질적으로 expose하는 의미가 떨어지게 되는데 metallb를 사용하면 모든 노드에 걸쳐서 데몬셋이 생성이 되고 그 데몬셋이 리턴을 해주기 때문에 EXTERNAL IP 하나로 전체에 있는 클러스터의 대표 IP, 즉 VIP 성격으로 쓸 수 있는 것이다.
또 이런 생각을 해볼 수 있다.
VIP, 즉 지금 EXTERNAl 되는 IP가 192.168.11-192.168.1.13까지 있었는데 만약 추가로 요구사항이 있어서 VIP를 추가로 생성하는 부분에 대해서는 어떻게 할까? 이것은 걱정할 필요는 없다. 우리가 추가로 서비스를 expose하면 된다. 만약에 VIP를 새로 생성한다는 의미는 다른 종류의 deployment를 붙인다는 것이 된다. 아래 사진과 같이 새로 생성한 디플로이먼트를 expose한 경우에 우리가 잡아놓은 IP range에서 부여되는 것을 볼 수 있다.