TTOII 2023. 12. 4. 19:13
728x90

Envoy란 ?

Envoy란 Istio에 사용되는 proxy이다. 
Envoy Proxy는 Lyft 사에서 개발되었으며 오픈소스로 공개되었다.
기존 프록시 L4 기능뿐만 아니라 L7 기능도 지원하면서 HTTP 뿐만 아니라 다양한 프로토콜을 지원한다.
 
 
주요 기능적인 특성

  • HTTP, HTTP2.0, TCP, gRPC 프로토콜을 지원
  • TLS client certification 지원
  • HTTP L7 라우팅 지원을 통한 URL 기반 라우팅, 버퍼링, 서버간 부하 분산량 조절등
  • Auto retry, circuit breaker, 부하량 제한등 다양한 로드밸런싱 기능 제공
  • 다양한 통계 추적 기능 제공 및 Zipkin 통합을 통한 MSA 서비스간의 분산 트렌젝션 성능 측정 제공함으로써 서비스에 대한 다양한 가시성 (visibility)을 제공
  • Dynamic configuration 지원을 통해서, 중앙 레파지토리에 설정 정보를 동적으로 읽어와서 서버 재시작없이 라우팅 설정 변경이 가능함
  • MongoDB 및 AWS Dynamo 에 대한 L7 라우팅 기능 제공

 
 

Envoy 배포 아키텍처

Envoy 프록시는 배포 위치에 따라 다양한 기능을 수행 가능한데, 크게 4가지 구조에 배포가 가능하다.
 
Front envoy proxy

  • 특정 서비스가 아닌 전체 시스템 앞에 위치하는 프록시로, 클라이언트에서 들어오는 호출을 받아서 각각의 서비스로 라우팅한다. 
  • URL 기반으로 라우팅하는 기능 외에도 TLS 처리하는 역할들을 할 수 있다.
  • nginx나 apache httpd가 reverse proxy로 이 용도로 사용되었다.

 
Service to service ingress listener

  • 특정 서비스 앞에 위치하는 배포 방식으로 서비스로 들어오는 트래픽에 대한 처리를 하는데, 트래픽에 대한 버퍼링이나 Circuit breaker와 같은 역할을 수행한다.

 
Service to service egress listener

  • 특정 서비스 뒤에서 서비스로부터 나가는 트래픽을 통제하는데, 서비스로부터 호출 대상이 되는 서비스에 대한 로드밸런싱, 호출 횟수 통제(Rate Limiting)와 같은 기능을 수행한다.

 
External to service egress listener

  • 내부서비스에서 외부 서비스로 나가는 트래픽을 관리하는 역할인데, 외부 서비스에 대한 일종의 대행자와 같은 역할을 한다.

 
 

Envoy 주요 용어

호스트(Host)

  • 논리적인 네트워크 애플리케이션을 의미한다.
  • 하나의 물리적인 장비에 여러개의 호스트가 있을 수 있다.
  • 물리 장비 하나에 여러개의 주소가 있는 경우에 그 각각의 주소를 이용하는 애플리케이션들이 모두 하나의 호스트가 될 수 있다.

 
다운스트림(Downstream)

  • 엔보이에 요청을 보내고 응답을 받는 호스트이다. 보통 요청을 보내는 클라이언트를 뜻한다.

 
업스트림(Upstream)

  • 엔보이로 부터 요청을 받아서 응답을 보내는 호스트를 의미한다. 보통 요청을 받아주는 서버를 뜻한다.

 
리스너(Listener)

  • 다운스트림 클라이언트에서 연결할 수 있는 네트워크 위치(포트, 유닉스 도메인 소켓)를 의미한다.
  • 엔보이는 다운스트림에서 연결할 수 있는 리스너를 하나 이상 제공한다.

 
클러스터(Cluster)

  • 엔보이가 연결할 수 있는 논리적으로 비슷한 업스트림 호스트들의 그룹이다.
  • 엔보이는 서비스 디스커버리(service discovery)를 통해서 멤버들의 상태를 확인한다.
  • 헬스체크와 로드밸런싱 정책을 설정할 수 있다.

 
메시(Mesh)

  • 안정적인 네트워크 토폴로지를 제공하도록 관리하는 호스트들의 그룹이다.
  • “엔보이 메시”라고 하면 엔보이 프록시들의 그룹을 의미한다.

 
런타임 설정(Runtime configuration)

  • 실행중인 엔보이를 재시작하지 않고도 주요 설정들을 변경할 수 있는 기능이다.

 
Downstream => Listener => Filter => Cluster(Upstream) 의 순서로 메세지를 처리한다.
 
 

Example

... 중략
static_resources:
  # 리스너 설정
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0,  port_value: 80 } 
 
    # Filter 설정
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        config:
          stat_prefix: ingress_http
          http_filters:
          - name: envoy.filters.http.router
 
          # Route 설정
          route_config:
            name: route
            virtual_hosts:
            - name: nginx_service
              domains: ["nginx.local"]
              routes:
              - match:
                  prefix: "/alicek106"
                route:
                  cluster: nginx_cluster # Nginx Cluster로 라우팅
 
  # 클러스터 설정
  clusters:
  - name: nginx_cluster # Nginx cluster
    type: STRICT_DNS4
    connect_timeout: 0.25s
    lb_policy: ROUND_ROBIN5
    load_assignment:
      cluster_name: nginx_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: nginx1, port_value: 80 }
        - endpoint:
            address:
              socket_address: { address: nginx2, port_value: 80 }

(1) Listener에서 0.0.0.0:80 으로 들어오는 요청을 처리하겠다고 정의했고,
(2) nginx.local 도메인으로 들어오는 /alicek106 url Path 요청에 대해서는 nginx_cluster 클러스터로 요청을 라우팅한다.
(3) nginx_cluster 클러스터에서는 nginx1, nginx2 총 두 개의 엔드포인트를 정의했고, 라운드 로빈으로 요청을 전달하게 된다.
 
위 설정 파일로 Envoy 프록시 컨테이너를 생성하고, 라우팅될 Nginx 컨테이너를 생성한다.

$ docker network create envoy_test
 
$ docker run -d --name nginx1 --network envoy_test -h nginx1 nginx
$ docker run -d --name nginx2 --network envoy_test -h nginx2 nginx
 
$ docker run -it --network envoy_test --rm -p 80:80 \
  -v /tmp/envoy.yaml:/tmp/envoy.yaml envoyproxy/envoy:v1.14.1 envoy -c /tmp/envoy.yaml

 
 
그리고 나서 적당히 요청을 보내 보면 Nginx로 요청이 잘 가고 있는 것을 알 수 있다.

$ curl nginx.local:80/alicek106 --resolve 'nginx.local:80:127.0.0.1'
 
...
<hr><center>nginx/1.17.10</center>
...​

 
 
 
참고

728x90