Envoy 내부 구조 · 요청이 지나가는 줄 · 실습
코드를 고치지 않고 장애를 만들어 본다
목표
HTTP 필터 사슬에 장애 주입과 속도 제한을 끼워 보고, 순서와 조건과 비율이 결과를 어떻게 바꾸는지 직접 확인한다.
왜 중요한가
필터는 애플리케이션을 건드리지 않고 그 앞에서 무엇인가를 하는 자리다. 그래서 '결제가 느려지면 우리는 어떻게 되나' 같은 질문에 추론 대신 실측으로 답할 수 있다. 다만 이 도구는 잘못 쓰면 그 자체가 장애가 된다 — 조건 없이 켠 장애 주입, 프록시 대수를 빠뜨린 속도 제한 한도, 순서가 뒤집힌 사슬이 전부 실제로 사고가 났던 모양이다. 한 번 손으로 만들어 두면 그 셋을 설정만 보고도 알아본다.
단계
1. 업스트림을 8095 에 ok 로 띄우세요. /root/envd-filter/f-ok.yaml 에 필터가 router 하나뿐인 설정을 두고(관리 9976, 리스너 127.0.0.1:10076, 클러스터 origin), /root/envd-filter/f-badorder.yaml 에는 router 뒤에 fault 필터를 둔 설정을 두세요. 두 파일을 각각 envoy --mode validate 로 검사해 /root/envd-filter/01-order.txt 에 ok_rc= 와 bad_rc= 두 줄을 적으세요.
2. /root/envd-filter/f-abort.yaml 을 만드세요 — router 앞에 fault 필터를 두고 abort 로 418 을, 조건은 요청 헤더 x-fault: yes 입니다. 띄운 뒤 헤더를 붙인 요청과 붙이지 않은 요청을 각각 보내 /root/envd-filter/02-abort.txt 에 with= 와 without= 두 줄(각각의 HTTP 코드)을 적으세요.
3. /root/envd-filter/f-delay.yaml 을 만드세요 — fault 필터의 delay.fixed_delay 를 2초로 두고 조건은 헤더 x-slow: yes 입니다. 띄운 뒤 헤더를 붙인 요청과 붙이지 않은 요청의 소요 시간을 재어 /root/envd-filter/03-delay.txt 에 slow_ms=·fast_ms=·gap_ms= 세 줄을 적으세요(밀리초 정수, gap_ms 는 두 값의 차).
4. /root/envd-filter/f-half.yaml 을 만드세요 — 조건 없이 abort 로 503 을 주되 percentage 를 50%로 둡니다. 띄운 뒤 20번 요청해 /root/envd-filter/04-percentage.txt 에 total=20, aborted=(503 을 받은 횟수), passed=(200 을 받은 횟수) 세 줄을 적으세요.
5. /root/envd-filter/f-lrl.yaml 을 만드세요 — fault 대신 local_ratelimit 필터를 router 앞에 두고, stat_prefix 는 lrl, 토큰은 max_tokens 3 · tokens_per_fill 3 · fill_interval 300s 이며 켜짐과 강제 모두 100% 입니다. 띄운 뒤 6번 요청해 /root/envd-filter/05-ratelimit.txt 에 ok=·limited=·codes= 세 줄을 적으세요(codes 는 받은 코드들을 공백으로).
6. /root/envd-filter/f-perroute.yaml 을 만드세요 — 전역 local_ratelimit 은 filter_enabled 를 0% 로 두어 꺼 두고, 라우트 /tight 에는 typed_per_filter_config 로 토큰 1개(stat_prefix: tight), /loose 에는 토큰 5개(stat_prefix: loose) 를 줍니다. 띄운 뒤 /tight 로 3번, /loose 로 3번 요청해 /root/envd-filter/06-perroute.txt 에 tight_ok=·tight_limited=·loose_ok=·loose_limited= 네 줄을 적으세요.
7. 지금 떠 있는 Envoy 의 /stats 에서 속도 제한 관련 통계를 뽑아 /root/envd-filter/07-stats.txt 에 tight_rate_limited=·loose_rate_limited=·enabled_total= 세 줄을 적으세요(앞 둘은 각 stat_prefix 의 rate_limited 값, 마지막은 두 stat_prefix 의 enabled 값을 더한 수).
8. /root/envd-filter/08-report.md 에 router_last=(종단 필터가 마지막이어야 하면 yes), abort_status=(2단계에서 받은 코드), delay_ms=(3단계의 gap_ms), tight_allowed=(6단계에서 /tight 가 통과시킨 횟수) 네 줄을 적고, 그 아래 배운 것을 네 줄 이상 적으세요.
참고
- Envoy 를 띄울 때는
setsid --fork nohup envoy -c <파일> --log-level warn --concurrency 1 > <로그> 2>&1 </dev/null를 쓰고, 다시 띄우기 전에는pkill -x envoy로 정리하세요. - 기동은 고정
sleep이 아니라/ready가 LIVE 를 돌려줄 때까지 도는 루프로 기다립니다. - 상태 코드만 받으려면
curl -s -o /dev/null -w '%{http_code}', 소요 시간은-w '%{time_total}'을 씁니다. 시간은 초 단위 소수라 밀리초로 바꾸려면 곱해야 합니다. - 업스트림은
python3 /opt/lab/envoy/upstream.py <포트> ok로 띄웁니다. - 흔한 실수 —
router를 사슬 맨 앞이나 중간에 두는 것. 그 뒤의 필터는 영원히 실행되지 않으므로 Envoy 가 설정을 통째로 거절합니다. - 흔한 실수 —
fill_interval을 짧게 두는 것. 실습 중에 토큰이 다시 차올라 결과가 흔들립니다.
단계 8개
- 사슬의 마지막은 정해져 있다
- 조건이 맞는 요청만 끊는다
- 끊는 대신 느리게 만든다
- 일부만 골라 끊는다
- 프록시 안에서 토큰을 센다
- 같은 필터를 라우트마다 다르게 설정한다
- 필터가 남기는 숫자를 읽는다
- 필터 설계 메모를 남긴다