베어메탈 쿠버네티스 환경에서도 별도의 하드웨어 장비 없이 로드밸런서 타입의 서비스를 할 수 있도록 고안된 오픈소스 프로젝트이다. 퍼블릭 클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출시킬 수 있지만 온프레미스 환경에서의 제약사항을 해결해 준다.

 

LoadBalancer란?

특정 서버(또는 프로세스)에 가해지는 트래픽을 여러 대의 서버에 분산 시켜주는 장치(또는 프로그램)으로 솔루션에 따라 여러 분산 알고리즘을 제공한다.

 

MetalLB 프로젝트

2021년 CNCF의 Orchestration & Management, Service Proxy 항목으로 인정된 프로젝트로 구조가 복잡하지 않으며 사용이 편리하다. 온프레미스 쿠버네티스 운영자가 원하는 기능을 명확히 구현해준다.

 

요구사항

  • Kubernetes 1.13.0 이상의 클러스터
  • Antrea, Canal, Cilium, Flannel, Kube-ovn CNI에서는 완벽히 사용가능 하며 Calico, Kube-router, Weave Net CNI 사용 시 사용시 일부 안정성 이슈 있다.
  • MetalLB에 할당 할 수 있는 IPv4 주소 필요
  • BGP 모드를 사용 할 경우, 하나 이상의 BGP 지원 라우터 필요
  • L2 모드를 사용할 경우, 하시코프의 memberlist* 요구사항 대로 노드 간 TCP&UDP 7946 포트를 오픈

*https://github.com/hashicorp/memberlist

 

기능

주소 할당

클라우드 제공자의 쿠버네티스 클러스터에서 로드 밸런서를 요청하면 클라우드 플랫폼이 IP 주소를 할당한다. MetlLB는 외부에서 IP 주소를 생성할 수 없으므로 사용할 수 있는 IP 주소 풀을 사용자가 제공해야 한다.

 

외부 발표

MetalLB가 서비스에 외부 IP주소를 할당한 후에는 클러스터 외부의 네트워크에서 해당 IP가 클러스터에 존재한다는 것을 인식하도록 해야한다. MetalLB는 사용되는 모드(ARP, NDP 또는 BGP)에 따라서 표준 네트워킹 또는 라우팅 프로토콜을 사용하여 외부 네트워크에 IP를 노출시킨다.

  • Layer 2 Mode (ARP/NDP)
    • Layer 2(데이터 링크) 모드에서는 클러스터의 한 시스템이 서비스의 소유권을 갖고 표준 주소 검색 프로토콜(IPv4일 경우는 ARP, IPv6일 경우 NDP)으로 해당 IP를 로컬 네트워크에서 연결 할 수 있도록 합니다.
  • BGP
    • BGP 모드에서 클러스터의 모든 노드는 BGP 사용자가 제어하는 근처 라우터와 피어링 세션을 만들고 해당 라우터에 트래픽을 서비스 IP로 전달하는 방법을 알려줍니다.
    • BGP를 사용하면 여러 노드에 걸친 로드 밸런싱과 BGP 정책 메커니즘 덕분에 세분화된 트래픽 제어가 가능합니다.

 

 

설치 및 사용

준비 사항

kube-proxy IPVS 모드를 사용하는 경우 StrictARP 모드를 활성화 한다.

root@k8s-master01:~# kubectl -n kube-system edit cm kube-proxy
[strictARP: true]로 변경

 

설치

root@k8s-master01:~# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/addresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
serviceaccount/controller created
serviceaccount/speaker created
role.rbac.authorization.k8s.io/controller created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/controller created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
secret/webhook-server-cert created
service/webhook-service created
deployment.apps/controller created
daemonset.apps/speaker created
validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created

 

설치 확인

root@k8s-master01:~# kubectl -n metallb-system get all
NAME                              READY   STATUS    RESTARTS   AGE
pod/controller-6c58495cbb-2l6dd   1/1     Running   0          13m
pod/speaker-gr4l9                 1/1     Running   0          13m
pod/speaker-mfqkn                 1/1     Running   0          13m
pod/speaker-nlddv                 1/1     Running   0          13m
pod/speaker-p69vf                 1/1     Running   0          13m
pod/speaker-sdk67                 1/1     Running   0          13m
pod/speaker-zwnht                 1/1     Running   0          13m

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/webhook-service   ClusterIP   10.233.13.253   <none>        443/TCP   13m

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/speaker   6         6         6       6            6           kubernetes.io/os=linux   13m

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/controller   1/1     1            1           13m

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/controller-6c58495cbb   1         1         1       13m

 

IP Address Pool 생성

root@k8s-master01:~# vi metallb_ip_pool.yaml
---
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.110.118-192.168.110.119
kubectl apply -f metallb_ip_pool.aml

 

Deployment & Service 생성

root@k8s-master01:~# vi nginx.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 8088
      targetPort: 80
root@k8s-master01:~# kubectl apply -f nginx.yaml

 

EXTERNAL-IP 확인 및 호출

root@k8s-master01:~# kubectl get svc
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)          AGE
nginx-service   LoadBalancer   10.233.24.150   192.168.110.118   8088:30950/TCP   13m


root@k8s-master01:~# curl 192.168.110.118:8088
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 

 

기타

이전 버전에서는 IP Address를 configmap으로 설정했는데, CR(Custom Resource) - IPAddressPool 에서 설정 하는 것으로 변경되었다.

 

 

참고)

https://metallb.universe.tf/installation/clouds/

'Kubernetes' 카테고리의 다른 글

OS 옵션 변경  (0) 2022.12.26
[kubespray] 1.22 -> 1.23 Upgrade: Calico Error  (0) 2022.12.01
[K8s] grafana Alerm list  (0) 2022.10.24
[rook-ceph] 스토리지 배포  (0) 2022.10.18
OS 점검 자동화(비공개)  (0) 2022.08.23

+ Recent posts