Telemetry APIで信号を設計する
한국어 원문으로 표시합니다.
목표
프록시가 만들어 주는 신호를 설정으로 다듬는 법을 익힙니다. 메시 전체에 기본 로그를 깔고, 실패만 남기는 조건을 걸고, 워크로드 하나에 샘플링과 태그를 붙이고, 카디널리티를 폭발시키는 태그를 배포 전에 거르는 데까지 갑니다.
왜 중요한가
메시가 파는 것은 균일함입니다. 계측이 없는 서비스에도 같은 이름과 같은 라벨의 메트릭이 생기고, 그 균일함이 대시보드를 비교 가능하게 만듭니다. 그런데 기본값 그대로 두면 두 가지가 문제가 됩니다. 액세스 로그는 요청마다 한 줄이라 트래픽이 많은 서비스에서 저장 비용이 금방 커지고, 커스텀 태그를 잘못 넣으면 시계열이 라벨 값의 종류만큼 늘어나 저장소와 질의가 함께 무너집니다.
Telemetry API 는 그 조정을 선언으로 하게 해 줍니다. 범위가 세 층이라는 점이
핵심입니다. 설치 네임스페이스에 셀렉터 없이 두면 메시 전체, 일반 네임스페이스에
셀렉터 없이 두면 그 네임스페이스, selector 를 붙이면 그 워크로드입니다. 그리고
셀렉터 없는 것은 네임스페이스마다 하나뿐이어야 합니다. 둘 이상이면 어느 것이
이기는지 정의되지 않기 때문입니다.
환경
이 파드에는 진짜 istiod 도 사이드카도 없습니다. 요청이 흐르지 않으니 메트릭도
로그도 만들어지지 않습니다. 대신 Telemetry CRD 가 등록된 진짜 apiserver 와
istioctl 이 있어서, 설정이 유효한가와 범위가 올바른가는 그대로
검증됩니다. 그 둘이 현장에서 사람을 잡는 자리이기도 합니다. 작업 디렉터리는
/root/istio-obs 이고 그 아래 k8s/·reject/·bin/·out/ 을 씁니다.
단계
mesh-obs를 만들고istio-system에 메시 기본 액세스 로그를 깝니다.mesh-obs에 실패만 남기는 로그 필터를 겁니다.app=reviews에 샘플링 10% 와 리터럴 태그를 걸고, 범위를 벗어난 값이 막히는 것을 봅니다.app=ratings에 메트릭 조정을 겁니다.bin/tag-lint.sh로 위험한 태그를 배포 전에 거릅니다.- 워크로드 둘을 만들고
istioctl analyze로 범위 규칙을 확인합니다. out/effective.txt에 한 파드에 실제로 걸리는 것을 계산해 적습니다.out/summary.txt에 여섯 줄로 정리합니다.
참고
- 셀렉터 없는 Telemetry 는 네임스페이스마다 하나뿐입니다. 3단계와 4단계에는 반드시 셀렉터를 붙이세요. 빠뜨리면 6단계에서 드러납니다.
- 셀렉터는 Deployment 이름이 아니라 파드 라벨을 봅니다.
- 3단계의 거절당할 파일은
k8s/가 아니라reject/에 두세요. 마지막 단계에서k8s/의 파일이 모두 유효해야 합니다. - 태그 값은 CEL 식입니다. 상수 문자열을 넣으려면 작은따옴표로 감싸야 합니다.
메시 전체에 기본 액세스 로그를 깐다
mesh-obs 네임스페이스를 만들어 istio-injection=enabled 라벨을 붙이고, /root/istio-obs/k8s/mesh-default.yaml 로 istio-system 에 Telemetry mesh-default 를 만드세요. 셀렉터 없이 accessLogging 제공자만 지정합니다.
Telemetry 의 범위는 세 층입니다. istio-system(설치 네임스페이스)에 셀렉터 없이 두면 메시 전체, 일반 네임스페이스에 셀렉터 없이 두면 그 네임스페이스, selector 를 붙이면 그 워크로드입니다. 셀렉터가 없다는 사실 자체가 범위를 정한다는 점이 이 API 의 핵심입니다. 제공자 이름은 메시 설정에 등록된 이름을 가리키는 문자열이라, 여기서는 실제로 존재하지 않아도 형식은 유효합니다.
실패한 요청만 로그로 남긴다
/root/istio-obs/k8s/failures-only.yaml 로 mesh-obs 에 Telemetry failures-only 를 만드세요. 셀렉터는 두지 말고, accessLogging 에 응답 코드가 400 이상일 때만 남기는 filter.expression 을 거세요.
전량 로깅은 비쌉니다. 프록시가 요청마다 한 줄을 남기니 트래픽이 많은 서비스에서는 저장 비용이 금방 커집니다. 필터는 CEL 식이고, 액세스 로그 문맥에서 response.code 를 쓸 수 있습니다. 이 Telemetry 는 네임스페이스 전체에 거는 것이므로 셀렉터를 붙이면 안 됩니다. 그리고 셀렉터 없는 Telemetry 는 네임스페이스마다 하나뿐 이어야 하니, 뒤 단계의 것들에는 반드시 셀렉터를 붙이세요.
샘플링 비율과 커스텀 태그를 워크로드에 건다
/root/istio-obs/k8s/trace-sampling.yaml 로 mesh-obs 에 Telemetry trace-sampling 을 만드세요. selector.matchLabels.app 은 reviews, tracing[0].randomSamplingPercentage 는 10, 그리고 customTags 에 리터럴 값을 가진 태그를 하나 두세요. 그다음 /root/istio-obs/reject/bad-sampling.yaml 에 범위를 벗어난 샘플링 값을 적어 적용을 시도하고, 거절 메시지를 /root/istio-obs/out/rejected.txt 에 저장하세요.
샘플링 기본값은 1% 입니다. 첫 프록시가 샘플링 여부를 정하고 헤더로 전파하므로 뒤쪽 홉은 그 결정을 따릅니다. 디버깅할 때만 올리고 상시로 100% 를 두지는 않습니다. 커스텀 태그는 값의 종류가 유한한 것만 넣어야 하므로 여기서는 리터럴을 씁니다. 범위를 벗어난 값은 CRD 스키마가 막으므로 오브젝트가 아예 만들어지지 않습니다. 메시지는 표준 오류로 나가니 2>&1 로 받으세요.
표준 메트릭을 끄고 태그를 더한다
/root/istio-obs/k8s/metrics-tuning.yaml 로 mesh-obs 에 Telemetry metrics-tuning 을 만드세요. selector.matchLabels.app 은 ratings 이고, 제공자는 prometheus 입니다. overrides 로 REQUEST_SIZE 를 mode 를 지정해 끄고, 다른 항목에서 tagOverrides 로 리터럴 값을 가진 태그를 하나 더하세요.
메트릭은 끄는 것도 설정입니다. 쓰지 않는 히스토그램을 끄면 시계열이 줄어 저장과 질의가 모두 가벼워집니다. mode 는 CLIENT·SERVER·CLIENT_AND_SERVER 중에서 고르는데, 같은 요청이 양쪽 프록시에서 각각 기록되기 때문에 어느 쪽을 말하는지 정해야 합니다. 태그 값은 CEL 식이라 상수 문자열을 넣으려면 작은따옴표로 감싸야 합니다.
카디널리티를 폭발시키는 태그를 배포 전에 거른다
/root/istio-obs/bin/tag-lint.sh <Telemetry파일> 을 만드세요. tagOverrides 의 값이 요청 경로·요청 식별자·사용자 식별자·요청 헤더처럼 값의 종류가 무한에 가까운 것을 가리키면 HIGH_CARDINALITY=<태그이름>=<값> 을 찍고 종료 코드 1로 끝냅니다. 상수 문자열만 쓰는 파일은 OK 를 찍고 0으로 끝냅니다.
시계열 수는 라벨 값 조합의 곱으로 늘어납니다. 사용자 식별자처럼 값이 무한에 가까운 것을 태그로 쓰면 저장소와 질의가 함께 무너지고, 프록시가 알아서 해시하거나 샘플링을 낮춰 주는 보호 장치는 없습니다. CEL 값이 작은따옴표로 감싼 상수면 안전하고, request.url_path 나 request.headers[...] 같은 것을 가리키면 위험합니다. 채점기가 안전한 파일과 위험한 파일로 이 검사기를 실제로 돌려 보고, 4단계에서 만든 파일에도 걸리지 않는지 함께 확인합니다.
범위 규칙을 정적 분석으로 확인한다
/root/istio-obs/k8s/workloads.yaml 로 mesh-obs 에 Deployment reviews 와 ratings 를 만드세요. 파드 라벨의 app 이 각각 이름과 같아야 합니다. 그다음 istioctl analyze -n mesh-obs 가 오류 없이 끝나는지 확인하세요.
셀렉터는 Deployment 이름이 아니라 파드 라벨을 봅니다. 그래서 파드 템플릿의 라벨을 정확히 맞춰야 합니다. 그리고 셀렉터 없는 Telemetry 가 한 네임스페이스에 둘 이상이면 어느 것이 이기는지 정의되지 않아, istioctl analyze 가 오류로 잡습니다. 앞 단계에서 셀렉터를 빠뜨렸다면 여기서 드러납니다. 이 파드에는 진짜 사이드카가 없으므로 주입 관련 경고는 남지만, 오류가 없으면 통과입니다.
한 파드에 실제로 걸리는 것을 계산한다
app=reviews 파드에 어떤 Telemetry 가 걸리는지 계산해 /root/istio-obs/out/effective.txt 에 다섯 줄로 적으세요. MESH, NAMESPACE, WORKLOAD, TRACING_PERCENT, METRICS_APPLIES 입니다.
세 층이 겹쳐 걸립니다. 메시 범위 하나, 네임스페이스 범위 하나, 그리고 그 파드를 고르는 워크로드 범위 하나입니다. 앞의 셋은 이름을 적고, TRACING_PERCENT 는 워크로드 범위에 적힌 샘플링 값을 적습니다. 마지막 줄은 4단계의 메트릭 설정이 이 파드에도 걸리는지에 대한 답을 yes 나 no 로 적으세요. 셀렉터가 어느 앱을 고르고 있었는지 다시 보면 됩니다. 이름은 짐작하지 말고 kubectl get telemetry -A 로 확인해 적으세요.
만든 것을 세고 모두 유효한지 확인한다
/root/istio-obs/k8s 의 파일이 모두 istioctl validate 를 통과하는지 확인하고, /root/istio-obs/out/summary.txt 에 여섯 줄로 정리하세요. TELEMETRY_TOTAL, MESH_SCOPED, NAMESPACE_SCOPED, WORKLOAD_SCOPED, SAMPLING_PERCENT, TRACE_HEADER_PROPAGATION 입니다.
앞의 다섯 줄은 클러스터에서 세어 적습니다. 마지막 줄은 이 코스에서 가장 자주 사람을 잡는 사실에 대한 답입니다. 프록시는 스팬을 만들고 타이밍을 재고 수집기로 보내는 일까지 해 주지만, 인바운드 요청의 트레이스 헤더를 아웃바운드 요청에 복사하는 일은 누가 해야 하는지를 한 단어로 적으세요. 그것을 안 하면 서비스마다 별개의 트레이스가 만들어져 호출 사슬이 끊깁니다.