본문 바로가기
기타/기타

[proxy] Envoy 이해하기 - 기본 이론편

by 사바라다 2025. 3. 28.
반응형

개요

마이크로서비스 아키텍처가 보편화되면서, 서비스 간 통신의 복잡성도 함께 증가했습니다. 서비스 간 라우팅, 로드 밸런싱, 모니터링, 보안 등 다양한 과제를 해결하기 위해 등장한 것이 바로 Envoy입니다. Envoy는 쿠버네티스 환경에서 Data Plane으로써 application의 side car로 많이 사용되는데요. 오늘은 이러한 Envoy에 대해서 알아보는 시간을 가져보도록 하겠습니다.

Envoy의 탄생 배경

Envoy는 원래 Lyft에서 개발되었습니다. Lyft는 수많은 마이크로서비스를 운영하면서 네트워크 관련 문제에 지속적으로 부딪혔고, 기존의 솔루션으로는 문제를 해결하기 어려웠습니다. 이 과정에서 새로운 L7 프록시가 필요하다는 결론에 도달했고, 그렇게 탄생한 것이 Envoy입니다. 이후 2016년 오픈소스로 공개되었고, 현재는 CNCF(Cloud Native Computing Foundation)의 핵심 프로젝트로 자리 잡았습니다.

Envoy의 역할

위의 이미지처럼 간단히 보면 Envoy는 nginx와 같은 Reverse Proxy 서버의 역할을 담당합니다. 추가로 Envoy는 설정에 따라서 L7 프록시, API Gateway, 그리고 사이드카 프록시 등의 역할을 수행 할 수 있습니다.

  • L7 프록시: HTTP/HTTPS와 같은 애플리케이션 계층의 트래픽을 기반으로 프록시 처리합니다.
  • API Gateway: 외부 클라이언트 요청을 내부 서비스로 라우팅하고, 인증·로그·모니터링 기능을 제공합니다.
  • 사이드카 프록시: 서비스 메시(SM)의 핵심 구성 요소로, 각 마이크로서비스 인스턴스 옆에 배치되어 인바운드/아웃바운드 트래픽을 관리합니다.

Envoy가 Application 서버의 Proxy 역할을 할 때의 장점

Envoy는 애플리케이션 서버 앞단에 위치해 리버스 프록시로 동작할 수 있습니다. 이 경우 다음과 같은 장점이 있습니다:

  • L7 라우팅 기능: 경로, 헤더, 쿼리 문자열 등을 기반으로 복잡한 라우팅 정책을 구성할 수 있어, 다양한 요청 처리 시나리오에 유연하게 대응할 수 있습니다.
  • Load Balancer: 여러 백엔드 서버로 트래픽을 효율적으로 분산시켜, 서버의 과부하를 방지하고 안정적인 응답 속도를 유지할 수 있습니다.
  • Service HealthCheck: 백엔드 서버의 상태를 주기적으로 점검하여 비정상적인 인스턴스를 자동으로 제외시켜 장애 전파를 방지합니다.
  • Observability: 요청/응답에 대한 메트릭 수집, 구조화된 로그 출력, 분산 트레이싱 기능을 통해 시스템 전반의 가시성을 높일 수 있습니다.
  • TLS 종료 및 보안 강화: 클라이언트와의 TLS 연결을 Envoy에서 종료함으로써 애플리케이션은 평문 통신만 처리하면 되고, 보안 설정을 중앙 집중화할 수 있습니다.
  • 속도 및 확장성: C++로 구현되어 성능이 뛰어나며, 다양한 환경에 배포 가능한 유연성을 제공합니다.

주요 기능

Envoy는 다음과 같은 핵심 기능들을 제공합니다:

  • 정교한 라우팅: 요청 경로, 헤더, 메서드 등을 기반으로 트래픽을 라우팅합니다.
  • 필터 체인: 요청/응답 처리 과정에서 다양한 필터를 체인 형태로 구성해 트래픽을 가공합니다.
  • 서비스 디스커버리: 동적으로 백엔드 서비스 인스턴스를 검색하고 연결합니다.
  • 트래픽 분할: Canary 배포, A/B 테스트 등을 위한 트래픽 분할이 가능합니다.
  • 헬스 체크: 백엔드 서비스 상태를 주기적으로 점검하고, 문제가 있는 인스턴스를 자동으로 제외합니다.
  • 통계 및 로그 수집: 메트릭, 로그, 트레이싱 기능을 통해 네트워크 상태를 관찰할 수 있습니다.

간단한 Envoy 구성 파일 분석

Envoy는 YAML 포맷의 구성 파일을 통해 동작을 정의합니다. 구조가 유연하고 모듈화되어 있어 상황에 맞게 확장하거나 축소할 수 있습니다.

envoy.yaml 기본 구조

아래는 가장 기본적인 Envoy 설정의 구조입니다.
구성의 자세한 내용은 다음 포스팅에서 확인해보며 이번 포스팅에서는 파일의 기본 구조만 보도록 하겠습니다.

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 10000 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route: { cluster: backend_service }
                http_filters:
                  - name: envoy.filters.http.router
  clusters:
    - name: backend_service
      connect_timeout: 0.25s
      type: logical_dns
      lb_policy: round_robin
      load_assignment:
        cluster_name: backend_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: backend
                      port_value: 8080

예제: HTTP 요청을 백엔드로 프록시하는 기본 설정

위 예제는 Envoy가 수신하는 HTTP 요청을 내부의 backend:8080 서비스로 전달하는 가장 단순한 구성입니다. 주요 요소를 간단히 살펴보면:

  • listeners: Envoy가 수신 대기할 IP와 포트를 정의합니다.
  • filter_chains: 요청 처리를 위한 필터 체인을 설정합니다.
    • filter_chain이란 어떠한 조건으로 요청을 처리할 것인지 정하는 것입니다.
    • 예를 들어 L4 계층 기반으로 라우팅할지 L7 계층 기반으로 라우팅할지 등의 상위 레벨의 설정을 할 수 있습니다.
  • route_config: URL 경로 기반 라우팅 설정입니다.
    • 실제 라우팅의 조건 및 라우팅할 서비스 등을 지정할 수 있습니다.
  • clusters: 백엔드 서비스의 연결 정보와 로드 밸런싱 정책입니다.

이러한 구성을 통해 Envoy는 수신된 요청을 적절한 백엔드 서비스로 전달하고, 그 과정에서 로깅, 모니터링, 라우팅 등 다양한 처리를 수행할 수 있습니다.

마무리

다음 시간에는 로컬에서 Envoy 실행 및 테스트를 진행해서 좀 더 쉽게 이해할 수 있도록 다가가겠습니다.

감사합니다.

참조

[1] https://www.youtube.com/watch?v=40gKzHQWgP0

[2] https://www.youtube.com/watch?v=E-UpGmj6B9M

반응형

댓글