Service Discovery

Service Discovery는 동적으로 변화하는 환경에서 수집 대상을 자동으로 찾아내고 관리하는 기술로, 사용자가 수동으로 각각의 서비스를 추적하고 업데이트하는 번거로움을 해소해 줍니다. 이 기술은 특히 클라우드 환경에서 매우 유용하며, AWS, Azure, GCP와 같은 주요 Public Cloud 제공 업체들과 Kubernetes, 호스트, HTTP 서비스 등 다양한 환경에서의 Service Discovery를 지원합니다. Prometheus는 이러한 동적 환경에 탁월하게 대응할 수 있도록 Service Discovery 기능을 제공하고 있습니다. 본 문서에서는 Prometheus의 구성 파일을 통해 Service Discovery를 어떻게 정의하는지, 그리고 Prometheus가 이 설정을 바탕으로 어떻게 자동으로 수집 대상을 식별하고 선정하는지에 대한 방법에 대하여 기록하였습니다. 이를 통해 사용자는 Prometheus를 사용하여 보다 효율적으로 자원을 모니터링 할 수 있는 방법을 이해하는데 많은 도움이 되었으면 합니다.

 

Kubernetes Service Discovery

동적인 환경에서 서비스들이 어떻게 변화하는지를 실시간으로 파악하고 관리하는 것은 매우 복잡하고 어려운 일입니다. 이러한 문제를 해결하기 위해 Prometheus에서는 다양한 Service Discovery 메커니즘을 제공하고 있으며, 그 중에서도 특히 Kubernetes 환경에 최적화된 Kubernetes Service Discovery를 예시로 들어 Prometheus의 Service Discovery 작동 원리를 상세하게 설명해 보고자 합니다. 이 예제를 통해 설명드리는 것은 Kubernetes 환경에서의 Service Discovery 방식이지만, 이와 유사한 원리로 다양한 환경에서 Prometheus가 어떻게 서비스를 자동으로 감지하고 모니터링 대상으로 추가하는지에 대한 이해를 돕기 위함입니다. 따라서 이 예제를 통해 Kubernetes Service Discovery의 구체적인 작동 방식을 파악하시면, Prometheus가 지원하는 다른 환경들에서의 Service Discovery 작동 방식도 보다 쉽게 이해하고 적용하실 수 있습니다. 이번 문서의 내용은 Prometheus의 설치 과정이나 초기 설정 방법 등 기초적인 내용보다는, Prometheus가 어떻게 동적인 서비스 환경에서 모니터링 대상을 자동으로 발견하고 관리하는지에 대한 동작 원리와 방식에 초점을 맞추어 정리하였습니다.

 

Service Discovery 설정 파일 작성

Prometheus에서 scrape_configs 설정을 통해 Kubernetes 상의 특정 노드에서 실행 중인 exporter의 메트릭을 수집하는 과정은 매우 세밀하고 구체적인 접근이 필요합니다. 이러한 설정에서 scrape_configs의 선언 순서는 타겟을 효과적으로 식별하고 분류하는 데 있어 핵심적인 역할을 합니다. Prometheus는 이 설정들을 선언된 순서대로 처리하게 되므로, 가능한 한 빠르게 대상을 좁혀나갈 수 있도록 최적화된 조건을 선두에 배치하는 것이 중요합니다. 이렇게 함으로써, Prometheus는 불필요한 탐색을 줄이고, 보다 효율적으로 메트릭을 수집할 수 있는 대상을 신속하게 파악할 수 있습니다. (참고 : Kubernetes Service Discovery는 node, pod, service, endpoints, endpointslice의 리소스를 통하여 수집 대상을 정의할 수 있습니다.)

 

이 예제는 Prometheus의 구성에서 특히 Kubernetes 환경 내의 특정 노드에서 실행되고 있는 nginx-exporter라는 이름의 워크로드로부터 메트릭을 수집하는 방법니다. 이 과정에서 kubernetes_sd_configs 설정에서 role을 pod로 지정함으로써, Prometheus가 Kubernetes의 파드 단위에서 동작하는 서비스를 대상으로 메트릭 수집을 수행하도록 설정하였습니다.

  1. 해당 파드가 worker1이라는 노드에 동작한다면 Keep 합니다.
  2. worker1에 동작하는 파드의 워크로드가 nginx-exporter라면 Keep 합니다.
  3. 파드의 9113이라는 Container port가 있으면 Keep 합니다.

이러한 단계별 접근 방식은 Prometheus가 Kubernetes 환경 내에서 메트릭을 수집할 때 필요한 정확성과 효율성을 보장합니다. 이 과정을 통해 Prometheus는 불필요한 데이터 수집을 최소화하고, 관련된 메트릭만을 효과적으로 수집하며, 시스템의 부하를 줄이는 동시에 모니터링의 정확성을 높일 수 있습니다.

scrape_configs:
  - job_name: 'my-metrics'
    kubernetes_sd_configs:
      - role: pod  # 파드 레벨에서 메트릭 수집

    relabel_configs:
      # 동작중인 노드이름이 'worker1'인 파드만 수집 설정
      - source_labels: [__meta_kubernetes_pod_node_name]
        action: keep
        regex: worker1

      # 워크로드 이름이 'nginx-exporter'인 파드만 수집 설정
      - source_labels: [__meta_kubernetes_pod_label_app]
        action: keep
        regex: nginx-exporter

      # 컨테이너 포트가 9113 파드만 수집
      - source_labels: [__meta_kubernetes_pod_container_port_number]
        action: keep
        regex: '(.*)9113'

 

Service Discovery 동작 방식

Prometheus의 Service Discovery 메커니즘은 크게 Discovery Manager와 Scrape Manager 두 가지 핵심 구성 요소의 동작에 의해 구현됩니다. 이 Manager는 Prometheus가 동적 환경에서 서비스를 발견하고, 해당 서비스로부터 메트릭을 수집하는 작업을 수행합니다.

 

Discovery Manager 동작

Discovery Manager는 사용자가 정의한 Service Discovery 설정에 따라 각각의 서비스 발견 메커니즘을 실행하고, 이러한 메커니즘을 통해 발견된 리소스의 변화를 지속적으로 감지합니다. 이렇게 발견된 리소스에 필요한 메타데이터를 Label로 할당하는 작업을 수행합니다. 이 메타데이터는 주로 리소스를 식별하고 분류하는 데 사용되는 라벨 형태로 제공되며, Prometheus가 메트릭을 수집할 때 리소스를 구분하고 필터링하는 데 필수적입니다. 예를 들어, Kubernetes 환경에서 Discovery Manager는 각 파드, 서비스, 노드 등의 Kubernetes 리소스에 대한 정보를 수집하고, 이러한 리소스에 적절한 라벨을 할당하여 Scrape Manager가 이들을 구분할 수 있도록 합니다. Discovery Manager의 이름만 봤을 때는 위에서 선언한 scrape_configs를 통하여 필터링까지 수행하는 것 같지만 실제로 Discovery Manager에서는 필터링을 수행하지 않고 변경된 리소스만 감지하는 역할만 수행합니다.

 

소스 코드 위치

https://github.com/prometheus/prometheus/tree/main/discovery

 

Scrape Manager 동작

Discovery Manager가 발견한 리소스 정보는 일종의 중간 저장소 또는 메시지 큐인 Channel을 통해 Scrape Manager에 전달됩니다. Scrape Manager는 scrape_configs에 정의된 설정을 기반으로 실제 메트릭 수집 대상을 선별하고 필터링하는 중요한 작업을 수행합니다. scrape_configs 설정에는 수집할 대상의 종류, 주소, 포트, 경로 등이 명시되어 있으며, Scrape Manager는 이 정보를 사용하여 Prometheus가 어떤 서비스로부터 메트릭을 수집할지를 결정합니다. 또한, 이 과정에서 특정 조건에 맞는 리소스에 대해서만 메트릭을 수집하도록 필터링하여 Prometheus가 설정된 간격에 따라 각 수집 대상으로부터 메트릭을 수집합니다.

 

소스 코드 위치

https://github.com/prometheus/prometheus/tree/main/scrape

대상을 필터링하는 소스코드 위치

https://github.com/prometheus/prometheus/blob/main/model/relabel/relabel.go

 

Service Discovery 동작 순서

위에서 선언한 scrape_configs를 기반으로 동작하는 방식은 다음과 같습니다.

Discovery Manager는 kubernetes_sd_configs 설정을 통해 Kubernetes 환경과의 통신을 위한 Kubernetes 클라이언트를 초기화합니다. 이 클라이언트는 Kubernetes API Server에 Request를 통하여, 설정된 role에 따라 특정 Kubernetes 리소스(예를 들어, Pod)의 변화를 실시간으로 감지할 수 있는 Watcher(Informer)를 생성합니다. 이러한 방식으로 Prometheus는 Kubernetes 클러스터 내의 Pod 리소스의 생성, 업데이트, 삭제 등의 이벤트를 지속적으로 모니터링할 수 있게 됩니다.

 

Discovery Manager가 Kubernetes API 서버로부터 받아온 Pod 정보에는 다양한 메타데이터가 포함되어 있으며, 이 중에서 특히 중요한 정보는 라벨 형태로 Prometheus에 전달됩니다. 예를 들어, __meta_kubernetes_namespace, __meta_kubernetes_pod_name, __meta_kubernetes_pod_container_name과 같은 라벨은 각 Pod의 메타데이터의 값을 Label에 추가합니다. 이러한 Label들은 메트릭 데이터에 포함되어 Prometheus 사용자가 보다 상세한 쿼리와 분석을 수행할 수 있도록 합니다.

 

이렇게 Discovery Manager에 의해 수집되고 라벨이 할당된 리소스 정보는 Channel을 통해 Scrape Manager로 전달됩니다. Scrape Manager는 이 정보를 받아 relabel_configs 설정에 정의된 규칙을 적용하여 실제 메트릭을 수집할 대상을 최종적으로 결정합니다. relabel_configs에서는 수집할 대상의 라벨을 재정의하거나, 특정 조건에 부합하는 리소스만을 필터링하여 수집 대상으로 선정하는 작업을 수행합니다. 이 과정을 통해 Prometheus는 사용자가 정의한 규칙에 따라 필요한 리소스로부터만 메트릭을 수집하게 되며, 이는 Prometheus의 수집 효율성을 극대화하고 불필요한 데이터 수집을 최소화하는 데 중요한 역할을 합니다.

 

마지막으로, Scrape Manager는 scrape_configs에 정의된 간격에 따라, 선별된 대상으로부터 메트릭을 수집합니다. 이때 각 메트릭에는 Discovery Manager로부터 할당받은 라벨 정보가 포함되어 있으며, relabel_configs에 정의된 순서대로 수집할 대상과 수집하지 않을 대상을 분리 또는 라벨 재정의하는 작업을 수행합니다. 이렇게 분리된 수집 대상에게 사용자가 정의한 일정 간격으로 메트릭을 수집합니다.

 

 

참조

https://prometheus.io/docs/prometheus/latest/configuration/configuration/

 

Configuration | Prometheus

An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.

prometheus.io

 

 

'Prometheus' 카테고리의 다른 글

Prometheus exporter의 구조와 개인 exporter 만들기  (0) 2023.11.04
Prometheus 윈도우10에 설치  (0) 2021.06.13

Prometheus exporter의 구조

Prometheus exporter의 구조는 하나 이상의 registry와 여러 개의 collector로 구성되어 있습니다. Prometheus가 "/metrics"로 request를 보내게 되면 "/metrics" endpoint에 등록된 handler에 의해 registry를 통하여 metric을 수집하게 됩니다. registry는 각각의 collector로부터 metric을 수집하여 metric을 정렬 수행한 후 http body 형식으로 변환하여 response를 전달하는 구조로 되어 있습니다. 

 

Collector란

collector는 각각의 특성에 맞는 데이터를 수집하여 해당 데이터를 metric으로 변환하여 registry에 전달하는 역할을 합니다. 예를 들어 processor collector는 processor에 관련된 데이터만 수집하여 processor metric을 생성하고 disk collector는 disk에 관련한 데이터를 수집하여 disk metric을 생성하도록 역할을 분리해 놓은 것입니다. 전체적인 Exporter의 구조는 아래 그림과 같습니다.

 

쉽고 간단하게 개인 Exporter 만들기

이번에 개인 Exporter를 만들기 위해서 제가 개발한 exporter_builder라는 Opensource를 이용하였습니다. exporter_builder는 명령어 2번만으로 Prometheus exporter의 기본적인 틀을 생성해 주는 Opensource입니다. 개인 Prometheus exporter를 초기에 개발 시 유용하게 사용할 수 있습니다.

https://github.com/k8shuginn/exporter_builder

 

GitHub - k8shuginn/exporter_builder: exporter_builder is a project that allows you to create your own prometheus exporter.

exporter_builder is a project that allows you to create your own prometheus exporter. - GitHub - k8shuginn/exporter_builder: exporter_builder is a project that allows you to create your own prometh...

github.com

 

1. 오픈소스 exporter_builder를 설치합니다.

먼저 go가 설치되어 있어야합니다. 그리고 아래 명령어를 실행하여 exporte_builder를 설치하여 줍니다. exporter_builder를 설치하면 이제 builder라는 명령어를 사용할 수 있습니다.

go install github.com/k8shuginn/exporter_builder/cmd/builder@latest

 

2. config.yaml 파일을 생성합니다.

name: my_exporter
module: github.com/myname/my_exporter
collectors:
  - sample1
  - sample2

name : 개인 exporter의 이름

module : go.mod init을 하기 위한 프로젝트명

collectors : 각 특성의 collector 이름

 

3. exporter_builder를 이용하여 exporter 생성

builder --config ./config.yaml

exporter가 정상적으로 생성되면 아래와 같이 my_exporter가 생성됩니다.

 

4. Collector 제작

sample2의 collector.go파일을 확인하면 아래 코드와 같습니다. Prometheus에서 "/metrics"로 request를 보내게 되면 regitsry의 gather를 통하여 Collect 메서드를 호출하게 됩니다. 그러면 데이터를 만들어 "chan<- prometheus.Metric" channel에 Metric을 전송해 주는 코드를 작성하시면 됩니다.

package sample2

import (
	"github.com/prometheus/client_golang/prometheus"
)

var (
	sampleDesc = prometheus.NewDesc(
		"sample_metric",
		"sample metric",
		[]string{"key1", "key2"}, nil)
)

func SetFlags() {

}

type Collector struct {
}

func NewCollector() *Collector {
	return &Collector{}
}

func (c *Collector) Describe(ch chan<- *prometheus.Desc) {
	ch <- sampleDesc
}

func (c *Collector) Collect(ch chan<- prometheus.Metric) {
	ch <- prometheus.MustNewConstMetric(sampleDesc, prometheus.GaugeValue, 1, "value1", "value2")
}

 

SetFlags는 flag 사용시 이용하시면 됩니다. 사용하지 않더라도 지우지 마세요. 이상 Exporter의 구조와 개인 Exporter를 만드는 방법에 대하여 알아봤습니다. 자신만의 Exporter로 안전한 모니터링 시스템을 구축하세요 ~

'Prometheus' 카테고리의 다른 글

Prometheus가 Kubernetes service discover하는 동작 방식  (0) 2024.02.23
Prometheus 윈도우10에 설치  (0) 2021.06.13

Prometheus 다운로드

https://prometheus.io/download/

위 주소에서 Prometheus를 다운로드 받고 압축을 풀어 줍니다.

Prometheus 실행하기

prometheus.exe 파일을 실행합니다.

Prometheus의 기본 Port번호는 9090입니다. 브라우저를 통하여 'localhost:9090'을 입력합니다.

Prometheus 화면

짜잔 ~!

프로메테우스가 정상적으로 동작합니다.

 

Prometheus 설정하기

Prometheus는 모니터링을 할려는 Client에서 Metric port를 오픈하면 해당 Client에 Metric 데이터를 가져옵니다. 그렇기 때문에 Metric 데이터를 가져올 Client의 Metric port를 등록해야 됩니다.

prometheus.yml 파일을 열어 수정합니다.

scrape_configs에 다음과 같은 내용을 추가합니다.

  - job_name: 'MyPrometheus'
    scrape_interval: 2s
    static_configs:
    - targets: ['localhost:30001']

job_name : 프로메테우스에 등록할 이름

scrape_interval : metric 데이터를 가져오는 시간

targets : metric 수집할 대상 (Exporter 등등)

 

모든 설정이 끝나면 Prometheus를 재시작 합니다.

 

Prometheus Target 확인하기

각각의 타겟이 정상적으로 떳는지 확인하고 싶을때는 Status -> Target에서 확인 가능합니다.


Prometheus에 대한 자세한 내용은 다음 링크를 통하여 확인하세요

https://prometheus.io/docs/introduction/overview/

 

Overview | Prometheus

An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.

prometheus.io

 

+ Recent posts