블로그 | NGINX

OpenTelemetry를 최신 앱 참조 아키텍처에 통합하기 – 진행 보고서

NGINX-F5-수평-검정-유형-RGB의 일부
엘리야 주판치치 썸네일
엘리야 주판치치
2022년 3월 8일 게시
제이슨 슈미트 썸네일
제이슨 슈미트
2022년 3월 8일 게시

작년 가을 Sprint 2.0에서 NGINX Modern Apps Reference Architecture(MARA) 프로젝트를 소개했을 때, 우리는 이것이 일부 아키텍처와 같은 "장난감"이 아니라 "견고하고, 테스트를 거쳐 Kubernetes 환경에서 실행되는 라이브 프로덕션 애플리케이션에 배포할 준비가 된" 솔루션이 되어야 한다는 의도를 강조했습니다. 이러한 프로젝트에는 관찰 툴이 절대적으로 필요합니다. MARA팀의 모든 구성원은 상태 및 성능에 대한 통찰력이 부족하여 애플리케이션 개발 및 제공이 좌절스러운 작업으로 이어지는 것을 직접 경험했습니다. 우리는 MARA에 프로덕션 환경에서 디버깅 및 추적을 위한 계측기를 포함해야 한다는 데 즉시 합의했습니다.

MARA의 또 다른 지침 원칙은 오픈 소스 솔루션을 선호한다는 것입니다. 이 게시물에서는 다기능 오픈소스 관찰 도구에 대한 우리의 검색이 어떻게 OpenTelemetry 로 이어졌는지 설명하고, Python, Java, NGINX로 구축된 마이크로서비스 애플리케이션과 OpenTelemetry를 통합하는 데 사용한 절충안, 설계 결정, 기법 및 기술에 대해 자세히 설명합니다.

당사의 경험에 대한 이야기를 들으시면 여러분이 잠재적인 함정을 피하고 OpenTelemetry 도입을 가속화하는 데 도움이 될 것입니다. 이 게시물은 시간에 민감한 진행 상황 보고서라는 점을 참고해 주십시오. 우리가 논의하는 기술은 1년 안에 성숙될 것으로 예상합니다. 게다가 우리는 현재 일부 프로젝트의 단점을 지적하지만, 오픈소스로 진행되고 있는 모든 작업에 대해 매우 감사하게 생각하며 그 진전을 지켜보고 싶습니다.

우리의 응용 프로그램

관찰 솔루션과 통합할 애플리케이션으로, 우리는 Google의 Bank of Anthos 샘플 앱에서 파생된 Bank of Sirius 를 선택했습니다. 이는 인프라를 코드로 배포할 수 있는 마이크로서비스 아키텍처를 갖춘 웹앱입니다. 이 애플리케이션은 성능과 안정성 측면에서 개선될 수 있는 방법이 많지만, 브라운필드 애플리케이션으로 간주될 만큼 성숙 단계에 접어들었습니다. 따라서 이는 OpenTelemetry를 애플리케이션에 통합하는 방법을 보여주는 좋은 예라고 생각합니다. 이론상 분산 추적은 애플리케이션 아키텍처의 단점에 대한 귀중한 통찰력을 제공하기 때문입니다.

다이어그램에서 볼 수 있듯이, 애플리케이션을 지원하는 서비스는 비교적 간단합니다.

이미지는 Google 에서 제공

우리가 OpenTelemetry를 선택한 이유

OpenTelemetry를 선택하게 된 과정은 매우 복잡했고 여러 단계로 이루어졌습니다.

기능 위시리스트 만들기

사용 가능한 오픈소스 관찰 도구 자체를 평가하기에 앞서, 우리는 관찰성의 어떤 측면이 중요한지 파악했습니다. 우리는 과거의 경험을 토대로 다음과 같은 목록을 작성했습니다.

  • 로깅 - 우리가 사용하는 용어에 따르면 이는 애플리케이션에서 줄바꿈으로 구분된 클래식 메시지 세트를 생성하는 것을 의미합니다. Bank of Sirius 앱은 Bunyan 형식 으로 로그를 구조화합니다.
  • 분산 추적 – APM( 애플리케이션 성능 관리 ) 공급업체가 제공하는 것과 같은 전체 애플리케이션 내의 각 구성 요소에 대한 타이밍 및 메타데이터
  • 메트릭 – 일정 기간 동안 수집된 측정값을 시계열 데이터로 그래프화한 것
  • 예외/오류 집계 및 알림 – 가장 일반적인 예외 및 오류의 집계된 컬렉션으로, 어떤 애플리케이션 오류가 가장 일반적인지 확인할 수 있도록 검색이 가능해야 합니다.
  • 상태 점검 – 애플리케이션 내에서 서비스가 올바르게 기능하고 있는지 확인하기 위해 주기적으로 서비스에 프로브를 전송합니다.
  • 런타임 상태 내성 – 애플리케이션의 런타임 상태에 대한 정보를 반환하는 관리자에게만 표시되는 API 세트
  • 힙/코어 덤프 - 서비스 런타임 상태의 포괄적인 스냅샷. 우리 목적에 중요한 요소는 이러한 덤프를 요구 시 또는 서비스가 충돌할 때 얼마나 쉽게 얻을 수 있는지입니다.

위시리스트와 도구 기능 비교

물론, 우리는 이 모든 기능을 포함하는 단일 오픈소스 도구나 접근 방식을 기대하지는 않았지만, 적어도 사용 가능한 도구를 비교할 수 있는 대략적인 기준은 제공했습니다. 우리는 우리의 위시리스트에 있는 7가지 기능 중 어떤 기능을 지원하는지 알아보기 위해 각 도구의 설명서를 참조했습니다. 다음 표는 우리의 연구 결과를 요약한 것입니다.

기술 벌채 반출 분산 추적 메트릭 오류 집계 건강 검진 런타임 내성 힙/코어 덤프
ELK + 탄력적 APM
그라파나
그레이로그
저격병
오픈센서스
오픈 텔레메트리 베타 *
프로메테우스
통계D
지킨

* 확장 으로

이 테이블을 만드는 것은 불쾌한 깨달음이었습니다. 다양한 도구는 기능과 의도된 목적이 너무 다르기 때문에 이를 모두 같은 범주에 속한다고 볼 수 없습니다. 마치 사과와 토스터를 비교하는 것과 같습니다!

예를 들어, ELK ( Elasticsearch-Logstash-KibanaFilebeat )와 Zipkin은 근본적으로 다른 기능을 하기 때문에 이 둘을 비교하는 것은 무엇보다도 혼란스럽습니다. 불행히도 "미션 크립"은 상황을 더욱 흐리게 만들 뿐입니다. 의심할 여지 없이 사용자 요청에 따라 도구의 주요 목적과 무관한 기능이 추가되어 다른 도구와 중복이 발생합니다. 표면적으로 ELK는 로그 저장과 시각화를 담당하는 반면 Zipkin은 분산 추적을 담당합니다. 하지만 Elastic 제품 포트폴리오를 조금 더 자세히 살펴보면 분산 추적을 지원하고 Jaeger 와도 호환되는 Elastic APM을 빠르게 발견하게 됩니다.

임무 확장 문제를 넘어, 많은 도구를 서로 통합하여 수집기, 애그리게이터, 대시보드 등 다양한 조합을 만들어낼 수 있습니다. 일부 기술은 서로 호환되고, 일부 기술은 서로 호환되지 않습니다.

정성적 조사 수행

따라서 이 비교 표는 우리의 선택의 기준이 될 만큼 정확한 그림을 제공하지 못했습니다. 우리는 각 프로젝트의 목표, 지침 원칙, 그리고 가능한 미래 방향에 대한 정성적 조사를 해야 했습니다. 프로젝트의 가치가 우리의 가치와 유사할수록, 시간이 지나도 호환될 가능성이 높기 때문입니다. 프로젝트 페이지를 방문해 보니 OpenCensus 페이지에서 바로 이 사실을 발견했습니다.

OpenCensus와 OpenTracing이 합병되어 OpenCensus와 OpenTracing의 차기 주요 버전으로 OpenTelemetry가 탄생했습니다. OpenTelemetry는 기존 OpenCensus 통합과의 하위 호환성을 제공할 것이며, 2년 동안 기존 OpenCensus 라이브러리에 대한 보안 패치를 계속 제공할 것입니다.

그것은 우리가 보기에 중요한 데이터 포인트였습니다. 우리는 우리의 선택이 미래에도 통할 것이라는 보장은 없지만, 적어도 앞으로 커뮤니티의 든든한 지지를 받을 수 있을 것이라는 사실은 알고 싶었습니다. 이 정보를 바탕으로 우리는 후보 목록에서 OpenCensus를 삭제할 수 있었습니다. Jaeger를 사용하는 것도 좋은 생각이 아니었을 것입니다. 왜냐하면 Jaeger는 현재 공식적으로 사용이 중단된 OpenTracing 프로젝트에 대한 참조 구현이기 때문입니다. 새로운 기여의 대부분은 OpenTelemetry에 포함될 것입니다.

그리고 OpenTelemetry Collector 에 대해서도 알아보았습니다.

OpenTelemetry Collector는 원격 측정 데이터를 수신, 처리 및 내보내는 방법에 대해 공급업체에 독립적인 구현을 제공합니다. 또한 오픈소스 원격 측정 데이터 형식(예: Jaeger, Prometheus 등)을 여러 오픈소스 또는 상용 백엔드로 전송하기 위해 여러 에이전트/수집기를 실행, 운영 및 유지할 필요성이 없어집니다.

OpenTelemetry Collector는 다양한 백엔드를 사용하여 다양한 관찰 가능성 수집 및 계측 방법을 혼합하고 일치시킬 수 있는 집계기 역할을 합니다. 기본적으로, 우리 애플리케이션은 Zipkin을 통해 추적 정보를 수집하고 Prometheus를 통해 측정 항목을 수집한 다음 이를 구성 가능한 백엔드로 보내고 Grafana를 통해 시각화할 수 있습니다. 이 디자인에는 여러 가지 다른 변형이 가능하므로, 다양한 접근 방식을 시도해 보고 어떤 기술이 우리의 사용 사례에 적합한지 알아볼 수 있습니다.

OpenTelemetry를 미래로 통합

기본적으로, 우리가 OpenTelemetry Collector를 선택한 이유는 이론상 관찰 기술을 전환할 수 있기 때문입니다. 프로젝트가 상대적으로 미숙한 편이었음에도 불구하고, 우리는 과감하게 뛰어들어 오픈소스 통합을 통한 OpenTelemetry를 사용하기로 결정했습니다. 이 분야의 현황을 이해하는 유일한 방법은 기술을 사용하는 것이기 때문입니다.

하지만 OpenTelemetry Collector에는 일부 기능이 누락되어 있으므로 해당 기능을 사용하려면 다른 기술을 사용해야 합니다. 다음 섹션에서는 우리의 선택과 그 이유를 요약합니다.

로깅 구현

로깅은 관찰 가능성의 겉보기에 간단한 부분이지만, 복잡한 결정으로 빠르게 이어집니다. 컨테이너에서 로그 출력을 수집하기만 하면 되므로 간단하지만, 그런 다음 데이터를 저장할 위치, 해당 저장소로 전송하는 방법, 유용하게 만들기 위해 인덱싱하는 방법, 보관 기간 등을 결정해야 하므로 복잡합니다. 로그 파일이 유용하려면 다양한 검색자의 요구를 충족할 만큼 충분히 다양한 기준으로 쉽게 검색될 수 있어야 합니다.

저희는 OpenTelemetry Collector의 로깅 지원을 살펴보았고, 이 글을 쓸 당시에는 아직 베타 상태였습니다. 우리는 다른 옵션을 계속 조사하면서 단기적으로 로깅에 ELK를 사용하기로 결정했습니다.

그렇게 하지 않을 만한 확실한 이유가 없다면, 우리는 Elasticsearch 툴을 기본적으로 사용하여 배포를 수집, 조정, 마스터, 데이터 노드 로 분할할 수 있었습니다. 보다 쉬운 배포를 위해 Bitnami 차트를 사용했습니다. 데이터를 전송하기 위해 Kubernetes DaemonSet의 일부로 Filebeat를 배포했습니다. Kibana를 배포하고 미리 로드된 인덱스, 검색, 시각화 및 대시보드를 활용하여 검색 기능을 추가했습니다.

이 솔루션이 작동하기는 하지만 기본 구성은 리소스를 많이 소모하기 때문에 K3SMicrok8s 와 같이 리소스 사용량이 적은 환경에서 실행하기 어렵다는 점이 빠르게 드러났습니다. 각 구성 요소의 복제본 수를 조정하는 기능을 추가하면 이 문제는 해결되지만, 리소스 고갈이나 과도한 양의 데이터로 인해 발생할 수 있는 일부 오류가 발생하게 되었습니다.

우리는 이에 실망하기는커녕, 이를 다양한 구성으로 로깅 시스템을 벤치마킹하고 Grafana Loki , Graylog 와 같은 다른 옵션을 조사할 기회로 보고 있습니다. 우리는 가벼운 로깅 솔루션으로는 일부 사용자에게 필요한 모든 기능을 제공할 수 없고, 더 많은 리소스를 필요로 하는 도구에서 얻을 수 있는 기능도 제공하지 못한다는 사실을 깨닫게 될 것입니다. MARA 의 모듈형 특성을 감안할 때, 우리는 사용자에게 더 많은 선택권을 제공하기 위해 이러한 옵션에 대한 추가 모듈을 구축할 가능성이 높습니다.

분산 추적 구현

원하는 추적 기능을 제공하는 도구가 무엇인지 결정하는 것 외에도 솔루션을 구현하는 방법과 솔루션에 통합해야 할 기술이 무엇인지 고려해야 했습니다.

첫째, 우리는 어떤 계측도 애플리케이션 자체의 서비스 품질에 부정적인 영향을 미치지 않는지 확인하고 싶었습니다. 우리 모두는 로그를 내보낼 때 한 시간에 한 번씩 성능이 예상대로 저하되는 시스템을 사용해 왔으며, 그 경험을 다시 겪고 싶지 않았습니다. OpenTelemetry Collector의 아키텍처는 호스트당 하나의 인스턴스를 실행할 수 있기 때문에 이런 측면에서 매력적이었습니다. 각 수집기는 호스트에서 실행 중인 모든 다양한 애플리케이션(컨테이너화 여부와 관계없이)의 클라이언트와 에이전트로부터 데이터를 수신합니다. 수집기는 데이터를 집계하고 압축한 다음 저장 백엔드로 전송하는데, 이는 이상적으로 들렸습니다.

다음으로, 우리는 애플리케이션에서 사용하는 다양한 프로그래밍 언어와 프레임워크에서 OpenTelemetry에 대한 지원을 평가했습니다. 여기서는 상황이 조금 더 까다로워졌습니다. 표에 나와 있는 두 가지 프로그래밍 언어와 관련 프레임워크만 사용했음에도 불구하고 복잡성 수준이 놀라울 정도로 높았습니다.

언어 뼈대 서비스 수
자바 스프링 부트 3
파이썬 플라스크 3

언어 수준 추적을 추가하기 위해 먼저 OpenTelemetry의 자동 계측 에이전트를 시도했지만 출력이 지저분하고 혼란스럽다는 것을 발견했습니다. 자동 계측 라이브러리가 발전함에 따라 이 부분도 개선될 것이라고 확신하지만, 당장은 OpenTelemetry 에이전트를 배제하고 코드에 추적 기능을 짜넣기로 했습니다.

코드에서 추적을 직접 구현하기 전에 먼저 OpenTelemetry Collector를 연결하여 모든 추적 데이터를 로컬에서 실행 중인 Jaeger 인스턴스로 출력하여 출력을 보다 쉽게 볼 수 있도록 했습니다. OpenTelemetry를 완벽하게 통합하는 방법을 알아내면서 추적 데이터의 시각적 표현을 가지고 놀 수 있었기 때문에 이 기능은 매우 유용했습니다. 예를 들어, 종속 서비스를 호출할 때 HTTP 클라이언트 라이브러리가 추적 데이터를 포함하지 않는다는 것을 발견하면 우리는 즉시 해당 문제를 수정 목록에 추가했습니다. Jaeger는 단일 추적 내에서 모든 다양한 스팬을 잘 보여줍니다.

Python을 위한 분산 추적

Python 코드에 추적을 추가하는 것은 비교적 간단했습니다. 모든 서비스에서 참조하는 두 개의 Python 소스 파일을 추가하고 해당 requirements.txt 파일을 업데이트하여 관련 opentelemetry-instrumentation-* 종속성을 포함했습니다. 즉, 모든 Python 서비스에 동일한 추적 구성을 사용할 수 있고, 로그 메시지에 각 요청의 추적 ID를 포함하고 종속 서비스에 대한 요청에 추적 ID를 내장할 수 있다는 의미입니다.

Java용 분산 추적

다음으로, Java 서비스에 주목했습니다. 그린필드 프로젝트에서 OpenTelemetry Java 라이브러리를 직접 사용하는 것은 비교적 간단합니다. 필요한 라이브러리를 가져오고 추적 API를 직접 사용하기만 하면 됩니다. 하지만 우리처럼 Spring을 사용한다면, 추가적인 결정을 내려야 합니다.

Spring에는 이미 분산 추적 API인 Spring Cloud Sleuth 가 있습니다. 이는 설명서에 설명된 대로 다음을 수행하는 기본 분산 추적 구현에 대한 외관을 제공합니다.

  • Slf4J MDC에 추적 및 범위 ID를 추가하므로 로그 집계기에서 지정된 추적 또는 범위에서 모든 로그를 추출할 수 있습니다.
  • Spring 애플리케이션의 일반적인 유입 및 유출 지점(서블릿 필터, REST 템플릿, 예약된 작업, 메시지 채널, 가짜 클라이언트)을 도구화합니다.
  • spring-cloud-sleuth-zipkin을 사용할 수 있는 경우 … HTTP를 통해 Zipkin과 호환되는 추적을 생성하고 보고합니다. 기본적으로 로컬호스트(포트 9411)의 Zipkin 수집 서비스로 전송됩니다. spring.zipkin.baseUrl을 사용하여 서비스의 위치를 구성합니다.

API를 사용하면 @Scheduled 주석이 달린 작업에 추적을 추가할 수도 있습니다.

다시 말해, Spring Cloud Sleuth만 사용해도 바로 HTTP 서비스 엔드포인트 수준에서 추적을 얻을 수 있어서 좋은 장점입니다. 우리 프로젝트에서는 이미 Spring을 사용하고 있으므로 모든 것을 해당 프레임워크 내에서 유지하고 제공되는 기능을 활용하기로 결정했습니다. 하지만 Maven을 사용하여 모든 것을 연결하면서 몇 가지 문제를 발견했습니다.

  • Spring Cloud Sleuth Autoconfigure 모듈은 아직 마일스톤 릴리스 단계에 있습니다.
  • Spring Cloud Sleuth Autoconfigure 모듈은 opentelemetry-instrumentation-api 의 오래된 알파 버전에 의존합니다. 현재 이 라이브러리의 최신 비알파 1.x 릴리스는 없습니다.
  • Spring Cloud Sleuth가 마일스톤 릴리스에 대한 종속성 참조를 코딩하는 방식 때문에 해당 프로젝트는 Spring Snapshot 저장소에서 부모 프로젝트 객체 모델(POM) spring-cloud-build를 가져와야 합니다.

이로 인해 Maven 프로젝트 정의가 조금 더 복잡해졌습니다. Maven Central뿐 아니라 Spring 저장소에서도 Maven을 가져와야 했기 때문입니다. 이는 Spring Cloud에서 OpenTelemetry 지원이 얼마나 초기 단계인지를 명확하게 보여줍니다. 그럼에도 불구하고, 우리는 계속해서 발전하여 Spring Cloud Sleuth와 OpenTelemetry를 사용하여 분산 추적을 구성하는 공통 원격 측정 모듈을 만들었고, 여기에는 다양한 원격 측정 관련 도우미 함수와 확장 기능이 포함되어 있습니다.

공통 원격 측정 모듈에서 Spring Cloud Sleuth와 OpenTelemetry 라이브러리가 제공하는 추적 기능을 확장하여 다음을 제공합니다.

또한, 서비스 간에 HTTP 호출을 할 때 더 많은 측정항목과 사용자 정의 기능을 원했기 때문에 Apache HTTP 클라이언트로 지원되는 Spring 호환 HTTP 클라이언트를 구현했습니다. 이 구현에서는 종속 서비스가 호출될 때 추적 및 스팬 식별자가 헤더로 전달되어 추적 출력에 포함될 수 있습니다. 게다가, 이 구현은 OpenTelemetry에서 집계된 HTTP 연결 풀 메트릭을 제공합니다.

결론적으로 Spring Cloud Sleuth와 OpenTelemetry를 사용하여 추적 기능을 연결하는 작업은 힘들었지만, 그만한 가치가 있었다고 믿습니다. 우리는 이 프로젝트와 이 글이 이 길을 가고자 하는 다른 사람들에게 길을 밝히는 데 도움이 되기를 바랍니다.

NGINX를 위한 분산 추적

요청의 전체 수명 주기 동안 모든 서비스를 연결하는 추적을 얻으려면 OpenTelemetry를 NGINX에 통합해야 했습니다. 이 목적을 위해 OpenTelemetry NGINX 모듈 (아직 베타 상태)을 사용했습니다. NGINX의 모든 버전에서 작동하는 모듈의 바이너리를 얻는 것이 잠재적으로 어려울 수 있다는 것을 예상하고, 지원되지 않는 NGINX 모듈을 통합한 컨테이너 이미지의 GitHub 저장소를 만들었습니다. 우리는 매일 밤 빌드를 실행하고, 쉽게 가져올 수 있는 Docker 이미지를 통해 모듈 바이너리를 배포합니다.

우리는 아직 이 프로세스를 MARA 프로젝트NGINX Ingress Controller 빌드 프로세스 에 통합하지 않았지만, 곧 통합할 계획입니다.

메트릭 수집 구현

추적을 위한 OpenTelemetry 통합을 완료한 후, 다음으로 지표에 집중했습니다. Python 기반 애플리케이션에 대한 기존 메트릭이 없었기 때문에 당장은 추가하는 것을 미루기로 했습니다. Java 애플리케이션의 경우, Google Cloud의 Stackdriver 와 함께 Micrometer를 사용하는 원래 Bank of Anthos 소스 코드는 메트릭을 지원합니다. 하지만 Bank of Anthos를 포킹한 후 Bank of Sirius에서 해당 코드를 제거했습니다. 해당 코드로는 메트릭 백엔드를 구성할 수 없기 때문입니다. 그럼에도 불구하고, 메트릭 후크가 이미 존재한다는 사실은 적절한 메트릭 통합이 필요함을 보여줍니다.

구성 가능하고 실용적인 솔루션을 찾기 위해 먼저 OpenTelemetry Java 라이브러리 와 Micrometer 내의 메트릭 지원을 살펴보았습니다. 기술 간 비교를 위한 검색 결과, 이 글을 쓰는 시점에서 OpenTelemetry 메트릭이 아직 알파 단계에 있음에도 불구하고 JVM에서 메트릭 API로 OpenTelemetry를 사용하는 경우의 단점이 여러 결과에 나열되어 있습니다 . Micrometer는 JVM을 위한 성숙한 메트릭 파사드 계층으로, 자체 메트릭 구현이 아닌 구성 가능한 메트릭 구현을 전면에 내세우는 공통 API 래퍼를 제공한다는 점에서 slf4j 와 유사합니다. 흥미로운 점은 이것이 Spring의 기본 메트릭 API라는 점입니다.

이 시점에서 우리는 다음과 같은 사실을 고려했습니다.

  • OpenTelemetry Collector는 Prometheus , StatsD 및 기본 OpenTelemetry Protocol (OTLP)을 포함한 거의 모든 소스에서 메트릭을 사용할 수 있습니다.
  • Micrometer는 Prometheus 및 StatsD를 포함한 다양한 메트릭 백엔드도 지원합니다.
  • JVM용 OpenTelemetry Metrics SDK는 OTLP를 통한 메트릭 전송을 지원합니다.

몇 가지 실험을 거친 후, 우리는 가장 실용적인 방법은 Prometheus 백킹 구현과 함께 Micrometer façade를 사용하고 Prometheus API를 사용하여 애플리케이션에서 메트릭을 가져오도록 OpenTelemetry Collector를 구성하는 것이라는 결론을 내렸습니다. 우리는 수많은 기사를 통해 OpenTelemetry에서 누락된 메트릭 유형이 문제를 일으킬 수 있다는 사실을 알고 있었지만, 우리의 사용 사례에는 해당 유형이 필요하지 않았기 때문에 타협은 수용 가능했습니다.

우리는 OpenTelemetry Collector에 대해 흥미로운 사실 하나를 발견했습니다. OTLP를 통해 추적 정보를 수신하고 Prometheus API를 통해 메트릭 정보를 수신하도록 구성했지만, OTLP나 다른 지원되는 프로토콜을 사용하여 두 가지 유형의 데이터를 모두 외부 데이터 수신기로 전송하도록 구성할 수 있습니다. 이를 통해 LightStep을 사용하여 쉽게 애플리케이션을 시도할 수 있었습니다.

전반적으로 Java로 메트릭을 코딩하는 것은 Micrometer API에 맞게 작성했기 때문에 비교적 간단했습니다. Micrometer API에는 수많은 예제와 튜토리얼이 있습니다. 아마도 메트릭과 추적 모두에서 가장 어려운 일은 telemetry-common 에 대한 pom.xml 파일에서 Maven 종속성 그래프를 정확하게 얻는 것이었을 것입니다.

오류 집계 구현

OpenTelemetry 프로젝트는 그 자체로 오류 집계 기능을 포함하지 않으며 SentryHoneybadger.io 와 같은 솔루션만큼 우아한 오류 태그 구현을 제공하지 않습니다. 그럼에도 불구하고, 우리는 다른 도구를 추가하기보다는 단기적으로 오류 집계를 위해 OpenTelemetry를 사용하기로 결정했습니다. Jaeger와 같은 도구를 사용하면 error=true를 검색하여 오류 조건이 있는 모든 추적을 찾을 수 있습니다. 이를 통해 우리는 적어도 일반적으로 어떤 문제가 발생하는지 알 수 있습니다. 앞으로 Sentry 통합을 추가하는 것을 고려할 수도 있습니다.

상태 점검 및 런타임 내성 구현

애플리케이션의 맥락에서 상태 검사를 통해 Kubernetes는 서비스가 정상인지 또는 시작 단계를 완료했는지 알 수 있습니다. 서비스가 정상적이지 않은 경우 Kubernetes를 구성하여 인스턴스를 종료하거나 다시 시작할 수 있습니다. 우리 애플리케이션에서는 OpenTelemetry 상태 검사를 사용하지 않기로 결정했습니다. 설명서가 충분하지 않기 때문입니다.

대신 JVM 서비스의 경우 Spring Boot Actuator 라는 Spring 프로젝트를 사용하는데, 이는 상태 점검 엔드포인트뿐 아니라 런타임 내성 및 힙 덤프 엔드포인트도 제공합니다. Python 서비스의 경우 Spring Boot Actuator 기능의 하위 집합을 제공하는 Flask Management Endpoints 모듈을 사용합니다. 현재는 사용자 정의 가능한 애플리케이션 정보와 상태 검사만 제공합니다.

Spring Boot Actuator는 JVM과 Spring에 연결되어 내성, 모니터링 및 상태 점검 엔드포인트를 제공합니다. 게다가 엔드포인트에 제공되는 기본 데이터에 사용자 정의 정보를 추가할 수 있는 프레임워크도 제공합니다. 엔드포인트는 캐시 상태, 런타임 환경, 데이터베이스 마이그레이션, 상태 점검, 사용자 정의 가능한 애플리케이션 정보, 메트릭, 주기적 작업, HTTP 세션 상태, 스레드 덤프와 같은 항목에 대한 런타임 내성을 제공합니다.

Spring Boot Actuator가 구현한 상태 점검 엔드포인트는 모듈식 구성을 갖고 있어 서비스의 상태를 활성 상태 또는 준비 상태로 분류하는 여러 개별 검사로 구성할 수 있습니다. 모든 검사 모듈을 표시하는 전체 상태 검사도 가능하며 일반적으로 이와 같은 모양입니다.

정보 엔드포인트는 JSON 문서에서 단일 상위 수준 JSON 개체와 일련의 계층적 키 및 값으로 정의됩니다. 일반적으로 문서에는 서비스 이름과 버전, 아키텍처, 호스트 이름, OS 정보, 프로세스 ID, 실행 파일 이름, 머신 ID나 고유 서비스 ID와 같은 호스트에 대한 세부 정보가 지정됩니다.

힙 및 코어 덤프 구현

위시리스트와 도구 기능을 비교한 표에서 어떤 도구도 런타임 내성이나 힙/코어 덤프를 지원하지 않는다는 것을 기억하실 겁니다. 하지만 기본 프레임워크인 Spring은 두 가지 모두 지원합니다. 다만 애플리케이션에 관찰 기능을 연결하는 데 약간의 작업이 필요했습니다. 이전 섹션에서 자세히 설명했듯이 런타임 내성을 위해 Spring Boot Actuator와 함께 Python 모듈을 사용합니다.

마찬가지로, 힙 덤프의 경우 Spring Boot Actuator가 제공하는 스레드 덤프 엔드포인트를 사용하여 원하는 기능의 하위 집합을 달성했습니다. 우리는 필요에 따라 코어 덤프를 얻을 수 없고 이상적으로 세밀한 수준의 JVM 힙 덤프도 얻을 수 없지만, 약간의 추가 노력으로 원하는 기능 중 일부를 얻을 수 있습니다. 불행히도 Python 서비스의 코어 덤프에는 상당한 추가 작업이 필요하므로 이는 나중으로 연기되었습니다.

요약

많은 울음과 삶의 선택에 대한 의문을 품은 끝에 우리는 MARA에서 관찰을 위해 다음 기술을 사용하기로 결정했습니다(이하 OTel은 OpenTelemetry를 뜻함):

  • 로깅 (모든 컨테이너에 대해) – Filebeat → Elasticsearch / Kibana
  • 분산 추적
    • Java – Spring Cloud Sleuth → OTel용 Spring Cloud Sleuth 내보내기 도구 → OTel Collector → Jaeger, Lightstep, Splunk 등과 같은 플러그형 내보내기 도구
    • Python – OTel Python 라이브러리 → OTel Collector → 플러그형 스토어
    • NGINX 및 NGINX Plus (NGINX Ingress Controller는 아직 지원되지 않음) – NGINX OTel 모듈 → OTel Collector → 플러그형 익스포터
  • 메트릭 수집
    • Java – Spring을 통한 Micrometer → Prometheus exporter → OTel Collector
    • Python – 아직 구현되지 않음
    • Python WSGI – GUnicorn StatsD → Prometheus(StatsD/ServiceMonitor를 통해)
    • NGINX – Prometheus 엔드포인트 → Prometheus(ServiceMonitor를 통해)
  • 오류 집계 – OTel 분산 추적 → 플러그형 내보내기 → 오류 로 표시된 추적을 찾기 위한 내보내기 검색 기능
  • 건강 검진
    • Java – Spring Boot Actuator → 쿠버네티스
    • Python – Flask 관리 엔드포인트 모듈 → Kubernetes
  • 런타임 내성
    • Java – Spring Boot 액추에이터
    • Python – Flask 관리 엔드포인트 모듈
  • 힙/코어 덤프
    • Java – 스레드 덤프에 대한 Spring Boot Actuator 지원
    • Python – 아직 지원 안 됨

이 구현은 특정 시점의 스냅샷입니다. 개발이 계속됨에 따라 분명히 변화하고 진화할 것입니다. 곧 우리는 이 애플리케이션에 대한 광범위한 부하 테스트를 실시할 예정입니다. 우리는 관찰성 접근 방식의 단점에 대해 많은 것을 배우고 추가적인 관찰성 기능을 추가할 것으로 기대합니다.

Modern Apps Reference Architecture샘플 애플리케이션 (Sirius 은행)을 사용해 보세요. 더 나은 서비스를 제공하기 위한 아이디어가 있으시다면, GitHub 저장소 에 공유해 주세요!

관련 게시물

이 게시물은 시리즈의 일부입니다. 시간이 지남에 따라 MARA에 기능을 추가함에 따라 블로그에 세부 정보를 게시하고 있습니다.


"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."