MetalLB를 사용하여 번들 부하 분산 구성

이 페이지에서는 Google Distributed Cloud용 MetalLB로 번들 부하 분산을 구성하는 방법에 대해 설명합니다. MetalLB 부하 분산기는 워커 노드의 전용 풀 또는 제어 영역과 동일한 노드에서 실행됩니다.

Google Distributed Cloud에서 사용 가능한 부하 분산 토폴로지의 예시는 부하 분산기 개요를 참조하세요.

요구사항

  • 모든 부하 분산기 노드는 동일한 레이어 2 서브넷에 있어야 합니다.
  • 모든 VIP는 부하 분산기 노드 서브넷에 있어야 하며 서브넷의 게이트웨이를 통해 라우팅할 수 있어야 합니다.
  • 부하 분산기 서브넷의 게이트웨이는 Gratuitous ARP 메시지를 리슨하고 ARP 패킷을 부하 분산기 노드로 전달해야 합니다.

구성 필드

번들 부하 분산을 구성하려면 클러스터 구성 파일의 cluster.spec.loadBalancer 섹션을 수정합니다. 클러스터 구성 파일 및 올바른 구성의 예시에 대한 자세한 내용은 다음 페이지 중 하나를 참조하세요.

loadBalancer.mode

번들 부하 분산을 사용 설정하려면 이 값이 bundled여야 합니다.

loadBalancer.ports.controlPlaneLBPort

이 값은 Kubernetes 제어 영역(Kubernetes API 서버)에 전송되는 트래픽에 사용할 목적지 포트를 지정합니다.

loadBalancer.vips.controlPlaneVIP

이 값은 Kubernetes 제어 영역(Kubernetes API 서버)에 전송되는 트래픽에 사용할 대상 IP 주소를 지정합니다. 이 IP 주소는 클러스터의 노드와 동일한 Layer 2 서브넷에 있어야 합니다. 구성 파일의 address pools 섹션에 이 주소를 나열하지 마세요.

loadBalancer.vips.ingressVIP

이 값은 인그레스 트래픽의 부하 분산기를 기반으로 하는 서비스에 사용되는 IP 주소를 지정합니다. 이 필드는 관리자 클러스터 구성 파일에서 허용되지 않습니다. 이 주소는 구성의 주소 풀 섹션에 나열되어야 합니다.

loadBalancer.addressPools

이 구성 섹션에는 하나 이상의 주소 풀이 포함되어 있습니다. 각 주소 풀은 IP 주소 범위 목록을 지정합니다. LoadBalancer 유형의 서비스를 만들면 서비스의 외부 IP 주소가 이 범위에서 선택됩니다.

주소 풀은 다음 형식으로 지정됩니다.

- name: POOL_NAME
  avoidBuggyIPs: BOOLEAN
  manualAssign: BOOLEAN
  addresses:
  - IP_RANGE
  - IP_RANGE2
  • name: 조직의 자체적인 용도를 위한 주소 풀 이름(pool-name)입니다. 이 필드는 변경할 수 없습니다.
  • avoidBuggyIPs: (선택사항) true 또는 false. true이면 풀은 .0.255로 끝나는 IP 주소를 생략합니다. 일부 네트워크 하드웨어는 이 특수 주소에 대한 트래픽을 삭제합니다. 이 필드를 생략할 수 있으며 기본값은 false입니다. 이 필드를 변경할 수 있습니다.
  • manualAssign: (선택사항) true 또는 false. true이면 이 풀의 주소가 Kubernetes 서비스에 자동으로 할당되지 않습니다. true이면 이 풀의 IP 주소는 서비스에서 명시적으로 지정된 경우에만 사용됩니다. 이 필드를 생략할 수 있으며 기본값은 false입니다. 이 필드를 변경할 수 있습니다.
  • addresses 겹치지 않는 IP 주소 범위 하나 이상의 목록입니다. CIDR 표기법(예: 198.51.100.0/24) 또는 범위 표기법(예: 대시 앞뒤로 공백이 없이 198.51.100.0-198.51.100.10)을 사용하여 ip-range를 지정할 수 있습니다 이 필드는 변경할 수 없습니다.

addresses 목록의 IP 주소 범위는 겹치면 안 되며 부하 분산기를 실행하는 노드와 동일한 서브넷에 있어야 합니다.

loadBalancer.nodePoolSpec

구성의 이 섹션에서는 부하 분산기를 실행할 노드 목록을 지정합니다. 부하 분산기 노드는 기본적으로 일반 워크로드를 실행할 수 있습니다. 이러한 노드에는 특별한 taint가 없습니다. 부하 분산기 노드 풀의 노드는 워크로드를 실행할 수 있지만 워커 노드 풀의 노드와 별개입니다. 지정된 클러스터 노드를 2개 이상의 노드 풀에 포함할 수 없습니다. 노드 풀 간에 겹치는 노드 IP 주소는 클러스터 생성 및 기타 클러스터 작업을 차단합니다.

워크로드가 부하 분산기 노드 풀의 노드에서 실행되지 않도록 하려면 노드에 다음 taint를 추가합니다.

node-role.kubernetes.io/load-balancer:NoSchedule

Google Distributed Cloud는 부하 분산에 필요한 포드에 이 taint에 대한 톨러레이션(toleration)을 추가합니다.

다음 예시에서는 노드가 2개인 부하 분산 노드 풀을 보여줍니다. 첫 번째 노드에는 표준 IP 주소 nodePoolSpec.nodes.address('1.2.3.4') 및 Kubernetes IP 주소 nodePoolSpec.nodes.k8sIP(10.0.0.32)가 있습니다. 노드에 선택적인 k8sIP 주소를 지정하면 Kubernetes API, kubelet, 워크로드에 대한 요청 및 응답과 같은 노드의 데이터 트래픽만 처리됩니다. 이 경우 표준 IP 주소 nodePoolSpec.nodes.address는 관리 클러스터 작업을 위한 노드에 대한 SSH 연결에 사용됩니다. k8sIP 주소를 지정하지 않으면 표준 노드 IP 주소에서 노드의 모든 트래픽을 처리합니다.

nodePoolSpec:
  nodes:
  - address: 1.2.3.4
    k8sIP: 10.0.0.32
  - address: 10.0.0.33

기본적으로 부하 분산기 노드 풀의 모든 노드는 구성 파일의 loadBalancer.addressPools 섹션에서 구성된 부하 분산기 VIP와 동일한 레이어 2 서브넷에 있어야 합니다. 그러나 노드에 Kubernetes IP 주소 k8sIP를 지정하면 해당 주소만 다른 부하 분산기 VIP와 동일한 레이어 2 서브넷에 있어야 합니다.

nodePoolSpec이 설정되지 않으면 번들 부하 분산기는 제어 영역 노드에서 실행됩니다. 가능하면 별도의 노드 풀에서 부하 분산기를 실행하는 것이 좋습니다.

제어 영역 부하 분산

제어 영역 부하 분산기는 제어 영역 가상 IP 주소(VIP)를 제공합니다. Google Distributed Cloud는 부하 분산기 노드에서 Keepalived 및 HAProxy를 Kubernetes 정적 포드로 실행하여 제어 영역 VIP를 알립니다. Keepalived는 고가용성을 위해 부하 분산기 노드에서 가상 라우터 중복 프로토콜(VRRP)을 사용합니다.

데이터 영역 부하 분산

데이터 영역 부하 분산기는 LoadBalancer 유형의 모든 Kubernetes 서비스에 사용됩니다. Google Distributed Cloud는 데이터 영역 부하 분산에 Layer 2 모드에서 실행되는 MetalLB를 사용합니다. 데이터 영역 부하 분산은 Google Distributed Cloud를 통해서만 구성할 수 있으며 MetalLB ConfigMap을 직접 수정하지 마세요. 서비스 간 IP 주소 공유를 포함한 모든 MetalLB 기능을 사용할 수 있습니다. 기능 정보는 MetalLB 문서를 참조하세요.

MetalLB는 고가용성을 위해 memberlist를 사용하여 데몬셋을 사용하여 각 노드에서 스피커 포드를 실행합니다. 전체 클러스터용 하나가 아닌 각 Kubernetes 서비스마다 MetalLB 전용 부하 분산기 노드가 있습니다. 이렇게 하면 서비스가 여러 개 있는 경우 부하 분산기 노드에 트래픽이 분산됩니다.

데이터 영역 부하 분산기는 제어 영역 노드 또는 워커 노드의 하위 집합에서 실행될 수 있습니다. 제어 영역 노드의 데이터 영역 부하 분산기를 번들로 묶으면 제어 영역 노드의 사용률이 증가합니다. 그러나 컨트롤 플레인 과부하가 발생할 위험이 증가하고 컨트롤 플레인에서 SSH 키와 같은 기밀 정보의 위험 프로필이 증가합니다.

클라이언트 소스 IP 주소 유지

번들 Layer 2 부하 분산 솔루션으로 만든 LoadBalancer 서비스는 외부 트래픽 정책에 대한 기본 Cluster 설정을 사용합니다. spec.externalTrafficPolicy: Cluster 설정은 클러스터 차원의 엔드포인트로 외부 트래픽을 라우팅하지만 클라이언트 소스 IP 주소도 가립니다.

다음 섹션에서는 클라이언트 소스 IP 주소를 보존하도록 클러스터를 구성하는 방법을 설명합니다.

서비스 NodePort

Kubernetes는 NodePort 서비스에 대해 소스 네트워크 주소 변환(NAT)을 수행합니다. 클라이언트 소스 IP 주소를 유지하려면 service.spec.externalTrafficPolicyLocal로 설정합니다. Kubernetes가 더 이상 소스 SNAT를 수행하지 않지만 선택한 노드 IP에서 정확하게 실행되는 포드가 있는지 확인해야 합니다.

서비스 LoadBalancer

LoadBalancer 서비스에서 externalTrafficPolicy: Local을 사용하는 경우 부하 분산기 노드에서 정확하게 실행되도록 애플리케이션 포드를 설정합니다. 이를 변경하려면 애플리케이션 포드에 다음 nodeSelector를 추가합니다.

apiVersion: v1
kind: Pod
...
spec:
  nodeSelector:
      baremetal.cluster.gke.io/lbnode: "true"
...

인그레스

애플리케이션이 HTTP 서비스인 경우 인그레스 구성요소를 설정하여 클라이언트 IP를 공개 상태로 만들 수 있습니다.

  1. 수정할 istio-ingress 서비스를 엽니다.

    kubectl edit service -n gke-system istio-ingress
  2. externalTrafficPolicy: Localspec에 추가하고 편집기를 저장한 후 종료합니다.

    apiVersion: v1
    kind: Service
    ...
    spec:
    ...
      externalTrafficPolicy: Local
    
  3. 수정할 istio-ingress 배포를 엽니다.

    kubectl edit deployment -n gke-system istio-ingress
  4. 배포에 다음 nodeSelector를 추가하고 저장한 후 편집기를 종료합니다.

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
      template:
        ...
        spec:
          ...
          nodeSelector:
              baremetal.cluster.gke.io/lbnode: "true"
    ...
    

이제 다음 예시와 같이 인그레스를 기반으로 하는 모든 서비스에 클라이언트 IP가 있는 X-Forwarded-For 헤더가 표시됩니다.

X-Forwarded-For: 21.0.104.4