# 오픈소스를 이용한 다중 k8s 클러스터 환경의 모니터링 시스템 구축

2022. 8. 3. 22:53 개발 이야기/오픈소스

Micro Service Architecture, 컨테이너 기반의 서비스 운영이 당연시되고 있는 요즘, 많은 컨테이너를 관리하기 위해서 컨테이너 오케스트레이션(Orchestration) 툴을 사용하지 않을 수 없습니다. 컨테이너 오케스트레이션 툴은 컨테이너화된 수 많은 애플리케이션의 배포의 복잡성과 고가용성, 안정성, 보안 및 자동 확장 등에 대한 요구를 충족해주는 툴인데요. 그 중에서도 가장 많은 관심을 받고 있고, 많이 사용되는 컨테이너 오케스트레이션 툴은 쿠버네티스(Kubernetes)입니다. 다른 컨테이너 오케스트레이션 툴도 동일하지만 실제로 쿠버네티스를 운영하다보면 많은 컨테이너와 노드, k8s 오브젝트들의 관리가 쉽지 않다는 것을 느끼실 수 있습니다. 서비스에 장애가 발생하였을 때 숙련된 사용자가 아니라면 실제로 장애 지점을 파악하기 어렵고 적절한 모니터링 시스템이 구축되지 않는다면 컨테이너 오케스트레이션 툴이 주는 수 많은 이점을 취하지 못하고, 복잡한 운영 방식에서 스트레스만 받게 될것입니다.

https://kubernetes.io/

실제로 쿠버네티스를 이용해 서비스를 운영하는 기업들의 사례를 보면 하나의 k8s 클러스터가 아닌 여러 k8s 클러스터를 구성하여 운영하고 있는 것을 알 수 있습니다. 또한, 컨테이너화되지 않은 레거시 서비스의 운영을 위해 k8s 클러스터가 아닌 일반 서버로도 많은 서비스가 운영되고 있는 것을 알 수 있습니다. 점점 백엔드의 구성은 이처럼 복잡하고 어려워지는 것을 알 수 있습니다. 이렇게 복잡한 백엔드에 모니터링 시스템이 존재하지 않는다면 운영에 많은 어려움을 겪을 수밖에 없는데요. k8s 클러스터와 non-k8s 클러스터 환경 모두 오픈소스를 이용해 모니터링할 수 있는 방법에 대해 알아보도록 하겠습니다.

Observability의 세 가지 기둥

Event Logs

이벤트 로그는 전통적으로 문제가 생겼을 때 가장 많이 참고되고 있는 정보입니다. 서버의 로그는 /var/log, journalctl, systemd 등의 다양한 로그가 곳곳에 존재하고 있으며, 장애가 발생하면 서버의 로그와 애플리케이션의 로그를 가장 먼저 참고하게 됩니다. 하지만 수 많은 텍스트는 가독성이 떨어지는 문제가 있으며, 성숙한 운영자가 아닌 경우 문제 해결에 많은 시간이 소모되곤 합니다. 적게는 초당 수 백건에서 수 백만의 로그가 쏟아지고 있어 빠르게 정확한 원인 파악을 하기에는 어려움이 있습니다.

/var/log/boot.log

Metrics

메트릭은 일정 시간 간격에 따라 측정된 데이터의 숫자 표현입니다. 예를들어 CPU 사용량은 매 10초마다 기록되고 있으며 매 10초마다 수집된 데이터는 CPU 사용 추이를 나타낼 수 있습니다. 이런 데이터를 시계열 데이터라고도 하며, 현대에는 머신러닝과 수학적 모델링을 이용해 추이를 예측하고 이상 상황을 탐지할 수 있습니다.  하지만 로그와 메트릭은 시스템 범위이므로 특정 시스템 내부에서 발생하는 일 외에 외부에서 발생하는 것들은 이해할 수 없다는 단점이 있습니다. 예를 들어 A 서비스와 B 서비스가 통신을 하는데 서로 다른 네트워크 망에 존재할 경우 외부 네트워크의 장애 발생 시 로그와 메트릭으로는 알 수 있는 방법이 많지 않습니다.

Tracing

마이크로 서비스 아키텍처로 구성된 최신 시스템의 경우 상호 복잡한 백엔드로 구성되어 있습니다. 애플리케이션 간의 요청 흐름과 시스템 통신을 이해하는 것은 운영자에게 커다란 어려움을 주고 있습니다. 여러번 언급했듯, 여러 k8s 클러스터로 구성되어 서비스가 운영되고 non-k8s 환경도 함께 구성된 백엔드의 병목 현상을 분석하기는 상당한 에너지를 소비하게 됩니다. 이는 인력을 낭비하는 기업의 손실로 직결되고 있습니다. 트레이싱은 Observability 에서 분산 시스템의 관찰 가능성을 높이고 성능 병목 현상을 이해하기위한 필수적인 요소입니다.

 

분산 환경의 시스템, 여러 k8s 클러스터와 레거시 서버를 한 눈에 관측하고자 한다면 최소한 위에서 언급한 로그, 메트릭, 트레이싱의 모니터링 시스템을 한 눈에 볼 수 있도록 구축해야 합니다. 많은 유료 솔루션이 존재하지만, 오픈소스를 이용해 유료 솔루션 못지 않은 모니터링 시스템을 구축할 수 있습니다.

Observability 도메인 오픈소스 소개

Clymene-project(https://clymene-project.github.io/)

오픈소스 clymene 프로젝트는 분산 환경의 메트릭과 로그를 수집하고 다양하게 백엔드를 구성할 수 있는 컴포넌트들이 존재합니다. 메트릭을 수집하는 Clymene-agent는 Prometheus의 서비스 디스커버리 기능이 있기 때문에 다양한 환경의 메트릭 수집 엔드포인트를 손쉽게 설정할 수 있습니다. 또한 ElasticSearch, prometheus, cortex, opentsdb, influxDB 등 다양한 데이터 베이스에 메트릭을 저장할 수 있으며, 익숙한 데이터베이스에 prometheus exporter로 추출한 메트릭 데이터를 수집/저장하고 관리할 수 있습니다. 또한 gRPC, HTTP 수신이 가능한 Clymene-gateway, kafka를 이용할 수 있는 Clymene-ingester를 이용해 고부하 환경에도 적합한 아키텍처로 구성할 수 있습니다.

Clymene-promtail은 로그를 수집하는 컴포넌트로 Clymene-agent와 마찬가지로 서비스 디스커버리 기능이 존재하며, /var/log, journalctl systemd 등 다양한 로그를 수집하여 백엔드로 전송하고 ElasticSearch, Loki 저장소에 저장할 수 있습니다. Clymene-agent와 동일하게 promtail-gateway, promtail-ingester를 이용해 다양한 아키텍처로 구성할 수 있습니다

https://clymene-project.github.io/docs/architecture/

Jaegertracing(https://www.jaegertracing.io/)

오픈소스 jaegertracing은 opentracing 데이터 모델을 구현한 분산 추적 시스템으로 애플리케이션이 코드를 instrumentation 하는 Jaeger-client, 트레이스 데이터의 기본이 되는 Span 데이터를 수집하는 Jaeger-agent, 데이터를 수신하고 저장소제 저장하는 Jaeger-collector 등의 컴포넌트가 존재합니다. 고부하 환경에 적합하도록 모두 scale-out이 가능한 이키텍처를 가지고 있습니다.

https://www.jaegertracing.io/docs/1.36/architecture/

Grafana(https://grafana.com/)

그라파나는 메트릭과 로그, 트레이싱 데이터를 시각화할 수 있는 가장 강력한 툴입니다. 2014년부터 현재까지도 활발하게 개발되고 있으며, 어렵지 않게 배울 수 있으며 유연하게 대시보드를 구성할 수있습니다. 여러 모니터링 유료 제품에 영감을 주는 오픈소스입니다.

 

다중 k8s 클러스터 환경의 모니터링 시스템 구축

메트릭과 로그를 수집할 수 있는 clymene 프로젝트에는 다양한 예제 파일이 존재합니다. k8s 환경의 예제를 참고해 모니터링 시스템을 구축해보겠습니다(https://github.com/Clymene-project/Clymene/tree/master/k8s)

1. clymene 메트릭 백엔드 구성(https://github.com/Clymene-project/Clymene/tree/master/k8s/clymene-metrics)

  • 메트릭 수집에 필요한 k8s RBAC을 설정합니다
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-metrics/1.clymene_rbac.yaml
# default namespace clymene
$ kubectl create -f 1.clymene_rbac.yaml
  • 메트릭을 추출해줄 node-exporter와 kube-state-metrics를 배포합니다
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-metrics/node-exporter.yaml
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-metrics/kube-state-metrics.yaml

$ kubectl create -f node-exporter.yaml
$ kubectl create -f kube-state-metrics.yaml
  • clymene 백엔드 데이터를 수집할 clymene-agent를 배포합니다
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-metrics/2.clymene_agent.yaml
$ kubectl create -f 2.clymene_agent.yaml
  • clymene agent의 데이터를 수신할 clymene-gateway를 배포하고 kafka와 연동을 확인합니다
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-metrics/3.clymene_gateway.yaml
# kafka 설정 확인 필요
$ kubectl create -f 3.clymene_gateway.yaml

#          args:
#            - --kafka.producer.brokers=kafka.kafka:9092
  • kafka에 적재된 메트릭을 저장소에 저장해줄 clymene-ingester를 배포하고 저장소와의 연동을 확인합니다(아래와 같이설정할 경우 prometheus와 elasticsearch에 동시 적재 가능)
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-metrics/4.clymene_ingester.yaml
$ kubectl create -f 4.clymene_ingester.yaml

#          args:
#            - --prometheus.remote.url=http://prometheus-server-http.prometheus:9090/api/v1/write
#            - --kafka.consumer.brokers=kafka.kafka:9092
#            - --es.server-urls=http://elasticsearch.es:9200

2. clymene 로그 백엔드 구성(https://github.com/Clymene-project/Clymene/tree/master/k8s/clymene-logs)

  • 서버의 로그를 수집하는 clymene-promtail 배포
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-logs/1.clymene-promtail_agent.yaml
$ kubectl create -f 1.clymene-promtail_agent.yaml
  • clymene-promtail의 로그를 수신하여 kafka, 저장소에 적재하는 clymene-gateway 배포
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-logs/2.clymene-promtail_gateway.yaml
$ kubectl create -f 2.clymene-promtail_gateway.yaml
  • kafka에 적재된 로그를 데이터베이스에 저장하는 clymene-ingester 배포
# https://github.com/Clymene-project/Clymene/blob/master/k8s/clymene-logs/3.clymene-promtail_ingester.yaml
$ kubectl create -f 3.clymene-promtail_ingester.yaml

3. jaegertracing 백엔드 구성(https://github.com/Clymene-project/Clymene/tree/master/k8s/jaeger-backend)

  • Jaeger All-in-one 배포
# https://github.com/Clymene-project/Clymene/blob/master/k8s/jaeger-backend/jaeger-all-in-one-template.yml
$ kubectl create -f jaeger-all-in-one-template.yml
  • Jaeger 예제 애플리케이션 hotrod 배포
# https://github.com/Clymene-project/Clymene/blob/master/k8s/jaeger-backend/hotrod-deploy.yml
$ kubectl create -f hotrod-deploy.yml

4. 관측 대상 k8s 클러스터에 clymene-agent, clymene-promtail 설치

# https://github.com/Clymene-project/Clymene/blob/master/k8s/target-cluster/1.clymene_rbac.yaml
$ kubectl create -f 1.clymene_rbac.yaml

# https://github.com/Clymene-project/Clymene/blob/master/k8s/target-cluster/2.clymene_agent.yaml
$ kubectl create -f 2.clymene_agent.yaml

# https://github.com/Clymene-project/Clymene/blob/master/k8s/target-cluster/1.clymene-promtail_agent.yaml
$ kubectl create -f 1.clymene-promtail_agent.yaml

 

 위의 절차를 통해 Prometheus와 ElasticSearch에 메트릭을 저장하고, Elasticearch와 Loki에 로그를 저장하는 백엔드를 구성하였습니다. 또한 트레이싱 데이터를 수집할 수 있는 Jaeger를 배포해 분산 환경의 Observability에 필수 요소인 메트릭, 로그, 트레이싱 데이터를 모두 하나의 백엔드에서 관리할 수 있게 되었습니다. 데이터 수집 시 label을 이용해 cluster를 구분하고 이를 통해 다중 클러스터의 표현이 가능합니다. 데이터 수집이 모두 완료되었다면 grafana를 통해 다중 k8s 클러스터의 모니터링 데이터를 시각화 해보겠습니다.

clymene-agent로 수집한 node와 k8s 메트릭 데이터 시각화

 

clymene-promtail로 수집한 로그 데이터 시각화

jaegertracing을 이용한 트레이스 데이터 시각화

 

이상으로, Clymene-project, Jaegertracing, Grafana를 이용한 이용한 다중 k8s 클러스터 모니터링 시스템 구축이었습니다. 

 

참고

  • https://www.oreilly.com/library/view/distributed-systems-observability/9781492033431/ch04.html
  • https://logz.io/blog/implementing-kubernetes-observability/