LabHub

Istio 서비스 메시 · 관측성 · 이론

메트릭·액세스 로그·트레이스 — 프록시가 공짜로 주는 것과 아닌 것

LabHub 에서 이어서 보기

한 줄 요약

메시는 요청이 프록시를 지나는 김에 메트릭·액세스 로그·스팬을 만들어 준다. 다만 트레이스만은 애플리케이션이 헤더를 넘겨주지 않으면 끊긴다.

왜 이게 필요했나

관측성을 애플리케이션에서 챙기면 두 가지가 어긋난다. 첫째, 정의가 서비스마다 다르다. 어떤 팀은 5xx 만 오류로 세고 어떤 팀은 4xx 도 센다. 어떤 팀은 클라이언트 기준으로, 어떤 팀은 서버 기준으로 지연을 잰다. 대시보드를 나란히 놓아도 비교가 안 된다. 둘째, 계측되지 않은 서비스가 남는다. 급하게 만든 내부 도구, 인수한 팀의 레거시, 외주로 받은 컴포넌트에는 계측이 없고 그게 늘 장애의 사각지대다.

메시는 이 문제를 "요청이 어차피 프록시를 지나가니 거기서 재자"로 푼다. 표준 메트릭의 이름과 라벨이 모든 서비스에서 같아진다. 이 균일성이 계측을 새로 붙이는 것보다 훨씬 큰 가치다.

어떻게 동작하나

메트릭. 각 사이드카는 포트 15090 에서 프로메테우스 형식으로 통계를 노출한다. 핵심은 세 가지다.

| 메트릭 | 종류 | 쓰는 곳 |
| --- | --- | --- |
| istio_requests_total | 카운터 | 요청 수, 오류율 |
| istio_request_duration_milliseconds | 히스토그램 | p50/p99 지연 |
| istio_request_bytes / istio_response_bytes | 히스토그램 | 페이로드 크기 |

라벨 중에 특히 알아 둘 것이 셋이다. reportersource(보낸 쪽 프록시)와 destination(받은 쪽 프록시)으로 나뉘는데, 같은 요청이 양쪽에서 각각 기록되므로 둘을 합치면 두 배로 센다. response_flags 는 액세스 로그의 플래그와 같은 값이라 503 의 성격을 메트릭만으로도 구분할 수 있다. connection_security_policymutual_tls 또는 none 이고, STRICT 전환의 완료 기준이 바로 이 라벨이 none 인 요청 0건이다.

한 가지 함정은 카디널리티다. 라벨에 요청 경로나 사용자 ID 같은 값을 넣으면 시계열이 폭발한다. 커스텀 태그는 값의 종류가 유한한 것만 넣어야 한다.

아키텍처가 바뀐 역사도 알아 둘 만하다. 예전에는 Mixer 라는 별도 서비스가 요청마다 호출되어 메트릭을 모았고, 그게 지연과 장애의 원인이었다. 지금은 프록시 내부의 필터가 직접 만든다(Telemetry API v2). 그래서 관측성 때문에 요청 경로에 홉이 추가되는 일은 더 이상 없다.

액세스 로그. 프록시가 요청마다 한 줄을 남긴다. 사람이 읽어야 할 부분은 응답 코드와 그 옆의 플래그다.

| 플래그 | 의미 | 첫 번째로 볼 것 |
| --- | --- | --- |
| UH | 건강한 업스트림 없음 | subset 라벨과 파드 라벨 |
| UF | 업스트림 연결 실패 | 한쪽만 STRICT 인 mTLS 불일치 |
| UO | 연결 풀 초과 | 서킷 브레이커 한도 |
| NR | 라우트 없음 | catch-all 라우트 존재 여부 |
| URX | 재시도 소진 | 근본 원인은 다른 플래그와 함께 |
| UAEX | 외부 인가 거부 | CUSTOM 정책과 인가기 상태 |

전량 로깅은 비싸다. Telemetry 리소스의 필터로 response.code >= 400 같은 조건을 걸어 실패만 남기는 구성이 흔하다.

분산 트레이싱. 여기가 "공짜가 아닌" 부분이다. 프록시는 스팬을 만들고 타이밍을 재고 수집기로 보내는 일까지 해 준다. 그런데 인바운드 요청의 트레이스 헤더(B3 계열 또는 W3C traceparent)를 아웃바운드 요청에 복사하는 일은 애플리케이션이 해야 한다. 이걸 안 하면 서비스마다 별개의 트레이스가 만들어져 호출 사슬이 끊긴다. "메시를 깔았는데 트레이스가 한 홉짜리로만 보인다"의 답은 거의 언제나 이것이다.

샘플링 기본값은 1% 다. 첫 프록시가 샘플링 여부를 정하고 헤더로 전파하므로 뒤쪽은 그 결정을 따른다. 디버깅할 때만 올리고 상시로 100% 를 두지는 않는다.

시각화. Kiali 는 프로메테우스 메트릭으로 서비스 그래프를 그리고, 쿠버네티스 API 와 Istio 설정을 읽어 참조 무결성까지 검사한다. 즉 Kiali 의 설정 검증은 istioctl analyze 와 같은 종류의 일을 화면으로 보여 주는 것이다.

현장에서 만나는 모습

첫째, source 와 destination 을 섞어 세는 대시보드. 요청 수가 정확히 두 배로 나오면 십중팔구 reporter 필터를 빠뜨린 것이다. 클라이언트 관점이면 source, 서버 관점이면 destination 하나로 고정해야 한다.

둘째, 메시 메트릭이 앱 메트릭을 대체하지는 못한다. 프록시는 "요청이 200 을 냈다"까지만 안다. 응답 본문이 틀렸는지, 주문이 실제로 저장됐는지는 모른다. 메시 관측성은 인프라 계층의 균일한 바닥이고, 도메인 지표는 여전히 애플리케이션이 내야 한다.

셋째, 사이드카 없는 경로는 보이지 않는다. 메시 밖 크론이나 주입되지 않은 네임스페이스의 트래픽은 그래프에 아예 나타나지 않는다. 그래프가 깨끗하다는 것이 트래픽이 없다는 뜻은 아니다.

다음 확인에서 볼 것

이 모듈에는 실습이 없다. 정직하게 말하면, 이 실습 환경에는 실제로 트래픽을 나르는 Envoy 가 없기 때문이다. 사이드카가 붙은 파드가 Running 이 되어도 요청은 흐르지 않고, kubectl exec 도 포트포워딩도 없으니 15090 을 긁을 수도 15000 의 관리 API 를 두드릴 수도 없다. 메트릭이 없으니 프로메테우스 질의도, 트레이스도, 액세스 로그도 만들어 낼 수 없다.

없는 것을 있는 척 채점하는 실습을 만드는 것보다, 무엇이 자동으로 생기고 무엇이 여전히 사람 몫인지를 정확히 아는 편이 현업에서 훨씬 쓸모 있다. 대신 앞의 네 실습에서 이미 관측성의 절반을 다뤘다는 점을 짚어 두고 싶다. istioctl analyze 로 설정의 참조 무결성을 검사한 것, 라우트 순서를 JSON 으로 정리한 것, subset 라벨과 파드 라벨의 불일치를 잡아낸 것은 전부 Kiali 의 설정 검증 화면이 하는 일과 같은 종류다. 실제 클러스터를 만나면 여기에 프로메테우스·Grafana·Jaeger·Kiali 를 붙여 나머지 절반을 채우면 된다. 이어지는 퀴즈로 그 나머지 절반의 지도를 확인하자.