지난 포스팅에서는 Envoy Proxy의 기본 개념과 특징에 대해 알아보았다.
이번 포스팅에서는 실습을 통해 Envoy가 실제로 어떻게 동작하는지,
그리고 Istio에서는 Envoy를 어떤 방식으로 제어하고 구성하는지를 살펴보고, Istio의 동작 원리에 대해 이해해 보자.
Envoy 핵심 용어 정리
Istio를 학습하면서, 로그 및 설정을 분석하거나 디버깅할 때, Envoy의 개념과 용어를 명확하게 이해하고 있지 않아, 너무 헷갈렸다.
Envoy의 핵심 용어들을 먼저 정리해 보도록 하자. 이후 설정 확인이나 트래픽 흐름 분석에서도 훨씬 수월해질 것이다.
Upstream vs Downstream
• istio-proxy를 기준으로, Upstream은 요청이 향하는 대상(서버), Downstream은 요청을 보낸 주체(클라이언트)를 의미한다.
Clusters
• Envoy가 트래픽을 전달할 수 있는 논리적인 서비스 집합
• 여러 엔드포인트(실제 서버)를 하나로 묶은 개념
• 예: outboud|80|webapp.istioinaction.svc.cluster.local
Endpoints
• 개별 네트워크 노드(IP:Port 형식)
• 클러스터 내부에 포함되는 실제 트래픽 대상
• 예: 10.10.0.16:8080
Listeners
• Envoy가 바인딩된 IP/Port에서 수신할 트래픽을 정의(Haproxy 프론트엔드와 비슷)
• 다운스트림을 조정하는 역할
• Haproxy 프론트엔드 역할
Routes
• 들어온 요청을 어떤 클러스터로 라우팅 할지 결정
• URI, 헤더, 메서드 등에 따라 세부적으로 분기 가능
Filter / Filter Chain
• 요청이 들어오고 처리되기까지 중간 처리 파이프라인
• 인증, 로깅, 라우팅 전처리 등 다양한 역할 수행
Envoy xDS 이해하기
Istio는 동적으로 구성 정보를 주입받기 위해 Enovy의 xDS API를 활용한다.
Istio에서는 이 기능을 확장하여 istiod와 istio-proxy(Envoy)
간 통신을 라우팅, 클러스터, 엔드포인트 드의 설정을 자동으로 갱신하고 반영한다.
CDS (Cluster Discovery Service) | 업스트림 서비스와의 연결을 위한 클러스터 정의를 관리합니다. |
EDS (Endpoint Discovery Service) | 클러스터 내 엔드포인트(특정 인스턴스)를 관리하여 동적 서비스 발견을 가능하게 합니다.. |
LDS (Listener Discovery Service) | 특정 포트에서 Envoy가 수신 연결을 처리하는 리스너를 구성합니다 |
RDS (Route Discovery Service) | HTTP 요청의 라우팅 규칙을 정의하여 요청이 클러스터로 전달되는 방식을 결정합니다. |
SDS (Secret Discovery GService) | TLS 인증서와 같은 보안 자격 증명을 관리하여 안전한 통신 구성을 제공합니다. |
쉽게 말해, 위에서 다룬, Envoy 핵심 용어들의 설정들을 동적으로 관리해 주는 API 모음이다.
추가로, ADS(aggregation Discovery Service)는 동시성 문제를 위해, xDS API들을 순차적으로 관리해주는 서비스이다.
istioctl proxy-status
명령어 시, xDS 상태를 조회할 수 있다.
아래와 같이 개별 조회도 가능하다.
istioctl proxy-config listener webapp-7685bcb84-kck9h.istioinaction
ADDRESSES PORT MATCH DESTINATION
10.200.1.10 53 ALL Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
0.0.0.0 80 Trans: raw_buffer; App: http/1.1,h2c Route: 80
0.0.0.0 80 ALL PassthroughCluster
...
실습 전 준비사항
샘플 소스코드(책) 클론
책 예제 실습 코드를 클론 받고, 해당 경로에서 실습을 진행한다.
git clone https://github.com/AcornPublishing/istio-in-action
cd book-source-code-master
Envoy 설치
Envoy는 다양한 설치방식을 지원한다, 이번 실습에서는 macOS 및 Docker 환경에서 Envoy를 설치하여 사용한다.
MacOS
brew install envoy
envoy --help
Docker
docker run --rm \
envoyproxy/envoy:dev-72fd99b8c3681e413eb40ecaebfb1c3454810763 \
--version
Envoy 실습 1 - Configuration: Static
Istio를 사용하기 전, Enovy에 대한 기능들을 실습해 보고, 동작원리를 이해할 수 있도록 한다.
Envoy Admin API 기본 동작 확인
먼저, 간단한 정적 Enovy 설정 파일을 주입하여, Envoy의 기본동작 및 Admin API를 확인해 본다.
Envoy 설정 파일 확인(simple_change_timeout.yaml)
- Admin API 포트는
15000
, httpbin 서비스는15001
로 라우팅 - 모든 도메인에 대한 요청 시,
httpbin_service
클러스터로 라우팅
Envoy의 컨테이너 실행
- 도커 컨테이너로 envoy의 설정파일을 적용하고 envoy 프록시를 실행하여 envoy-admin api를 사용해 본다.
- curl 이미지 컨테이너를 이용하여 통신한다
- -- link 옵션으로 둘 간의 컨테이너 통신을 할 수 있도록 함.
# httpbin 서비스 배포
docker run -d -e PORT=8000 --name httpbin mccutchen/go-httpbin
# 정적파일을 주입하여 Envoy 실행
docker run --name proxy \
-p 15000:15000 \
-p 15001:15001 \
--link httpbin \
envoyproxy/envoy:v1.19.0 \
--config-yaml "$(cat ch3/simple_change_timeout.yaml)"
httpbin 서비스 요청
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001
Admin API 요청 예시
# admin API로 Envoy stat 확인 : 응답은 리스너, 클러스터, 서버에 대한 통계 및 메트릭
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 POST http://proxy:15000/logging?http=debug
# 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 # 엔보이 통계(프로메테우스 레코드 형식
주요 Admin API 엔드포인트는 다음과 같다.
엔드포인트 | 설명 |
---|---|
/stats | 전체 통계 조회 |
/stats/prometheus | Prometheus 형식의 통계 출력 |
/clusters | 설정된 클러스터 정보 확인 |
/listeners | 리스너 정보 확인 |
/config_dump | 전체 Envoy 설정 덤프 |
/certs | 인증서 상태 조회 |
/logging | 현재 로깅 수준 확인 |
/logging?http=debug (POST) | HTTP 로깅 레벨을 debug로 설정 |
브라우저 확인 - httpbin 서비스
브라우저 확인 - Envoy Admin Page
Admin API 같은 경우 간단한 UI를 통해 기능 제공
Envoy Configuration : Envoy request retrie
이전, Istio 환경에서 사용했던 Retry 설정을 Envoy 단독 구성으로 직접 적용하고, 내부에서 어떻게 동작하는지를 확인해 본다.
Envoy 설정 파일 확인(simple_retry.yaml)
- 5xx 오류 코드를 반환하는 엔드포인트가 있을 경우 재시도(3회) 설정
Envoy Retry 설정 적용
# Envoy 실행
docker run -p 15000:15000 \
--name proxy \
--link httpbin \
envoyproxy/envoy:v1.19.0 \
--config-yaml "$(cat ch3/simple_retry.yaml)"
Retry 동작 확인
실제 요청은 500 오류를 반환하지만, Envoy가 자동으로 재시도를 수행하기 때문에, 사용자 입장에서는 에러를 인지할 수 없음
# /stats/500: 이 경로로 httphbin 호출하면 의도적으로 500 에러 발생
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/status/500
-> 아무런 응답도 보이지 않는다 = 에러 X
# 엔보이 프록시 debug 모드로 변경
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging?http=debug
# 엔보이 프록시 로그 확인
docker logs -f proxy
...
[2025-04-17 06:34:59.685][33][debug][http] [source/common/http/conn_manager_impl.cc:1456] [C7][S1691598046856484536] encoding headers via codec (end_stream=true):
':status', '500'
'access-control-allow-credentials', 'true'
'access-control-allow-origin', '*'
'content-type', 'text/plain; charset=utf-8'
'date', 'Thu, 17 Apr 2025 06:34:59 GMT'
'content-length', '0'
'x-envoy-upstream-service-time', '100'
'server', 'envoy'
Admin API 통계로 Retry 여부 확인
위 값들을 통해 Envoy가 실제로 3번의 재시도를 수행했음을 확인
# 호출이 끝났는데 아무런 응답도 보이지 않는다. 엔보이 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
...
Envoy 실습 2 - Configuration: Dynamic
Envoy의 핵심 기능 중 하나는 동적(dynamic) 설정을 지원하는 것이다.
동적 설정은 두 가지 방식으로 구성할 수 있다:
- 파일 시스템 기반(Filesystem): 설정 파일을 로컬 디렉터리에서 주기적으로 읽어 반영
- 컨트롤 플레인 기반(Control Plane): Istiod 같은 서버로부터 xDS API를 통해 실시간으로 주입
Configuration: Dynamic from Filesystem
이번 실습에서는 파일 시스템 기반 동적 설정 방식을 먼저 다루며, 설정 파일을 통해 Envoy가 동적으로 구성되는 과정을 확인한다
설정 파일 구성
- path: 설정 파일들의 파일 경로를 지정
- 10000 포트로 접근 시,
www.envoyproy.io
데모 페이지로 라우팅
Envoy 실행
- 19000 포트에서 Admin API 서버가 시작됨
- Listener 및 Cluster가 정상적으로 로드되었음을 알 수 있음
# 같은 경로 인지 확인
envoy-dynamic-cds-demo.yaml envoy-dynamic-filesystem-demo.yaml envoy-dynamic-lds-demo.yaml
# Envoy실행
envoy -c envoy-dynamic-filesystem-demo.yaml
Starting admin HTTP server at 0.0.0.0:19000
...
lds: add/update listener 'listener_0'
...
all clusters initialized. initializing init manager
...
라우팅 테스트
# 응답으로 www.envoyproxy.io 페이지의 HTML 내용이 출력되면 성공
curl localhost:10000
브라우저에서 확인
⚠️ 파일 시스템 기반 방식의 단점
- 설정 파일이 변경되었을 경우, Envoy는 자동으로 반영하지 않음
- 파일을 잘못 수정하거나 재시작 없이 반영하려 할 경우, 프로세스 충돌 또는 크래시가 발생할 수 있음
따라서, 이러한 이유들로 Istio에서는 Filesystem 기반보다 Control Plane 기반의 동적 설정(xDS) 방식을 사용한다.
Configuration: Dynamic from control plane
Envoy는 파일 기반이 아닌 컨트롤플레인과의 연결을 통해 동적으로 설정을 주입받을 수 있다. 이때는 Envoy는 이때 Envoy의 핵심 컴포넌트 Istiod와 gPRC기반의 xDS API로 통신하며, 클러스터, 리스터, 라우트 등 설정을 실시간으로 수행한다. Istio는 가장 인기 있는 Envoy의 컨트롤 플레인이라고 소개한다.
Istiod 포트포워딩으로 Envoy 연결
kind 클러스터에 설치된 Istiod는 클러스터 외부에서 접근 불가하므로, 포트포워딩으로 gRPC 포트를 노출한다.
# 30004: trace -> istiod 임시 변경!
kubectl port-forward -n istio-system svc/istiod 30004:15010
Envoy 설정파일 확인(envoy-dynamic-control-plane-demo)
• xds_cluster를 통해 Envoy는 Istiod로부터 설정을 실시간 수신함
node:
cluster: test-cluster
id: test-id
dynamic_resources:
ads_config:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
cds_config:
ads: {}
lds_config:
ads: {}
static_resources:
clusters:
- type: STRICT_DNS
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
name: xds_cluster
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: localhost #
port_value: 30004
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 19000
Envoy는 Istiod와의 연결을 통해 xDS 기반 설정을 동적으로 수신하는 것을 확인할 수 있다. 해당 실습에서는 컨트롤플레인과의 연결을 확인하였고, 세부적인 설정을 Istio를 통해 다뤄볼 것이다.
Istio가 애플리케이션에 사이드카로 주입한 Envoy Proxy
실제, Istio가 각 워크로드(Pod)에 istio-proxy 사이드카를 자동 주입하고, 이 과정에서 /etc/istio/proxy/envoy-rev.json
파일을 통해 설정을 수신하며, 실제 xds 설정 흐름을 살펴볼 수 있다.
kubectl exec -it -n istioinaction webapp-7685bcb84-z7xjg -c istio-proxy -- cat /etc/istio/proxy/envoy-rev.json
kubectl exec -it -n istioinaction webapp-7685bcb84-z7xjg -c istio-proxy -- cat /etc/istio/proxy/envoy-rev.json | grep 15000
설정 파일을 확인해 보면, xds-grpc 클러스터는 유닉스 도메인 소켓(XDS)파일을 통해 istiod와 통신하며, istio-proxy 컨테이너에서 소켓 파일도 확인 할 수 있다.
kubectl exec -it -n istioinaction webapp-7685bcb84-z7xjg -c istio-proxy -- ls -al /etc/istio/proxy │rminationDrainDuration":"5s","tracing":{"zipkin":{"address":"zipkin.istio-system:9411"}}},"SERVICE_ACCOUNT":"webapp","WORKLOAD_NAME":"webapp
total 24 │"}
drwxrwxrwt 2 root root 100 Apr 17 12:24 . │ "port_value": 15000
drwxr-xr-x 1 root root 16 Apr 17 12:24 .. │ "port_value": 15000
srw-rw-rw- 1 istio-proxy istio-proxy 0 Apr 17 12:24 XDS │(⎈|kind-myk8s:external-test) JSX⚡️ ~/workspace
-rw-r--r-- 1 istio-proxy istio-proxy 17777 Apr 17 12:24 envoy-rev.json │ kubectl exec -it -n istioinaction webapp-7685bcb84-z7xjg -c istio-proxy -- cat /etc/istio/proxy/envoy-rev.json | grep dynamic
-rw-r--r-- 1 istio-proxy istio-proxy 2814 Apr 17 12:24 grpc-bootstrap.json
XDS 소켓 파일을 통해.. 통신
#envoy-rev.json
{
"name": "xds-grpc",
"type" : "STATIC",
"connect_timeout": "1s",
"lb_policy": "ROUND_ROBIN",
"load_assignment": {
"cluster_name": "xds-grpc",
"endpoints": [{
"lb_endpoints": [{
"endpoint": {
"address":{
"pipe": {
"path": "./etc/istio/proxy/XDS"
}
}
}
}]
}]
},
정리하자면, Istio의 모든 트래픽 제어는 Envoy가 담당하며, Istiod는 Envoy에게 설정을 동적으로 주입하는 컨트롤러 역할을 한다.
'Kubernetes > Istio' 카테고리의 다른 글
Istio 시리즈 # 6 – 메트릭과 트레이싱으로 살펴보는 Istio Observability (1) | 2025.05.04 |
---|---|
Istio 시리즈 # 5 – 네트워크 복원력 강화하기(Resilience) (1) | 2025.04.27 |
Istio 시리즈 # 4 – 세밀하게 트래픽 제어하기(Traffic Control) (0) | 2025.04.27 |
Istio 시리즈 # 3 – 외부 트래픽 진입점, Ingress Gateway 알아보기 (0) | 2025.04.20 |
Istio 시리즈 # 1 - 설치부터 기본 트레픽 제어까지 (0) | 2025.04.13 |