Container Orchestration/Kubernetes

MetalLB란?

Somaz 2023. 5. 3. 20:51
728x90
반응형

Overview

오늘은 Bare-Metal에서 많이 사용하는 LoadBalancer인 MetalLB에 대해서 공부해보려고 한다.

https://devops.cisel.ch/deploy-metallb-as-an-on-prem-load-balancer-for-your-kubernetes-services


MetalLB란?

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

MetalLB는 MetalLB는 BareMetalLoadBalancer 약자로 베어메탈 환경에서 사용할 수 있는 로드 벨런서를 제공하는 오픈소스 프로젝트이다. 클라우드 환경의 서비스(로드밸런서 타입)와는 동작이 조금 다르다.
 
서비스(로드 밸런서)의 External IP 전파를 위해서 표준 프로토콜인 ARP(IPv4)/NDP(IPv6), BGP 를 사용한다
데몬셋으로 speaker 파드를 생성하여 External IP 전파한다.
 

https://mlops-for-all.github.io/docs/appendix/metallb/


MetalLB Mode

 


 

Layer 2 Mode

출처 : Cloudnet@ 스터디

 
서비스(로드밸런서) '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

출처 : Cloudnet@ 스터디

 
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

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

728x90
반응형