Envoy로 Consul 서비스 메시에서 서비스 로드 밸런싱하기

Envoy로 Consul 서비스 메시에서 서비스 로드 밸런싱하기

로드 밸런싱은 가용한 리소스를 가장 효과적으로 활용하기 위해 여러 대상 간에 트래픽을 분산하는 메커니즘이에요. 이를 달성하는 방법은 매우 다양하므로 Envoy는 여러 가지 로드 밸런싱 전략을 제공합니다. 이 Envoy 기능을 활용하기 위해 Consul은 Envoy 데이터 플레인 프록시가 사용하는 로드 밸런싱 정책을 변경하는 것을 지원해요. Consul 구성 항목(configuration entries)이 원하는 로드 밸런싱 알고리즘을 지정합니다.

로드 밸런싱 정책은 서비스 메시 내부의 내부 서비스 요청과, 인그레스 게이트웨이를 통해 데이터센터의 서비스에 접근하는 외부 클라이언트의 요청 모두에 적용돼요. 정책은 service-resolver 구성 항목을 사용해 정의됩니다.

이 튜토리얼은 메시의 서비스에 대한 로드 밸런싱 정책을 변경하는 데 필요한 단계를 안내해 드려요. maglev 정책을 사용해 서비스의 스티키 세션(sticky session)을 구성하고, 로드 밸런싱 트래픽을 위해 서비스 인스턴스의 요청 수를 고려하는 least_request 정책을 설정하는 방법을 배우게 됩니다.

출처: 문서

본문

전제 조건

Envoy 프록시용 Consul 로드 밸런싱 정책을 배포하고 테스트하려면 비프로덕션 환경에 다음 리소스가 배포되어 있어야 해요.

  • Consul 서비스 메시 기능이 활성화된 Consul 1.13.1 이상 클러스터. 구성 지침은 안전한 서비스 간 통신을 참고하세요. 이 튜토리얼에서는 이를 서버 노드(server node)라고 부를게요.
  • 로드 밸런싱 정책 튜닝이 필요한 backend라는 서비스의 인스턴스를 각각 호스팅하는 노드 2개
  • backend 서비스로 요청을 라우팅하는 데 사용할 클라이언트 서비스를 호스팅하는 노드 1개. 클라이언트 서비스는 backend 서비스를 업스트림으로 사용하도록 구성됩니다. 이 튜토리얼에서는 이를 클라이언트 노드(client node)라고 부를게요.
  • 선택 사항: 인그레스 게이트웨이로 실행되는 노드 1개

아래 다이어그램은 기능을 시연하는 데 필요한 최소 아키텍처를 보여줘요.

(다이어그램: 클라이언트 노드, backend 서비스 2개, 서버 노드, 선택적 인그레스 게이트웨이로 구성된 최소 아키텍처)

이 튜토리얼에는 실제 클라우드 인프라에서 진행해 볼 수 있는 무료 대화형 명령줄 랩이 포함되어 있어요.

사용 가능한 로드 밸런싱 정책

Consul은 선택한 접근 방식을 반영하도록 Envoy 구성을 자동화하여 로드 밸런싱을 구현해요. 다음 정책을 사용할 수 있습니다.

(표: 사용 가능한 로드 밸런싱 정책)

기본 로드 밸런싱 정책

Consul은 round_robin 정책을 사용해 해석된 서비스의 모든 정상 인스턴스에 걸쳐 트래픽을 자동으로 분산해요. 클라이언트 서비스를 실행하는 노드에서 curl 명령을 사용해 이를 확인할 수 있습니다.

먼저 클라이언트 노드에 로그인한 다음 클라이언트 서비스에 요청을 실행해요.

$ curl --silent localhost:9192

예제 출력:

{
  "name": "main",
  "uri": "/",
  "type": "HTTP",
  "ip_addresses": ["172.18.0.4"],
  "start_time": "2020-10-01T16:15:54.151406",
  "end_time": "2020-10-01T16:15:54.151885",
  "duration": "478.867µs",
  "body": "Hello World",
  "code": 200
}

명령을 여러 번 실행하면 출력을 통해 요청이 서비스의 두 인스턴스에 걸쳐 분산되고 있음을 확인할 수 있어요.

서비스 기본값 구성하기

서비스 해석을 활성화하고 로드 밸런서 정책을 적용하려면, 먼저 서비스의 service-defaults 구성 항목에서 서비스 프로토콜로 HTTP를 구성해야 해요.

먼저 서버 노드에 로그인한 다음 다음 내용으로 default.hcl 파일을 만드세요.

default.hcl

Kind     = "service-defaults"
Name     = "backend"
Protocol = "http"

그런 다음 구성을 Consul 데이터센터에 적용해요.

$ consul config write /etc/consul.d/default.hcl

예제 출력:

Config entry written: service-defaults/backend

서비스 해석을 위한 스티키 세션 구성하기

많은 애플리케이션의 일반적인 요구 사항은 특정 클라이언트의 모든 요청을 동일한 서버로 보내는 기능이에요. 이러한 구성은 일반적으로 HTTP 헤더에 의존하여 클라이언트 요청을 특정 백엔드에 매핑하고 그에 따라 트래픽을 라우팅합니다.

이 튜토리얼에서는 x-user-id 헤더를 사용하여 스티키 세션을 구현하는 정책을 구성할 거예요.

먼저 서버 노드에 로그인하고 다음 내용으로 hash-resolver.hcl 파일을 만드세요.

hash-resolver.hcl

Kind     = "service-resolver"
Name     = "backend"
LoadBalancer = {
  Policy = "maglev"
  HashPolicies = [
    {
      Field      = "header"
      FieldValue = "x-user-id"
    }
  ]
}

이 구성은 backend 서비스에 대해 maglev 정책을 사용하고 x-user-id 헤더의 내용에 의존하여 요청을 해석하는 service-resolver 구성을 만들어요. consul config 명령으로 정책을 적용할 수 있습니다.

$ consul config write /etc/consul.d/hash-resolver.hcl

예제 출력:

Config entry written: service-resolver/backend

정책 적용 확인하기

정책이 적용되면 클라이언트 노드에서 curl 명령을 사용하고 요청에 x-user-id 헤더를 추가하여 테스트할 수 있어요.

$ curl --silent localhost:9192 --header "x-user-id: 12345"

예제 출력:

{
  "name": "main",
  "uri": "/",
  "type": "HTTP",
  "ip_addresses": ["172.18.0.4"],
  "start_time": "2020-10-01T16:15:47.950151",
  "end_time": "2020-10-01T16:15:47.950581",
  "duration": "430.088µs",
  "body": "Hello World",
  "code": 200
}

이전 명령을 여러 번 실행하면 항상 동일한 인스턴스의 backend 서비스로 리다이렉트되는 것을 볼 수 있어요.

least_request 로드 밸런싱 정책 사용하기

기본 로드 밸런싱 정책인 round_robin은 요청이 동질적이고 시스템이 과잉 프로비저닝된 시나리오에서 일반적으로 최선의 접근 방식이에요. 서로 다른 인스턴스가 워크로드 측면에서 상당한 차이를 겪을 수 있는 시나리오에서는 더 나은 접근 방식이 있습니다.

least_request 정책을 사용하면 Consul이 연결 수준 메트릭에 대한 정보를 사용해 요청을 라우팅하고 연결 수가 가장 낮은 인스턴스를 선택할 수 있어요.

least_request 로드 밸런싱 정책 구성하기

튜토리얼의 랩 환경은 least_request 정책용 예제 구성 파일 least-req-resolver.hcl를 제공해요.

least-req-resolver.hcl

Kind     = "service-resolver"
Name     = "backend"
LoadBalancer = {
  Policy = "least_request"
  LeastRequestConfig = {
    ChoiceCount = "2"
  }
}

이 구성은 backend 서비스에 대해 service-resolver 구성을 만들어요. 요청마다 서비스의 무작위 인스턴스 2개(ChoiceCount로 표현)를 선택하고 가장 부하가 적은 인스턴스로 라우팅합니다. consul config 명령으로 정책을 적용할 수 있어요.

$ consul config write least-req-resolver.hcl

예제 출력:

Config entry written: service-resolver/backend

정책 적용 확인하기

정책이 적용되면 curl 명령을 사용하고 요청에 x-user-id 헤더를 추가하여 테스트할 수 있어요. 먼저 클라이언트 노드에 로그인한 다음 다음 명령을 사용하세요.

$ curl --silent localhost:9192 --header "x-user-id: 12345"

예제 출력:

{
  "name": "main",
  "uri": "/",
  "type": "HTTP",
  "ip_addresses": ["172.18.0.4"],
  "start_time": "2020-10-01T16:25:47.950151",
  "end_time": "2020-10-01T16:25:47.950581",
  "duration": "420.066µs",
  "body": "Hello World",
  "code": 200
}

명령을 여러 번 실행하면 이전 정책이 사용한 헤더를 적용했음에도 요청이 서비스의 다른 인스턴스들에 의해 처리되는 것을 알 수 있어요. ChoiceCount가 2로 설정된 least_request 구성은 P2C(power of two choices)라고도 알려져 있어요. P2C 로드 밸런서는 클러스터에서 활성 요청 수가 가장 많은 호스트가 새 요청을 받지 않는 특성을 가집니다. 그 호스트는 다른 모든 호스트보다 적거나 같아질 때까지 드레인(drain)되도록 허용됩니다. 이에 대해 더 자세히는 이 논문에서 읽을 수 있어요.

로드 밸런서 정책과 인그레스 게이트웨이 (선택 사항)

데이터센터의 로드 밸런싱 정책은 인그레스 게이트웨이가 수행하는 서비스 해석에도 적용돼요. 서비스에 대한 정책을 구성하고 클라이언트 서비스로 내부 테스트를 완료했다면, 구성에 인그레스 게이트웨이를 도입할 수 있고 이제 Consul 데이터센터가 서빙하는 외부 요청에도 동일한 정책이 적용됩니다.

Consul은 메시 내부 서비스의 내부 요청과 메시 외부 클라이언트의 외부 요청을 해석하는 데 공통 정책을 사용함으로써 로드 밸런싱 정책을 지정하는 데 필요한 구성을 줄여요.

다음 구성을 사용해 인그레스 게이트웨이를 배포할 수 있습니다.

ingress-gateway.hcl

Kind = "ingress-gateway"
Name = "ingress-service"
Listeners = [
 {
   Port     = 8080
   Protocol = "http"
   Services = [
     {
       Name = "backend"
     }
   ]
 }
]

구성이 적용된 후 consul config write 명령을 사용하고, 다음 명령으로 게이트웨이 노드에서 게이트웨이를 시작할 수 있어요.

$ consul connect envoy -gateway=ingress -register -service ingress-service -address '{{ GetInterfaceIP "eth0" }}:8888'

Envoy 프록시가 활성화되면 인그레스 게이트웨이를 사용해 브라우저에서 http://backend.ingress.consul:8080으로 서비스에 접근해 로드 밸런싱 정책을 테스트하고, 페이지를 새로고침하여 정책을 확인할 수 있어요. 또는 이전 장에서 설명한 대로 curl 명령을 사용하되 DNS 이름과 8080 포트를 사용해 테스트할 수 있습니다.

$ curl --silent backend.ingress.consul:8080

예제 출력:

{
  "name": "main",
  "uri": "/",
  "type": "HTTP",
  "ip_addresses": ["172.18.0.4"],
  "start_time": "2020-10-01T18:15:27.650151",
  "end_time": "2020-10-01T18:15:27.650581",
  "duration": "420.066µs",
  "body": "Hello World",
  "code": 200
}

구성 정보: 인그레스 게이트웨이 구성에서 http 리스너를 사용하면 Consul은 호스트 이름이 내부 명명 규칙 <service_name>.ingress.*와 일치할 때만 인그레스 게이트웨이 서비스에 대한 요청을 수락해요. 서비스를 다른 호스트 이름이나 IP로 접근 가능하게 해야 한다면 인그레스 게이트웨이 구성 항목 문서를 참고하세요.

다음 단계

이 튜토리얼에서 서비스 메시의 서비스에 대한 기본 로드 밸런싱 정책을 변경하는 방법을 배웠어요. Consul에서 사용할 수 있는 트래픽 분할의 다른 옵션에 대해 더 알아보려면 서비스 스플리터로 무중단 카나리 배포 튜토리얼을 참고하세요.

Consul 서비스 메시용 인그레스 게이트웨이 배포 방법을 더 알아보려면 인그레스 게이트웨이로 서비스 메시 내부에 외부 트래픽 허용 튜토리얼을 완료할 수 있어요.

더 알아보기 (Learn more)