Service_Mesh/Istio
[Istio-2주차] Envoy in action (실습)
- -
Envoy - 실습
도커로 httpbin 서비스와 프록시 구성하기
- Envoy의 기본적인 프록시 기능과 타임아웃 설정, 그리고 헤더 변화를 하나씩 따라가며 경험한 과정을 정리한다.
1. 실습 환경 준비
- Envoy는 C++로 작성되어 다양한 플랫폼에서 사용할 수 있다.
- 실습에 사용할 이미지는 아래와 같다.
docker pull envoyproxy/envoy:v1.19.0
docker pull curlimages/curl
docker pull mccutchen/go-httpbin
이미지가 정상적으로 받아졌는지
docker images명령어로 확인한다.

2. httpbin 서비스 실행
- httpbin은 다양한 HTTP 요청을 실험할 때 유용한 테스트용 서비스로, 금번 실습에서는 간단한 httpbin 서비스를 만들어본다.
- 기본적으로 httpbin은 호출하는 엔드포인트에 따라 호출할 때 사용한 헤더를 반환하거나, HTTP 요청을 지연시키거나, 오류를 발생시키는 등의 서비스를 제공한다.
- ex) http://httpbin.org/headers 로 이동
- httpbin 서비스를 시작 → Envoy를 시작 → 모든 트래픽이 httpbin 서비스로 가도록 프록시를 설정할 예정
- 프록시 설정 후 클라이언트 앱을 시작해 프록시를 호출

예시 이미지 - 기본 포트는 8080이지만, 이번 실습에서는 8000번 포트로 변경해 실행한다.
docker run -d -e PORT=8000 --name httpbin mccutchen/go-httpbin
docker ps

- 정상적으로 컨테이너가 실행된 후, curl 컨테이너를 이용해 httpbin의
/headers엔드포인트를 호출해본다.
docker run -it --rm --link httpbin curlimages/curl curl -X GET http://httpbin:8000/headers
- 요청에 사용된 헤더 정보가 반환되는 것을 확인할 수 있다.

{
"headers": {
"Accept": [
"*/*"
],
"Host": [
"httpbin:8000"
],
"User-Agent": [
"curl/8.13.0"
]
}
}
3. Envoy 프록시 컨테이너 실행
- Envoy proxy 를 실행하고 help 를 전달해 플래그와 명령줄 파라미터 중 일부를 확인해 본다.
-
# envoy help document 참조 docker run -it --rm envoyproxy/envoy:v1.19.0 envoy --help ... --service-zone <string> # 프록시를 배포할 가용 영역을 지정 Zone name --service-node <string> # 프록시에 고유한 이름 부여 Node name ... -c <string>, --config-path <string> # 설정 파일을 전달 Path to configuration file- Envoy 실행 : 프록시를 실행하려고 했지만 유효한 설정 파일을 전달하지 않았다.
# envoy 실행 시도 docker run -it --rm envoyproxy/envoy:v1.19.0 envoy [2021-11-21 21:28:37.347][1][info][main] ... [source/server/server.cc:855] exiting At least one of --config-path or --config-yaml or Options::configProto() should be non-empty 위와 같이 --config-path 나 --config-yaml 을 제공해달라는 문구가 발생한다.
- 확인한 바와 같이 Envoy를 실행하려면 반드시 설정 파일이 필요하다.
- 아래와 같이, 예제 설정 파일로 해결해본다.
admin:
address:
socket_address: { address: 0.0.0.0, port_value: 15000 }
static_resources:
listeners:
- name: httpbin-demo
address:
socket_address: { address: 0.0.0.0, port_value: 15001 }
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
http_filters:
- name: envoy.filters.http.router
route_config:
name: httpbin_local_route
virtual_hosts:
- name: httpbin_local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
auto_host_rewrite: true
cluster: httpbin_service
clusters:
- name: httpbin_service
connect_timeout: 5s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: httpbin
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: httpbin
port_value: 8000
이 설정은 15001 포트로 들어온 모든 트래픽을 httpbin(8080) 서비스로 라우팅한다.
- Envoy를 아래와 같이 실행, 로그를 확인한다.
# 설정 예제 파일 확인
cat ch3/simple.yaml
# Terminal 1
docker run --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple.yaml)"
# Terminal 2
docker logs proxy
[2025-04-12 08:25:15.455][1][info][config] [source/server/listener_manager_impl.cc:834] all dependencies initialized. starting workers
[2025-04-12 08:25:15.456][1][info][main] [source/server/server.cc:804] starting main dispatch loo

- 위와 같이 all dependencies initialized. starting workers 혹은 starting main dispatch loop 로그가 확인된다.
- 서버가 정상적으로 실행되어 리스닝을 하고 있음을 알 수 있다.
4. 프록시를 통한 요청 및 헤더 확인
- 이제 curl 컨테이너를 통해 Envoy 프록시를 경유하여 httpbin에 요청을 보낸다.
- 위의 yaml 파일에서 port를 15001로 설정했기 때문에 15001로 접근해본다.
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/headers
- 응답 결과

{
"headers": {
"Accept": [
"*/*"
],
"Host": [
"httpbin"
],
"User-Agent": [
"curl/8.13.0"
],
"X-Envoy-Expected-Rq-Timeout-Ms": [
"15000"
],
"X-Forwarded-Proto": [
"http"
],
"X-Request-Id": [
"3fd55f78-4b23-4428-adbb-54351c74df20"
]
}
}
- 프록시에 curl 요청을 하였지만 httpbin 으로 트래픽이 라우팅 된 것을 확인할 수 있다.
- 응답에는 기존 헤더 외에도 Envoy가 자동으로 추가한
X-Envoy-Expected-Rq-Timeout-Ms와X-Request-Id헤더가 포함되어 있다.- X-Request-Id: 각 요청마다 고유한 ID가 생성되어, 클러스터에 인입되는 다양한 요청을 식별할 수 있다. 또한 요청에 따른 여러 서비스 간 홉 추적 가능
- X-Envoy-Expected-Rq-Timeout-Ms: 업스트림 서비스에 타임아웃 정보-힌트를 전달한다. (결과에서는 요청이 15,000ms 후에 타임아웃 될 것으로 기대하는 값임을 의미)
- 이후 실습을 위해 Envoy 프록시를 삭제한다.
docker rm -f proxy
5. 요청 타임아웃 설정 변경(지연) 실습
- 설정 파일의 라우팅 규칙에 타임아웃 값을 1초로 변경한다.
# timeout 변경 예시 yaml 적용
docker run -p 15000:15000 --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple_change_timeout.yaml)"
docker run --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple_change_timeout.yaml)"
cat ch3/simple_change_timeout.yaml
# 변경 내용
- match: { prefix: "/" }
route:
auto_host_rewrite: true
cluster: httpbin_service
timeout: 1s
# 확인
docker ps
- 변경된 설정으로 프록시를 통해 요청 보내기
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/headers
- 결과:
X-Envoy-Expected-Rq-Timeout-Ms값이 1000(1초)로 변경된 것을 확인할 수 있다.

{
"headers": {
"Accept": [
"*/*"
],
"Host": [
"httpbin"
],
"User-Agent": [
"curl/8.13.0"
],
"X-Envoy-Expected-Rq-Timeout-Ms": [
"1000" # 1000ms = 1s 변경 확인
],
"X-Forwarded-Proto": [
"http"
],
"X-Request-Id": [
"1ec6116b-da79-4886-9ae1-6254b13bb964"
]
}
}
6. 추가 테스트: 지연 응답 시 타임아웃 동작 확인
httpbin의 /delay/{n} 엔드포인트를 활용해 0.5초, 1초, 2초 지연 요청을 각각 보낸다.
# 추가 테스트 : http 로그 레벨 debug로 설정
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging?http=debug
# 추가 테스트 : Envoy Admin API(TCP 15000) 를 통해 delay 설정
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/delay/0.5
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/delay/1
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/delay/2
- 0.5초, 1초 요청은 정상 응답된다.


- 2초 요청은 Envoy에서 타임아웃 처리되어 실패한다. - upstream request timeout

위를 통해 Envoy의 타임아웃 설정이 실제로 동작하는 것을 직접 검증할 수 있다.
Envoy - Admin API
- 엔보이의 Admin API를 사용하면 프록시 동작에 대한 통찰력을 향상시킬 수 있고, 메트릭과 설정에 접근할 수 있다.
#
docker run --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple_change_timeout.yaml)"
# admin API로 Envoy stat 확인 : 응답은 리스너, 클러스터, 서버에 대한 통계 및 메트릭
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats
# retry 통계만 확인
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats | grep retry
cluster.httpbin_service.circuit_breakers.default.rq_retry_open: 0
cluster.httpbin_service.circuit_breakers.high.rq_retry_open: 0
cluster.httpbin_service.retry_or_shadow_abandoned: 0
cluster.httpbin_service.upstream_rq_retry: 0
cluster.httpbin_service.upstream_rq_retry_backoff_exponential: 0
cluster.httpbin_service.upstream_rq_retry_backoff_ratelimited: 0
cluster.httpbin_service.upstream_rq_retry_limit_exceeded: 0
cluster.httpbin_service.upstream_rq_retry_overflow: 0
cluster.httpbin_service.upstream_rq_retry_success: 0
...
# 다른 엔드포인트 일부 목록들도 확인
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/certs # 머신상의 인증서
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/clusters # 엔보이에 설정한 클러스터
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/config_dump # 엔보이 설정 덤프
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/listeners # 엔보이에 설정한 리스너
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging # 로깅 설정 확인 가능
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging?http=debug # 로깅 설정 편집 가능
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats # 엔보이 통계
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats/prometheus # 엔보이 통계(프로메테우스 레코드 형식)

Envoy request retries 요청 재시도
- httpbin 요청을 일부러 실패시켜서 envoy가 요청을 자동으로 재시작하는지 살펴보자. (retries)
- 전과 같이 retry_policy를 사용하도록 설정 파일을 업데이트 한다.
- match: { prefix: "/" }
route:
auto_host_rewrite: true
cluster: httpbin_service
retry_policy:
retry_on: 5xx # 5xx 일때 재시도
num_retries: 3 # 재시도 횟수
- 실습 진행
# 이전 envoy proxy 삭제
docker rm -f proxy
# retry 예제 적용하여 envoy proxy 실행
cat ch3/simple_retry.yaml
docker run -p 15000:15000 --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple_retry.yaml)"
# http 로그 레벨 debug 설정
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging?http=debug
# /stats/500 경로로 프록시를 호출 : 이 경로로 httphbin 호출하면 오류가 발생
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/status/500
# 호출이 끝났는데 아무런 응답도 보이지 않는다. 엔보이 Admin API에 확인
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats | grep retry
...
cluster.httpbin_service.retry.upstream_rq_500: 3
cluster.httpbin_service.retry.upstream_rq_5xx: 3
cluster.httpbin_service.retry.upstream_rq_completed: 3
cluster.httpbin_service.retry_or_shadow_abandoned: 0
cluster.httpbin_service.upstream_rq_retry: 3
...
- 500 에러 주입

- envoy에서 재시도 호출 확인

- stats 확인
- cluster.httpbin_service.retry.upstream_rq_500 가 3으로 확인
- cluster.httpbin_service.upstream_rq_retry 가 3으로 확인
- cluster.httpbin_service.upstream_rq_retry_limit_exceeded가 1로 확인
Envoy는 업스트림 클러스터 httpbin을 호출할 때 500 에러를 반환받아 요청을 재시도하였음을 알 수 있다.
Envoy 동적 설정
- 위의 httpbin 예시는 정적 설정 파일을 사용
- Istio는 xDS 컴포넌트를 이용해서 동적 설정 기능을 사용
동적 설정 예시
bootstrap:
dynamicResources:
ldsConfig:
ads: {} # ADS for listeners 리스너용 ADS
cdsConfig:
ads: {} # ADS for clusters 클러스터용 ADS
adsConfig:
apiType: GRPC
grpcServices:
- envoyGrpc:
clusterName: xds-grpc # Uses a cluster named xds-grpc 라는 클러스터를 사용
refreshDelay: 1.000s
staticResources:
clusters:
- name: xds-grpc # Defines the xds-grpc cluster 라는 클러스터를 정의
type: STRICT_DNS
connectTimeout: 10.000s
hosts:
- socketAddress:
address: istio-pilot.istio-system
portValue: 15010
circuitBreakers: # Reliability and circuit-breaking settings 신뢰성 및 서킷 브레이커 설정
thresholds:
- maxConnections: 100000
maxPendingRequests: 100000
maxRequests: 100000
- priority: HIGH
maxConnections: 100000
maxPendingRequests: 100000
maxRequests: 100000
http2ProtocolOptions: {}
# 다음 실습을 위해 Envoy 종료
docker rm -f proxy && docker rm -f httpbin
'Service_Mesh > Istio' 카테고리의 다른 글
| [Istio-3주차] Traffic control (이론, 실습) (0) | 2025.04.27 |
|---|---|
| [Istio-2주차] Ingress Gateway, Virtual Service (실습) (0) | 2025.04.20 |
| [Istio-2주차] Istio Gateway (이론) (0) | 2025.04.20 |
| [Istio-2주차] Envoy (이론) (0) | 2025.04.20 |
| [Istio-1주차] Istio 첫걸음 (실습) (0) | 2025.04.13 |
Contents
소중한 공감 감사합니다.