Overview
오늘은 Bare-Metal에서 많이 사용하는 LoadBalancer인 MetalLB에 대해서 공부해보려고 한다.
MetalLB란?
Kubernetes 사용 시 AWS, GCP, Azure 와 같은 클라우드 플랫폼에서는 자체적으로 로드 벨런서(Load Balancer)를 제공해 주지만, 온프레미스 클러스터에서는 로드 벨런싱 기능을 제공하는 모듈을 추가적으로 설치해야 한다.
MetalLB는 MetalLB는 BareMetalLoadBalancer 약자로 베어메탈 환경에서 사용할 수 있는 로드 벨런서를 제공하는 오픈소스 프로젝트이다. 클라우드 환경의 서비스(로드밸런서 타입)와는 동작이 조금 다르다.
서비스(로드 밸런서)의 External IP 전파를 위해서 표준 프로토콜인 ARP(IPv4)/NDP(IPv6), BGP 를 사용한다
데몬셋으로 speaker 파드를 생성하여 External IP 전파한다.
MetalLB Mode
Layer 2 Mode
서비스(로드밸런서) 'External IP' 생성 시 speaker 파드 중 1개가 리더가 되고, 리더 speaker 파드가 존재하는 노드로 서비스 접속 트래픽이 인입되게 된다
- 데몬셋으로 배포된 speaker 파드는 호스트 네트워크를 사용한다 ⇒ "NetworkMode": "host"
리더는 ARP(GARP, Gratuitous APR)로 해당 'External IP' 에 대해서 자신이 소유라며 동일 네트워크에 전파를 한다
만약 리더(노드)가 장애 발생 시 자동으로 나머지 speaker 파드 중 1개가 리더가 된다.
- 멤버 리스터 및 장애 발견은 hashicorp 의 memberlist 를 사용 - Gossip based membership and failure detection
Layer 2에서 멤버 발견 및 자동 절체에 Keepalived(VRRP)도 있지만 사용하지 않은 이유는 아래 링크에 있다.
- 링크
BGP Mode
speaker 파드에 BGP 가 동작하여 서비스 정보(EXTERNAL-IP)를 전파한다
- 기본은 IP주소(32bit)를 전파하며, 설정으로 축약된 네트워크 정보를 전파할 수 있다 → bgp-advertisements 에 aggregation-length 설정
- BGP 커뮤니티, localpref 등 BGP 관련 설정을 할 수 있다
- IP 주소 마지막이 0 과 255 를 처리를 못하는 라우터 장비가 있을 경우 avoid-buggy-ips: true 옵션으로 할당되지 않게 할 수 있다
외부 클라이언트에서 SVC(서비스, EXTERNAL-IP)로 접속이 가능하며, 라우터에서 ECMP 라우팅을 통해 부하 분산 접속 할 수 있다
- 일반적으로 ECMP 는 5-tuple(프로토콜, 출발지IP, 목적지IP, 출발지Port, 목적지Port) 기준으로 동작한다.
- 물론 라우터 장비에 따라 다양한 라우팅(분산) 처리가 가능하다
MetalLB 설치
설치 방법 지원 : Kubernetes manifests, using Kustomize, or using Helm
- 참고 : kube-proxy 의 ipvs 모드 사용 시 'strictARP: true' 설정 필요
- https://github.com/metallb/metallb
kubectl edit configmap -n kube-system kube-proxy
...
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
# or
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
# 재시작
k rollout restart -n kube-system daemonset kube-proxy
Install With Helm
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb -n metallb-system --create-namespace
# example
helm install -n <네임스페이스> <릴리즈 이름> -f <브랜치별 helm values 파일명>.yaml metallb/metallb
# helm으로 설치할 때는 memberlist 필요없다. 자동으로 설치됨.
k get secret -n metallb-system
NAME TYPE DATA AGE
metallb-memberlist Opaque 1 2d
metallb-webhook-cert Opaque 4 2d
sh.helm.release.v1.metallb.v1 helm.sh/release.v1 1 2d
metallb config 설정한다.
# metallb config 설정
cat <<EOF >> metallb-config.yaml
# 사용 apiversion
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ip-pool
namespace: metallb-system
spec:
addresses:
# 사용할 ip address pool
- 143.92.123.123-143.92.123.123
autoAssign: true
---
apiVersion: metallb.io/v1beta1
# metalib의 l2모드를 사용한다.
kind: L2Advertisement
metadata:
name: l2-network
namespace: metallb-system
spec:
# 사용할 ipAddressPools
ipAddressPools:
- ip-pool
EOF
기존설정 삭제 후에 ipaddresspool 확인한다.
# 설정 확인
kubectl get validatingwebhookconfigurations
# 기존설정 삭제
kubectl delete validatingwebhookconfigurations metallb-webhook-configuration
# 삭제 확인 (no resource found가 나와야 한다.)
kubectl get validatingwebhookconfigurations
# 설정 적용
k apply -f metallb-config.yaml -n metallb-system
# 최종 확인
kubectl describe ipaddresspool.metallb.io --namespace metallb-system
# ipaddresspool 확인
Name: ip-pool
Namespace: metallb-system
Labels: <none>
Annotations: <none>
API Version: metallb.io/v1beta1
Kind: IPAddressPool
Metadata:
Creation Timestamp: 2024-05-29T08:10:22Z
Generation: 1
Managed Fields:
API Version: metallb.io/v1beta1
Fields Type: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.:
f:kubectl.kubernetes.io/last-applied-configuration:
f:spec:
.:
f:addresses:
f:autoAssign:
f:avoidBuggyIPs:
Manager: kubectl-client-side-apply
Operation: Update
Time: 2024-05-29T08:10:22Z
Resource Version: 742627
UID: 358e924f-c935-431c-a4a0-46788c4a1392
Spec:
Addresses:
ex. 192.168.10.10 - 192.168.10.20
Auto Assign: true
Avoid Buggy I Ps: false
Events: <none>
Install By Manifest
Manifest를 통해 설치한다.
다만 해당 파일의 native에는 모든 resource가 전부 다들어가있는 것 같다.
따라서 MetalLB의 github를 보고 필요한 리소스를 설치하는 것이 좋아보인다.
curl -O https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml
kubectl apply -f metallb-native.yaml -n metallb-system
# If you want to deploy MetalLB using the FRR mode, apply the manifests
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-frr.yaml
memberlist secret을 만들어서 스피커간의 통신을 암호화한다.
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" -o yaml > metallb-secret.yaml
cat metallb-secret.yaml
apiVersion: v1
data:
secretkey: bmRzd3hQSWZDUX...
kind: Secret
metadata:
creationTimestamp: null
name: memberlist
namespace: metallb-system
kubectl apply -f metallb-secret.yaml -n metallb-system
memberlist secret이 없으면 아래와 같이 Error가 발생한다.
{"branch":"HEAD","caller":"main.go:138","commit":"v0.10.2","goversion":"gc / go1.16.5 / arm","msg":"MetalLB controller starting version 0.10.2 (commit v0.10.2, branch HEAD)","ts":"2021-06-14T10:07:51.113257418Z","version":"0.10.2"}
{"caller":"main.go:173","error":"Get \"https://10.96.0.1:443/api/v1/namespaces/metallb-system/secrets?fieldSelector=metadata.name%3Dmemberlist\": dial tcp 10.96.0.1:443: i/o timeout","msg":"failed to create memberlist secret","op":"startup","ts":"2021-06-14T10:08:21.120420776Z"}
MetalLB 구성
metalLB는 configmap을 전달하기 전까지 유휴상태이다.
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: metallb-ip-range
protocol: layer2
addresses:
- <ip range start> - <ip range End>
ex. 192.168.10.10 - 192.168.10.20
ex. 10.10.100.26 - 10.10.100.26
- <ip range 대역대>
ex. 192.168.10.0/24
구성을 완료하면 아래와 같이 MetalLB pod가 정상적으로 Running된다
$ k get po -n metallb-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
controller-f54fbc6f9-pxgqv 1/1 Running 2 (97d ago) 365d 10.233.70.84 node5 <none> <none>
speaker-5xqc9 1/1 Running 2 (98d ago) 365d 10.10.100.24 node4 <none> <none>
speaker-cxzgx 1/1 Running 2 (97d ago) 365d 10.10.100.25 node5 <none> <none>
speaker-dn6mg 1/1 Running 1 365d 10.10.100.20 master0 <none> <none>
speaker-m2psn 1/1 Running 3 (97d ago) 365d 10.10.100.22 node2 <none> <none>
speaker-nhxms 1/1 Running 2 (97d ago) 365d 10.10.100.23 node3 <none> <none>
speaker-zt72w 1/1 Running 2 (97d ago) 365d 10.10.100.21 node1 <none> <none>
- MetalLB의 Speaker의 IP는 Node의 IP를 가지게 된다.
마지막으로 저는 MetalLB Service는 배포하지 않았습니다. 그 이유는 ingress-nginx-controller를 사용할 것이고 MetalLB는 LoadBalancer Type을 위한 설치이다.
마무리
다음시간에는 Ingress-Nginx에 대해 공부해보려고 합니다. 잘 설치가 된다면 아래와 같은 모습이 된다.
k get po,svc -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-patch-s6zwc 0/1 Completed 2 365d
pod/ingress-nginx-controller-75f58fbf6b-qph5z 1/1 Running 5 (97d ago) 365d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.233.10.100 10.10.100.26 80:31500/TCP,443:31158/TCP 365d
service/ingress-nginx-controller-admission ClusterIP 10.233.39.214 <none> 443/TCP 365d
- 10.10.100.26 이 MetalLB의 IP입니다. Config 파일에 작성해주는 IP요!
Reference
MetalLB 공식사이트
https://devops.cisel.ch/deploy-metallb-as-an-on-prem-load-balancer-for-your-kubernetes-services
https://mlops-for-all.github.io/docs/appendix/metallb/
https://mydevjourney.tistory.com/96
'Container Orchestration > Kubernetes' 카테고리의 다른 글
Kuberntes Service Account란? (0) | 2023.05.10 |
---|---|
Kubernetes Secret이란? (0) | 2023.05.09 |
Kubernetes Resources(쿠버네티스 리소스) (0) | 2023.05.02 |
Kubernetes 플러그인 매니저 Krew란? (0) | 2023.04.30 |
Kubernetes API Server, Group / RBAC란? (2) | 2023.04.19 |