Updated:

2 minute read

개요


특징

  • 기존 push 방식이 아닌 pull 방식을 채택
  • Pushgateway를 통해 push 방식도 지원
  • Prometheus에 수집할 엔드포인트와 주기를 설정하면 주기마다 해당 url를 http get하여 결과를 저장하는 방식
  • 직접적인 확장을 지원하지는 않으며 Prometheus에 Prometheus를 연결하거나 Thanos를 이용하여 확장
  • PromQL(Prometheus Query Language) 사용
  • 메트릭을 시각화 해주는 오픈소스인 Grafana와 함께 사용되는 경우가 많음


적합한 경우

  • 숫자 시계열 저장이 필요한 경우


부적합한 경우

  • 100% 정확도가 필요한 경우 수집된 데이터가 부정확할 수 있음


config

  • https://prometheus.io/docs/prometheus/latest/configuration/configuration/
  • scrape_interval : 수집 주기
  • scrape_timeout : 수집 타임아웃
  • scrape_configs : 수집 정보
  • scrape_configs.job_name, scrape_configs.metrics_path, scrape_configs.static_configs.targets
       prometheus.yml: |
         global:
           scrape_interval: 15s
           scrape_timeout: 10s
         scrape_configs:
         - job_name: test-1
           metrics_path: /metrics
           static_configs:
           - targets:
             - 127.0.0.1:10000
    


설치

  • prometheus-community/helm-charts
  • vim kube-prometheus-stack-values.yaml
    • values.yaml을 참조하여 설정
         prometheus:
           service:
             type: NodePort
              
         grafana:
           service:
             type: NodePort
             nodePort: 30100
      
  • helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  • helm repo update
  • kubectl create ns prometheus-stack
  • helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack -f kube-prometheus-stack-values.yaml -n prometheus-stack


삭제

  • helm uninstall kube-prometheus-stack -n prometheus-stack


UI 접속 정보

  • Prometheus
    • http://127.0.0.1:30090/
  • Grafana:
    • http://127.0.0.1:30100/


metric_types

  • https://prometheus.io/docs/concepts/metric_types/
  • Counter
    • 0부터 증가만 가능한 단일 숫자 누적 매트릭
  • Gauge
    • 특정 값, 증가, 감소가 가능한 단일 숫자 매트릭
  • Histogram
    • 관찰한 값 들에 대해 관찰 카운트, 관찰 된 값의 합, 관찰 버킷에 대한 누적 카운터를 제공
  • Summary
    • Histogram과 유사
    • 관찰한 값 들에 대해 관찰 카운트, 관찰 된 값의 합, φ-quantiles를 제공


metric exporter example code

  • https://github.com/prometheus/client_golang
  • http://ip:10000에 접속하여 메트릭 값을 변경
  • http://ip:10000/metrics에 접속하여 매트릭 값 확인
  • 자동으로 레지스트리에 추가되는 것을 원하지 않으면 promauto.NewXXX() 대신 prometheus.NewXXX()를 쓰고 prometheus.MustRegister()로 개별 등록
     package main
    	
     import (
         "log"
         "math/rand"
         "net/http"
    	
         "github.com/prometheus/client_golang/prometheus"
         "github.com/prometheus/client_golang/prometheus/promauto"
         "github.com/prometheus/client_golang/prometheus/promhttp"
     )
    	
     var (
         counterTest = promauto.NewCounter(
             prometheus.CounterOpts{
                 Namespace: "namespace_test",
                 Subsystem: "subsystem_test",
                 Name:      "counter_test",
                 Help:      "counter test help",
             })
    	
         gaugeTest = promauto.NewGauge(prometheus.GaugeOpts{
             Namespace: "namespace_test",
             Subsystem: "subsystem_test",
             Name:      "gauge_test",
             Help:      "gauge test help",
         })
    	
         histogramTest = promauto.NewHistogram(prometheus.HistogramOpts{
             Namespace: "namespace_test",
             Subsystem: "subsystem_test",
             Name:      "histogram_test",
             Help:      "histogram test help",
             Buckets:   prometheus.LinearBuckets(20, 5, 5),
         })
    	
         summaryTest = promauto.NewSummary(prometheus.SummaryOpts{
             Namespace:  "namespace_test",
             Subsystem:  "subsystem_test",
             Name:       "summary_test",
             Help:       "summary test help",
             Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
         })
     )
    	
     func handler(w http.ResponseWriter, r *http.Request) {
         counterTest.Inc()
         counterTest.Add(1)
    	
         //  gaugeTest.SetToCurrentTime()
         //  gaugeTest.Set(1)
         gaugeTest.Inc()
         gaugeTest.Dec()
         gaugeTest.Add(1)
         gaugeTest.Sub(-1)
    	
         histogramTest.Observe(float64(rand.Intn(10) + 1))
    	
         summaryTest.Observe(float64(rand.Intn(10) + 1))
    	
         w.Write([]byte("ok"))
     }
    	
     func main() {
         http.HandleFunc("/", handler)
         http.Handle("/metrics", promhttp.Handler())
         log.Fatal(http.ListenAndServe(":10000", nil))
     }
    


Prometheus HTTP API example code

  • https://github.com/prometheus/client_golang
  • Prometheus에 쿼리 전송 및 결과 출력
     package main
    	
     import (
         "context"
         "fmt"
         "os"
         "time"
    	
         "github.com/prometheus/client_golang/api"
         v1 "github.com/prometheus/client_golang/api/prometheus/v1"
     )
    	
     func query(address, query string) {
         client, err := api.NewClient(api.Config{
             Address: address,
         })
         if err != nil {
             fmt.Printf("new client error : %s\n", err.Error())
             os.Exit(1)
         }
    	
         v1api := v1.NewAPI(client)
    	
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         defer cancel()
    	
         result, warnings, err := v1api.Query(ctx, query, time.Now())
         if err != nil {
             fmt.Printf("query error : (%s)\n", err.Error())
             os.Exit(1)
         }
         if len(warnings) > 0 {
             fmt.Printf("query warnings : %v\n", warnings)
         }
    	
         fmt.Printf("%v", result)
     }
    	
     func queryRange(address, query string) {
         client, err := api.NewClient(api.Config{
             Address: address,
         })
         if err != nil {
             fmt.Printf("new client error : %s\n", err.Error())
             os.Exit(1)
         }
    	
         v1api := v1.NewAPI(client)
    	
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         defer cancel()
    	
         r := v1.Range{
             Start: time.Now().Add(-time.Hour),
             End:   time.Now(),
             Step:  time.Minute,
         }
         result, warnings, err := v1api.QueryRange(ctx, query, r)
         if err != nil {
             fmt.Printf("query range error : (%s)\n", err.Error())
             os.Exit(1)
         }
         if len(warnings) > 0 {
             fmt.Printf("query range warnings : %v\n", warnings)
         }
    	
         fmt.Printf("%v", result)
     }
    	
     func main() {
         query("http://127.0.0.1:31005", "up")
         fmt.Printf("\n=========================================================\n\n")
         queryRange("http://127.0.0.1:31006", "rate(namespace_test_subsystem_test_counter_test[5m])")
     }