Envoy 내부 구조 · 두 번 고른다 — 가상 호스트와 라우트 · 실습
가상 호스트 넷과 매치 다섯 가지를 갈라 본다
목표
Host 헤더로 가상 호스트가 먼저 정해지는 것을 확인하고, 매치의 종류와 목적지의 종류를 하나씩 붙여 가며 같은 요청이 어디로 가는지 본다.
왜 중요한가
라우팅 설정은 사람이 읽기에는 '규칙 목록' 처럼 보이지만 실제로는 두 단계의 선택이다. 그리고 두 단계가 서로 다른 규칙으로 돌아간다 — 앞은 구체성, 뒤는 순서. 이 차이를 모르면 규칙을 위아래로 옮기며 시간을 버리게 된다. 여기에 더해 weighted_clusters 가 보장이 아니라 확률이라는 것, direct_response 로 앱을 건드리지 않고 끝낼 수 있다는 것, 헤더가 세 층에서 각각 더해진다는 것까지 손으로 확인해 두면 남이 쓴 라우트 표도 몇 분이면 읽힌다.
단계
1. /root/envd-route/route.yaml 에 가상 호스트 네 개를 두세요 — exact(shop.envd.test), suffix(*.envd.test), prefixw(shop.*), anyhost(*). 각각 / 에서 vh=exact·vh=suffix·vh=prefixw·vh=any 를 돌려줍니다(관리 9931, 리스너 127.0.0.1:10031). 띄운 뒤 네 가지 Host 헤더로 /zzz 를 요청해 /root/envd-route/01-vhosts.txt 에 exact=·suffix=·prefixw=·any= 네 줄로 결과를 적으세요(요청한 Host 는 차례로 shop.envd.test, www.envd.test, shop.other.test, nowhere.example 입니다).
2. /root/envd-route/route.yaml 을 /root/envd-route/route-dup.yaml 로 복사한 뒤 domains: ["*"] 인 가상 호스트를 하나 더 만드세요(이름은 겹치지 않게). envoy --mode validate 로 검사해 출력과 종료 코드를 /root/envd-route/02-onestar.txt 에 저장하세요(마지막 줄은 rc=1).
3. exact 가상 호스트의 / 라우트 위에 두 라우트를 더하세요 — path: "/exact" 는 m=path 를, safe_regex 로 ^/id/[0-9]+$ 는 m=regex 를 돌려줍니다. /root/envd-route/03-match.txt 에 path=(/exact 요청), regex=(/id/42 요청), regex_miss=(/id/abc 요청) 세 줄을 적으세요. Host 는 모두 shop.envd.test 입니다.
4. /api 로 가는 라우트를 두 개 더하세요(정규식 라우트 아래, / 라우트 위). 하나는 headers 조건으로 x-canary: yes 일 때 m=header 를, 다른 하나는 query_parameters 조건으로 debug=1 일 때 m=query 를 돌려줍니다. /root/envd-route/04-cond.txt 에 header=, query=, plain=(조건 없이 /api 만) 세 줄을 적으세요.
5. 업스트림 둘을 띄우고(8082, 8083) 클러스터 blue·green 을 만든 뒤, /split 라우트가 weighted_clusters 로 75 대 25 로 나눠 보내게 하세요. --concurrency 1 로 띄우고 40번 요청해 /root/envd-route/05-weighted.txt 에 blue=·green=·total= 세 줄(각 업스트림이 받은 횟수와 합)을 적으세요.
6. 두 라우트를 더하세요 — path: "/healthz" 는 direct_response 로 200 과 alive 를, prefix: "/old" 는 redirect 로 /new 로 301 을 보냅니다. /root/envd-route/06-direct.txt 에 health=(응답 본문), redirect_code=(HTTP 코드), redirect_url=(Location 헤더 값) 세 줄을 적으세요.
7. 응답 헤더 x-level 을 세 층에 각각 더하세요 — 라우트에 route, 가상 호스트에 virtualhost, 라우트 표에 routeconfig. shop.envd.test 의 /zzz 로 요청해 돌아온 x-level 헤더를 모두 /root/envd-route/07-headers.txt 에 levels= 한 줄로 쉼표 없이 공백으로 이어 적고, count= 줄에 개수를 적으세요.
8. /root/envd-route/08-report.md 에 vhost_order=(가상 호스트 구체성 순서를 exact,suffix,prefix,star 형식으로), star_limit=(라우트 표 하나에 둘 수 있는 * 가상 호스트 수), blue_share=(5단계에서 blue 가 받은 비율, 백분율 정수), redirect_code=(6단계의 코드) 네 줄을 적고, 그 아래 배운 것을 네 줄 이상 적으세요.
참고
- Envoy 를 띄울 때는
setsid --fork nohup envoy -c <파일> --log-level warn --concurrency 1 > <로그> 2>&1 </dev/null를 쓰고, 다시 띄우기 전에는pkill -x envoy로 정리하세요. - 기동은 고정
sleep이 아니라/ready가 LIVE 를 돌려줄 때까지 도는 루프로 기다립니다. - 요청에 이름을 붙이려면
curl -H "Host: 이름"을 씁니다. 질의 문자열이 든 주소는 따옴표로 감싸야 셸이?를 삼키지 않습니다. - 업스트림 흉내용 서버는
python3 /opt/lab/envoy/upstream.py <포트> ok입니다. 응답 본문에 포트가 들어 있어 어느 쪽이 받았는지 셀 수 있습니다. - 흔한 실수 — 조건이 붙은 라우트를 넓은
prefix: "/"아래에 두면 영영 걸리지 않습니다. - 흔한 실수 —
--concurrency 1을 빼고 분배를 세면 숫자가 매번 달라집니다.
단계 8개
- 라우트 표보다 먼저 가상 호스트가 정해진다
- `*` 는 라우트 표 전체에 하나만 둘 수 있다
- 정확한 경로와 정규식으로 맞힌다
- 같은 경로를 헤더와 질의 문자열로 가른다
- 한 라우트가 두 클러스터로 나눠 보낸다
- 업스트림 없이 응답하고, 옛 경로를 옮겨 준다
- 헤더를 붙이는 자리가 세 군데다
- 라우팅 표를 읽는 규칙으로 정리한다