K8s 에서 외부 로드밸런서 구성하기

Dierslair·2022년 6월 1일
3

kubernetes

목록 보기
4/5
post-custom-banner

지난번 포스팅에서는 마스터 노드가 로드밸런서 역할을 하게끔 구성했는데 트래픽이 늘어남에 따라 마스터 노드가 사용할 리소스가 줄어드는 것은 좋지 않다고 생각하여 외부 로드밸런서를 구성해 보기로 했습니다.

  • 시도하려는 클러스터 구조는 아래와 같습니다.

서버 구성도

워커 노드를 생성하는 절차를 그대로 따라서 로드밸런서 노드를 생성합니다. 레이블은 노드 이름은 k8s-loadbalancer , 레이블은 type=lb 로 주도록 하겠습니다.

BaremetalIngress Controller 설치하기

  • 사용 가능한 컨트롤러 목록에서 사용하려는 서버 인스턴스 유형에 따라 컨트롤러를 선택할 수 있습니다. 저는 어느 서비스에도 해당하지 않기 때문에 baremetal 용 컨트롤러를 설치하겠습니다.
$ curl -L -o ingress-nginx-controller.yml \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/baremetal/deploy.yaml
  • controller , admission-create , admission-patch 세 파드는 k8s-loadbalancer 노드에서 동작하도록 nodeAffinity 를 추가해 줍니다.
# ingress-nginx-controller.yml
...
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: type
                operator: In
                values:
                  - lb
$ kubectl apply -f ingress-nginx-controller.yml
$ kubectl get pods -n ingress-nginx -o wide
===
NAME                                        READY   STATUS      RESTARTS   AGE   IP            NODE               NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-6b4r2        0/1     Completed   0          26m   10.244.4.34   k8s-loadbalancer   <none>           <none>
ingress-nginx-admission-patch-rbqhs         0/1     Completed   0          26m   10.244.4.35   k8s-loadbalancer   <none>           <none>
ingress-nginx-controller-7b5876f785-56789   1/1     Running     0          26m   10.244.4.36   k8s-loadbalancer   <none>           <none>
  • 베어메탈용 컨트롤러는 NodePort 로 동작합니다. 이 상태에서 외부 트래픽은 컨트롤러로 바로 접근할 수 없어 LoadBalancer 타입으로 변경해 주어야 합니다.
$ kubectl patch svc ingress-nginx-controller -n \
ingress-nginx -p '{"spec": {"type": "LoadBalancer"}}'

$ kubectl get svc -n ingress-nginx
===
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.96.161.225    <pending>     80:30723/TCP,443:32540/TCP   1m
ingress-nginx-controller-admission   ClusterIP      10.107.233.129   <none>        443/TCP                      1m
  • LoadBalancer 타입으로 변경되었지만, EXTERNAL-IP<pending> 상태로 할당되고 있지 않아 외부 접근은 여전히 불가능합니다. MetalLB 를 설치하면 외부에서 접근할 수 있으니 진행해 보겠습니다.

MetalLB 설치하기

  • 설치 가이드 를 참고하면, 설치 전 쿠버네티스 설정을 수정해야 합니다.
$ kubectl edit configmap -n kube-system kube-proxy
===
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true
  • modeipvs 로, ipvs.strictARPtrue 로 변경해야 하는군요.
    다음은 manifest 를 설치하면 되는데 노드 어피니티 설정을 위해 일단 다운로드 후 설치하겠습니다.
$ curl -L -o namespace.yml https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml

$ curl -L -o metallb.yml https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

$ vi metallb.yml
  • deployment/controllerdaemonset/speaker 에 노드 어피니티를 추가해 준 후 설치를 진행합니다.
$ kubectl apply -f namespace.yml
$ kubectl apply -f metallb.yml
  • speaker 간 통신시 암호화를 위해 secret 이 필요합니다.
$ kubectl create secret generic -n metallb-system \
memberlist --from-literal=secretKey="$(openssl rand -base64 128)"
  • configmap.yml 이 필요합니다.
# configmap.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - [HOST_IP]
  • HOST_IP 에는 현재 노드(마스터)의 ipv4 주소를 입력합니다. ifconfig 명령어 혹은 AWS 콘솔 등에서 확인하면 됩니다.
$ ifconfig
===
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
 inet 192.168.51.14  ...
  • ipv4가 192.168.51.14 이니, HOST_IP 에는 192.168.51.14-192.168.51.14 로 지정해 주겠습니다.
$ kubectl apply -f configmap.yml
  • 조금 기다린 후, 인그레스 컨트롤러의 EXTERNAL-IP 가 할당되는 것을 볼 수 있습니다.
    백엔드단의 애플리케이션을 외부 80 포트로 노출해 보겠습니다.
# ingress-nginx.yml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-router
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: [YOUR_DOMAIN]
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: application
                port:
                  number: 8080
$ kubectl apply -f ingress-nginx.yml

외부에서 접근시 애플리케이션의 반환값을 표시하는 것을 알 수 있습니다.

profile
Java/Kotlin Backend Developer
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 8월 17일

혹시 [MetalLB 설치하기] 과정에서 deployment/controller 및 daemonset/speaker 에 노드 어피니티를 추가하는 이유를 알 수 있을까요?
controller는 몰라도 speaker는 다른 노드에 배포되어야 하는게 아닌가 싶어서요..

답글 달기