LabHub
배우기 러닝패스 코스

Envoy 내부 구조 · 두 번 고른다 — 가상 호스트와 라우트 · 이론

라우트를 썼는데 안 걸리는 이유

LabHub 에서 이어서 보기

한 줄 요약

요청 하나가 목적지를 찾기까지 두 번 고른다. 먼저 Host 헤더로 가상 호스트를 고르고, 그다음 그 가상 호스트의 라우트 표를 위에서부터 훑어 첫 매치를 쓴다. 앞의 선택은 구체성으로, 뒤의 선택은 순서로 정해진다 — 이 둘이 다르다는 것이 이 글의 전부다.

왜 이게 필요했나

"라우트를 분명히 썼는데 안 걸립니다" 라는 신고의 절반은 라우트 문제가 아니다. 가상 호스트를 잘못 고른 것이다.

라우트 표(route_config) 하나에는 가상 호스트가 여러 개 들어간다. 각 가상 호스트는 domains 목록을 갖고, 요청의 Host(HTTP/2 에서는 :authority) 헤더가 그중 하나에 맞아야 그 가상 호스트의 라우트 표를 본다. 여기서 맞히는 규칙이 라우트와 다르다. 라우트는 위에서부터 훑어 첫 매치를 쓰지만, 가상 호스트는 가장 구체적인 것을 쓴다.

1. 정확한 이름        www.foo.com2. 접미 와일드카드    *.foo.com   (더 긴 와일드카드가 먼저)3. 접두 와일드카드    foo.*4. 특별한 *          아무 이름에나

그래서 *.example.com 가상 호스트를 파일 맨 위에 올려도 www.example.com 을 정확히 적은 가상 호스트가 이긴다. 순서를 바꿔 가며 하루를 보내지 않으려면 이 차이를 먼저 알아야 한다.

* 는 라우트 표 전체에 딱 하나만 둘 수 있다. 두 개면 누가 더 구체적인지 정할 방법이 없으므로 Envoy 는 실행 중에 헷갈리게 두는 대신 설정을 읽는 시점에 거절한다.

어떻게 동작하나

가상 호스트가 정해지면 그 안의 routes위에서부터 본다. 첫 매치에서 멈춘다. 매치에 쓸 수 있는 것은 경로만이 아니다.

| 조건 | 무엇 |
| --- | --- |
| prefix | 경로의 앞이 같으면 |
| path | 경로가 통째로 같아야 |
| safe_regex | 정규식에 맞으면 |
| headers | 헤더 값 조건(정확·존재·접두·정규식) |
| query_parameters | 질의 문자열 조건 |

한 매치 안의 조건은 전부 만족해야 한다. 그러니 "내부 테스터만 새 버전으로" 같은 요구는 prefixheaders 를 함께 적어 만든다. 조건이 맞지 않으면 그 라우트를 건너뛰고 아래로 계속 내려간다. 404 가 나오는 것이 아니라 다음 라우트가 받는다 — 그래서 조건이 붙은 좁은 라우트를 위에, 넓은 prefix: "/" 를 맨 아래에 둔다.

목적지도 클러스터 하나만은 아니다.

헤더를 더하는 자리는 세 군데다 — 라우트, 가상 호스트, 라우트 표. 덮어쓰는 것이 아니라 각각 더해진다. 그래서 같은 이름의 응답 헤더가 여러 개 남을 수 있다.

현장에서 만나는 모습

가중치가 비율대로 안 나온다는 신고. weighted_clusters 는 확률이지 배분표가 아니다. 게다가 Envoy 의 워커 스레드는 각자 상태를 들고 있어서, 기본 concurrency(코어 수)에서 요청 마흔 번을 세면 매번 다르게 나온다. 카나리 비율을 검증할 때는 표본을 충분히 키우거나 워커를 하나로 줄여야 한다. 운영에서는 "비율이 안 맞는다" 대신 통계로 본다.

direct_response 로 앱을 건드리지 않고 끝내는 일. 헬스 체크 경로, 점검 안내, 봇 차단 응답처럼 애플리케이션이 알 필요 없는 것들은 프록시에서 끝내는 편이 낫다. 배포 없이 고칠 수 있고, 앱이 죽어 있어도 답한다.

정규식을 남발했다가 느려지는 경우. prefixpath 는 문자열 비교지만 safe_regex 는 정규식 엔진을 탄다. 라우트가 수백 개인 표에서 앞쪽을 전부 정규식으로 채우면 요청마다 그것을 다 돌린다. 정규식은 다른 수로 안 되는 자리에만 쓴다.

공식 문서: [HTTP routing](https://www.envoyproxy.io/docs/envoy/v1.38.3/intro/arch_overview/http/http_routing) · [HTTP route components](https://www.envoyproxy.io/docs/envoy/v1.38.3/api-v3/config/route/v3/route_components.proto)

다음 실습에서 할 것

가상 호스트 네 개를 두고 구체성 순서를 직접 확인한 뒤, * 를 두 개 두면 설정이 거절되는 것을 본다. 그다음 path · safe_regex · headers · query_parameters 로 갈라 보내고, 가중치 75 대 25 를 마흔 번 요청으로 세어 보고, direct_responseredirect 를 붙이고, 헤더가 세 층에서 각각 더해지는 것을 확인한다.