Linkerd로 분산 추적하기
Linkerd로 분산 추적하기 (Distributed tracing with Linkerd)
실제 환경에서 분산 추적을 사용하는 것은 복잡할 수 있어요. Linkerd는 이런 문제 중 일부를 해결할 수 있지만 만병통치약은 아니에요. 서비스 메시가 분산 추적에 어떻게 도움이 되는지에 대한 높은 수준의 설명은 Distributed tracing in the service mesh: four myths 문서를 참고하세요.
이 가이드는 emojivoto 예제 애플리케이션에 대해 추적을 구성하고 활성화하는 과정을 안내해요. 맨 끝으로 건너뛰면 Linkerd와 함께 분산 추적을 활용하는 가장 좋은 방법에 대한 몇 가지 권장사항을 볼 수 있어요.
분산 추적을 사용하려면 다음이 필요해요:
- 클러스터에 추적 수집기(collector)와 뷰어(viewer) 설치
- 추적을 활성화하도록 Linkerd 업데이트
- 스팬(span)을 방출하도록 애플리케이션 수정
emojivoto의 경우 이 모든 단계가 완료되면 다음과 같은 토폴로지가 만들어져요: Topology
경고
Linkerd 2.19부터 Linkerd-jaeger 확장은 더 이상 사용되지 않으며(deprecated) 더 이상 제공되지 않아요. 이 가이드 대신 이 확장 없이 Jaeger를 사용해 현대적인 분산 추적 인프라를 구축하는 방법을 설명해요. Linkerd-jaeger 확장에서 마이그레이션하는 가이드를 참고하세요.
본문
추적 수집기 설치하기
분산 추적 환경 구축의 첫 단계는 추적을 수집·저장·조회하는 방법을 설치하는 것이에요. 수집기는 메시와 애플리케이션에서 방출된 스팬을 소비해서 뷰어로 보내며, 뷰어는 이를 저장하고 조회용 대시보드를 제공해요.
이를 위한 일반적인 도구 중 하나가 Jaeger인데, 올인원(all-in-one) 설치에 수집기, 저장소, 추적 뷰어가 모두 포함돼 있어요. 우리 예제에서는 이것을 사용할 거예요.
Helm으로 Jaeger를 설치하려면 먼저 Jaeger Helm 레포지토리를 추가하세요:
`helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
`
그런 다음 Jaeger Helm 차트를 설치하세요:
`kubectl create ns jaeger-system
kubectl annotate ns jaeger-system linkerd.io/inject=enabled
helm install \
--wait \
--namespace jaeger-system \
--set allInOne.enabled=true \
--set storage.type=memory \
--set agent.enabled=false \
--set collector.enabled=false \
--set query.enabled=false \
--set provisionDataStore.cassandra=false \
jaeger jaegertracing/jaeger
`
경고
Jaeger 올인원 설치는 설정하고 실행하기는 매우 간단하지만 프로덕션 배포에는 적합하지 않아요. 어떤 추적 설치가 여러분의 환경에 적합한지 판단하는 것은 이 문서의 범위를 벗어나요.
추적을 활성화하도록 Linkerd 업데이트하기
추적 내보내기를 활성화하고 그 추적을 보낼 위치를 정의하려면 Linkerd 설치에 설정해야 할 값이 몇 가지 있어요. 이 경우 방금 설치한 Jaeger 수집기로 추적을 보내도록 Linkerd를 구성할 거예요.
Linkerd를 CLI로 설치했다면:
`linkerd upgrade \
--set proxy.tracing.enabled=true \
--set proxy.tracing.collector.endpoint=jaeger-collector.jaeger-system:4317 \
--set proxy.tracing.collector.meshIdentity.serviceAccountName=jaeger \
--set proxy.tracing.collector.meshIdentity.namespace=jaeger-system \
| kubectl apply -f -
`
또는 Linkerd를 Helm으로 설치했다면 Linkerd의 Helm values에 다음을 추가하세요:
`# values.yaml
proxy:
tracing:
enabled: true
collector:
endpoint: jaeger-collector.jaeger-system:4317
meshIdentity:
serviceAccountName: jaeger
namespace: jaeger-system
`
Linkerd는 OpenTelemetry 프로토콜을 지원하는 어떤 수집기로든 추적을 내보낼 수 있어요. 자세한 내용은 OpenTelemetry 문서를 참고하세요.
참고
현재 meshIdentity 단락은 필수예요. Linkerd는 메시 안에 있는 수집기에게만 추적을 내보낼 수 있어요.
Emojivoto 설치하기
emojivoto를 클러스터에 추가하고 Linkerd 프록시로 주입하세요:
`linkerd inject https://run.linkerd.io/emojivoto.yml | kubectl apply -f -
`
다음 단계로 넘어가기 전에 kubectl로 모든 것이 정상 실행되는지 확인하세요:
`kubectl -n emojivoto rollout status deploy/web
`
애플리케이션 수정하기
대부분의 서비스 메시 기능과 달리, 분산 추적은 기본 애플리케이션의 협력이 필요해요. 즉 인바운드 요청의 특정 헤더를 해당하는 아웃바운드 요청으로 전파(propagate)해야 해요.
이유는 분산 추적이 여러분의 애플리케이션으로 들어오는 요청과 종속 서비스로 나가는 요청을 서로 연결할 방법이 필요하기 때문이에요. 이를 위해 각 요청에 추적을 위한 고유 ID가 담긴 헤더를 추가해요. Linkerd는 이를 연결하기 위해 w3c 및 b3 두 포맷을 모두 전파해요.
참고
w3c와 b3 헤더가 모두 존재하면 Linkerd는 w3c 헤더만 전파해요.
우리는 이미 emojivoto를 수정해서 요청에 이 정보를 계측(instrument)해 뒀어요 (이 커밋 참고).
emojivoto에서 추적을 활성화하려면 다음을 실행하세요:
`kubectl -n emojivoto set env --all deploy OTEL_EXPORTER_OTLP_ENDPOINT=jaeger-collector.jaeger-system:4317
`
이 명령은 애플리케이션이 컨텍스트를 전파하고 스팬을 방출할 수 있게 하는 환경 변수를 추가해요. 그동안 Linkerd-Jaeger와 함께 설치된 수집기는 두 프로토콜을 계속 지원해요.
Jaeger 살펴보기
vote-bot이 모든 요청에 대해 추적을 시작하므로 이제 Jaeger에 스팬이 나타나기 시작할 거예요. UI로 가려면 다음을 실행하세요:
`kubectl port-forward -n jaeger-system svc/jaeger-query 16686
`
그런 다음 브라우저에서 http://127.0.0.1:16686 을 여세요. Jaeger 드롭다운에서 아무 서비스나 검색하고 Find Traces를 클릭하면 돼요. vote-bot이 시작하기 좋은 예시예요.
특정 추적을 클릭하면 모든 세부 정보가 제공되며, 모든 프록시의 스팬을 볼 수 있어요! 출력에서 linkerd-proxy 스팬이 많이 보이는 것을 주목하세요. 내부적으로 프록시는 서버 쪽과 클라이언트 쪽이 있어요. 요청이 프록시를 통과하면 서버가 수신하고 클라이언트가 발신해요. 메시에 포함된 두 파드 사이를 오가는 단일 요청에 대해 총 4개의 스팬이 생겨요. 요청이 해당 프록시를 통과할 때 소스 쪽에 2개, 원격 프록시가 요청을 수신할 때 목적지 쪽에 2개가 생겨요.
정리 (Cleanup)
정리하려면 emojivoto를 제거하고, Linkerd 추적을 끄고, 마지막으로 Jaeger를 제거하면 돼요:
`kubectl delete ns emojivoto
linkerd upgrade --set proxy.tracing=null | kubectl apply -f -
kubectl delete ns jaeger-system
`
참고 (Notes)
프록시 스팬이 보이지 않는다면
Linkerd 프록시는 b3 포맷도 지원하면서 w3c 포맷을 선호해요. Jaeger 같은 일부 클라이언트 라이브러리는 기본적으로 다른 포맷을 사용해요. 프록시가 추적에 참여하도록 클라이언트 라이브러리를 w3c 포맷으로 구성하는 걸 권장해요.
인그레스 (Ingress)
인그레스는 분산 추적에서 특히 중요한 컴포넌트인데, 보통 각 추적의 루트 스팬(root span)을 만들고 그 추적을 샘플링할지 여부를 결정하는 역할을 하기 때문이에요. 인그레스가 모든 샘플링 결정을 내리게 하면 추적 전체가 샘플링되거나 전혀 되지 않거나 둘 중 하나로 보장되어 "부분 추적(partial traces)"이 생기는 것을 피할 수 있어요.
이 참조 아키텍처는 각 추적의 루트 스팬을 만들기 위해 인그레스 대신 vote-bot이라는 트래픽 생성기를 사용해요.
클라이언트 라이브러리
애플리케이션이 추적 전파 헤더를 수동으로 전파하는 것도 가능하지만, 보통은 라이브러리를 사용하는 것이 훨씬 쉬워요. 일반적인 분산 추적 라이브러리는 세 가지 일을 해요:
- 인커밍 요청 헤더에서 아웃고잉 요청 헤더로 추적 컨텍스트를 전파
- 추적 컨텍스트 수정 (즉 새 스팬 시작)
- 이 데이터를 추적 수집기로 전송
예를 들어 OpenTelemetry 에이전트 익스포터는 gRPC API를 통해 OpenTelemetry 수집기로 추적 데이터를 내보내요. OpenTelemetry를 구성하는 세부 방법은 언어마다 다르지만, 많은 인기 언어에 대한 가이드가 있어요.
Jaeger vs 대안
이 가이드에서는 가장 널리 사용되는 추적 백엔드 중 하나인 Jaeger를 사용했어요. 하지만 OpenTelemetry가 지원하는 어떤 백엔드든 사용할 수 있어요.
프록시 헤더 전파 (Proxy header propagation)
애플리케이션이 Linkerd로 주입되면 Linkerd 프록시가 추적에 참여하고 추적 수집기에 추적 데이터도 방출해요. 이렇게 하면 추적 데이터가 풍부해지고, 요청이 프록시와 네트워크에서 보내는 시간이 정확히 얼마인지 볼 수 있어요.
Linkerd는 w3c 또는 b3 전파 포맷을 사용하는 추적에만 적극적으로 참여할 수 있지만, 알 수 없는 요청 헤더는 항상 투명하게 전달해요. 즉 다른 전파 포맷을 사용하는 추적을 방해하지 않아요.