본문 바로가기
  • lakescript
스터디 이야기/AWS EKS

[AEWS] 4-2. Amazon EKS - Observability (Prometheus)

by lakescript 2024. 3. 29.

사전 준비

더보기

 

 

위와 같이 사전 준비가 필요합니다.

저번 글에서 설명했듯이, EKS를 배포하기 위한 VPC를 생성하고, Public Subnet, Private Subnet을 생성합니다. 그 후 EKS Cluster에 접근하기 위한 bastion EC2를 미리 생성합니다.
추가로, 지난번 실습 때 진행했었던 ExternalDNS와 AWS LB Controller, EBS csi driver 설치, gp3 스토리지 클래스 생성까지 해주셔야합니다.

 

이번 포스팅에는 이전에 포스팅했던 블로그 글 에서 많이 인용하였습니다.

 

 

Prometheus

 

Prometheus란?

Prometheus는 SoundCloud에서 처음 개발된 오픈 소스 시스템 모니터링 및 알림 툴킷입니다. 2012년에 시작된 이후로 많은 회사와 조직이 Prometheus를 채택하였고, 매우 활발한 개발자와 사용자 커뮤니티를 가지고 있습니다.

 

 

 

Prometheus는 2016년 Kubernetes 에 이어 두 번째 프로젝트로 Cloud Native Computing Foundation에 합류했으며, 서비스 운영을 위해 모니터링 시스템을 구축할 때 가장 널리 사용되는 툴 중 하나입니다.

 

 

 

Prometheus 특징

 

  • 다차원 데이터 모델: 메트릭 이름과 키/값 쌍으로 시계열 데이터를 식별합니다.
  • PromQL: 이러한 차원성을 활용할 수 있는 유연한 쿼리 언어입니다.
  • 분산 저장에 의존하지 않음: 단일 서버 노드가 자립적으로 작동합니다.
  • HTTP를 통한 풀 모델: 시계열 데이터 수집이 HTTP를 통해 이루어집니다.

공식문서에서는 Prometheus의 특징을 위처럼 알려주지만, 가장 큰 특징이 2가지 있습니다.

 

Pull-Based Monitoring

기존의 Push-Based Monitoring 방식 대신에 Pull-Based Monitoring을 사용합니다. 대상 서버에 설치된 Exporter가 메트릭 정보를 수집하고, 이 데이터는 수집 서버가 주기적으로 가져가는 구조입니다.

즉, 클라이언트에서 서버로 데이터를 보내는 것(PUSH)가 아닌 서버가 클라이언트의 데이터를 수집(Pull) 방식입니다. 이러한 방식은 기존의 에이전트(agent) 방식보다 더 유연하고 관리하기 쉽습니다.

시계열 데이터베이스(TSDB)

관계형 데이터베이스(RDB) 대신 metric 이름과 key-value 쌍으로 식별되는 시계열 데이터 모델을 사용합니다. 이를 통해 대량의 정보를 빠르게 검색할 수 있습니다.

 

 

Prometheus 구조

 

Prometheus는 크게 5가지로 구조를 나눠볼 수 있습니다.

Exporter

  • host서버에 설치되어 메트릭 데이터를 수집하는 역할을 합니다.
  • Prometheus 서버가 접근하여 데이터를 가져올 수 있는 HTTP 엔드포인트를 제공하여 다양한 데이터를 수집합니다.

Prometheus Server

  • Prometheus Server는 메트릭 데이터를 스크랩하고 저장합니다.
  • 메트릭 데이터 수집 주기를 설정하여 지정된 시간마다 대상 서버에 있는 Exporter로부터 데이터를 수집합니다.
  • 수집한 데이터를 저장하고 PromQL(프로메테우스 쿼리 언어)를 사용하여 데이터를 쿼리하고 필터링할 수 있습니다.

Grafana

  • Grafana는 데이터 시각화 도구로, Prometheus가 수집한 메트릭 데이터를 그래프나 대시보드 형태로 시각화하여 표현할 수 있습니다.
  • Prometheus Server에서 직접 제공하는 웹 뷰보다 더 다양한 시각화 기능을 제공하며, Grafana를 통해 데이터를 더 직관적으로 이해할 수 있습니다.

Alertmanager

  • Prometheus가 수집한 metric 데이터를 기반으로 경고를 생성하고 규칙을 만들어 관리합니다.

 

Prometheus Stack

 

 

kube-prometheus-stack이란?

kube-prometheus-stack은 kubernetes cluster에 맞게 구성된 오픈 소스 프로젝트입니다. Prometheus를 기반으로 하며, 쿠버네티스 클러스터의 다양한 컴포넌트들의 메트릭 데이터를 수집하고 이를 시계열 데이터로 생성하여 모니터링 및 경고 기능을 제공합니다.

 

kube-prometheus-stack 구조

 

 

일반적인 Prometheus와 구조가 비슷하지만 kubernetes cluster에 맞게 구성되어있습니다.

Prometheus Operator

  • 쿠버네티스 내에서 Prometheus 서버와 관련된 리소스들을 관리하기 위한 컨트롤러입니다.
  • Prometheus와 관련된 설정, 서비스 디스커버리, 룰 및 대시보드를 관리할 수 있습니다.

Prometheus Server

  • 고가용성을 제공하는 Prometheus 서버입니다.
  • metric 데이터를 스크랩하고 저장합니다.

Alertmanager

  • Prometheus가 수집한 메트릭 데이터를 기반으로 경고를 생성하고 관리하는 역할을 합니다.

Prometheus node-exporter

  • node-exporter는 Host의 metric을 수집하는 역할을 합니다.
  • CPU, 메모리, 디스크 사용량 등의 데이터를 수집하여 Prometheus로 전달합니다.

Prometheus Adapter for Kubernetes Metrics APIs

  • 쿠버네티스의 메트릭 API와 연동하여 클러스터 내부의 리소스 메트릭 데이터를 수집하고 Prometheus로 전달합니다.

kube-state-metrics

  • 쿠버네티스 클러스터의 상태 정보의 metric을 수집합니다.
  • 파드, 디플로이먼트, 노드 등의 상태 정보를 모니터링할 수 있습니다.

Grafana

  • Grafana는 데이터 시각화 및 대시보드 생성 도구로, 수집한 메트릭 데이터를 그래프나 대시보드 형태로 시각화하여 사용자에게 제공합니다.

 

kube-prometheus-stack 실습

monitoring namespace 생성

kubectl create ns monitoring

 

사용 리전의 인증서 ARN 확인 

CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN

 

console창에 값이 출력된다면 정상인 것이니 정상 상태임을 확인합니다.  (만료 상태면 후에 배포할 때에 에러 발생가 발생합니다!)

 

 

helm repo 설치

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

 

위의 명령어로 prometheus-community helm repo를 현재 cluster에 추가해줍니다.

 

prometheus:
  prometheusSpec:
    podMonitorSelectorNilUsesHelmValues: false
    serviceMonitorSelectorNilUsesHelmValues: false
    retention: 5d
    retentionSize: "10GiB"
    storageSpec:
      volumeClaimTemplate:
        spec:
          storageClassName: gp3
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 30Gi

  ingress:
    enabled: true
    ingressClassName: alb
    hosts: 
      - prometheus.$MyDomain
    paths: 
      - /*
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
      alb.ingress.kubernetes.io/group.name: study
      alb.ingress.kubernetes.io/ssl-redirect: '443'

grafana:
  defaultDashboardsTimezone: Asia/Seoul
  adminPassword: prom-operator

  ingress:
    enabled: true
    ingressClassName: alb
    hosts: 
      - grafana.$MyDomain
    paths: 
      - /*
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
      alb.ingress.kubernetes.io/group.name: study
      alb.ingress.kubernetes.io/ssl-redirect: '443'

  persistence:
    enabled: true
    type: sts
    storageClassName: "gp3"
    accessModes:
      - ReadWriteOnce
    size: 20Gi

defaultRules:
  create: false
kubeControllerManager:
  enabled: false
kubeEtcd:
  enabled: false
kubeScheduler:
  enabled: false
alertmanager:
  enabled: false

 

ExternalDNS의 alb로 배포하기 위해 prometheus-stack에서 prometheus와 grafana의 설정을 몇가지 수정하도록 하겠습니다.

 

위에 보시면 kube-controller-manager와 etcd, kube-scheduler등 Amazon EKS의 contorle plane은 Amazon에서 관리하는 영역은 수집할 수 없습니다.

 

helm 배포

helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 57.1.0 \
--set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s' \
-f monitor-values.yaml --namespace monitoring

 

 

배포 확인

  kubectl --namespace monitoring get pods -l "release=kube-prometheus-stack"

 

 

생성된 Pod들을 살펴보겠습니다.

 

grafana

프로메테우스는 메트릭 정보를 저장하는 용도로 사용하며, 그라파나로 시각화 처리를 합니다.

 

prometheus-0

모니터링 대상이 되는 파드는 ‘exporter’라는 별도의 사이드카 형식의 파드에서 모니터링 메트릭을 노출, pull 방식으로 가져와 내부의 시계열 데이터베이스에 저장합니다.

 

node-exporter

노드 익스포터는 물리 노드에 대한 자원 사용량(네트워크, 스토리지 등 전체) 정보를 메트릭 형태로 변경하여 노출합니다.

 

operator

시스템 경고 메시지 정책(prometheus rule), 애플리케이션 모니터링 대상 추가 등의 작업을 편리하게 할수 있게 CRD 지원합니다.

 

kube-state-metrics

쿠버네티스의 클러스터의 상태(kube-state)를 메트릭으로 변환하는 파드입니다.

 

 

AWS ELB(ALB) 갯수 확인

 

AWS Managed Console > EC2 > 로그밸런서 > 리로스맵에 접근해서 리스너(OSI 7계층에 해당하는 HTTP/HTTPS)별로 어떤 규칙에 의해 어떤 대상 그룹에 전달되는지 확인하실 수 있습니다.

 

쉽게 말해 Ingress에서 /metric의 경로에 설정한 pod가 있을 때 유저가 test.com/metric으로 접근한다면 해당 대상그룹으로 전송됩니다.

 

 

즉, 저와 같은 경우엔 lakescript.net이라는 host가 존재하며 grafana, prometheus로 서브 도메인을 설정하였고 각각 grafana와 prometheus pod로 트래픽을 전달합니다.

 

 

Prometheus 실습

prometheus는 일반적으로 모니터링 대상이 되는 서비스의 /metric 엔드포인트에 다양한 metric 정보를 수집합니다. 이후 프로메테우스는 해당 경로에 HTTP/GET 방식으로 metric 정보를 가져와 TSDB 형식으로 저장합니다.

 

노출 경로 확인

kubectl get node -owide
kubectl get svc,ep -n monitoring kube-prometheus-stack-prometheus-node-exporter

 

 

위의 사진처럼 Prometheus가 각 서비스의 9100 port에 접속하여 메트릭 정보를 수집합니다. 그렇기에 worker node 9100 port의  /metrics 경로에 접속 시 다양한 메트릭 정보를 확인 할 수 있습니다. (마스터 이외에 워커노드도 확인 가능합니다.)

 

프로메테우스 ingress 도메인으로 Web 접속

kubectl get ingress -n monitoring kube-prometheus-stack-prometheus

 

HOSTS에 출력된  URL에 접근하면 아래와 같이 정상적으로 접근하실 수 있습니다.!

 

 

Metric Target 확인

prometheus에서 다양한 metric 데이터를 수집하고 있는데, 어떤 것들인지 수집되고 있는지 확인해보겠습니다.

 

 

prometheus url에 접근하고 Status>Targets에 접근하면 아래와 같이 현재 어떤 targets들이 수집되고 있는지 확인하실 수 있습니다.

 

 

 

각 node의 9100 port로 각 node들의 metric 데이터를 수집하고 있는지 확인해보겠습니다.

 

 

마찬가지로 Status>Targets에 접근하여 kube-prometheus-stack-prometheus-node-exporter를 보시면 각 node의 9100/metric이 node의 metric 데이터를 수집하고 있는 것을 확인하실 수 있습니다.

 

 

Configure 확인

 

현재 어떤 설정에 의해 prometheus가 구성되었고, 실행중인지 파악하려면 Status>Configuration에 접근합니다.

 

그럼 위의 사진처럼 Configuration 정보들을 확인할 수 있습니다. 

 

이중 node-exporter 설정을 한번 보도록 하겠습니다.

global:
  scrape_interval: 15s     # 메트릭 가져오는(scrape) 주기
  scrape_timeout: 10s      # 메트릭 가져오는(scrape) 타임아웃
  evaluation_interval: 15s # alert 보낼지 말지 판단하는 주기
...
- job_name: serviceMonitor/monitoring/kube-prometheus-stack-prometheus-node-exporter/0
  scrape_interval: 30s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
...
kubernetes_sd_configs:    # 서비스 디스커버리(SD) 방식을 이용하고, 파드의 엔드포인트 List 자동 반영
  - role: endpoints
    kubeconfig_file: ""
    follow_redirects: true
    enable_http2: true
    namespaces:
      own_namespace: false
      names:
      - monitoring        # 서비스 엔드포인트가 속한 네임 스페이스 이름을 지정, 서비스 네임스페이스가 속한 포트 번호를 구분하여 메트릭 정보를 가져옴

 

위에서 주석으로 적혀져있는 것을 보셨듯이 중요한 정보를 정리하면 아래와 같습니다.

 

- global.scrape_interval:  메트릭 가져오는(scrape) 주기

- global.scrape_timeout:  메트릭 가져오는(scrape) 타임아웃

- global.evaluation_interval: alert 보낼지 말지 판단하는 주기

- kubernetes_sd_configs: 서비스 디스커버리(SD) 방식을 이용하고, 파드의 엔드포인트 List 자동 반영

- kubernetes_sd_configs.namespaces.names: 서비스 엔드포인트가 속한 네임 스페이스 이름을 지정(서비스 네임스페이스가 속한 포트 번호를 구분하여 메트릭 정보를 가져옴)

 

Graph 확인

node_exporter metric

node_exporter로 수집된 값들을 보실려면 node만 입력후 자동완성으로 검색되는 값들을 확인하실 수 있습니다.

 

그 중 node_memory_Active_bytes를 한번 확인해보겠습니다.

 

node_memory_Active_bytes

 

출력되는 metric 정보는 node-exporter 를 통해서 총 3개의 노드에서 수집된 정보입니다.

 

node_memory_Active_bytes{instance="192.168.1.105:9100"}

 

이렇듯 {instance=} 구문을 통해 특정 instance의 node_memory_Active_bytes 값을 확인하실 수 있습니다.

 

 

kube-state-meric

kubenetes-api를 통해 Deployments나 CronJob등 다양한 Kind의 값들을 수집합니다.

 

대표적으로 kube_deployment 입력시 나오는 값들이 kube-state-metirc 데이터입니다.

 

 

 

kube_deployment_status_replicas

 

kube_deployment_status_replicas 쿼리를 입력 후 실행하면 오른쪽에 replicas들의 숫자들이 출력됩니다.

 

kube_deployment_status_replicas_available{deployment="coredns"}

codedns pod의 숫자를 확인해보겠습니다.

 

 

현재는 2개로 확인하실 수 있는데, replicas를 3개로 늘려보겠습니다.

kubectl scale deployment -n kube-system coredns --replicas 3

 

 

 

그러고 다시 kube_deployment_status_replicas_available{deployment="coredns"} 쿼리를 입력하니 3개로 보여지는 것을 확인하실 수 있습니다!

 

애플리케이션 모니터링 실습

nginx 를 helm 설치 시 Prometheus Exporter 옵션을 설정 하여 자동으로 nginx 를 프로메테우스 모니터링에 등록 가능합니다. 또한 프nginx 모니터링 관련 내용을 서비스 모니터 CRD로 추가 가능하며 기존 애플리케이션 파드에 프로메테우스 모니터링을 추가하려면 사이드카 방식을 사용하며 exporter 컨테이너를 추가하면 됩니다.

 

NGINX 배포

helm repo 추가

helm repo add bitnami https://charts.bitnami.com/bitnami

 

파라미터 파일 생성

metrics:
  enabled: true

  service:
    port: 9113

  serviceMonitor:
    enabled: true
    namespace: monitoring
    interval: 10s

 

서비스 모니터 방식으로 nginx 모니터링 대상을 등록하고, export 는 9113 포트 사용합니다.

 

파라미터 파일을 설정 파일로 사용하여 nginx 배포

helm install nginx bitnami/nginx --version 15.14.0 -f nginx_metric-values.yaml

 

배포 확인

kubectl get pod,svc,ep

 

 

Prometheus 확인

target 확인

 

Prometheus에서 Target 확인하면 위의 사진과 같이 serviceMonitor/monitoring/nginx/0 이 생성된 것을 보실 수 있습니다.

 

Configurations 확인

 

nginx의 설정이 추가 되었는데, 주요 config가 적용될 시에 reloader하여 설정이 자동으로 반영됩니다.

 

 

Graph 확인

현재 nginx deployments의 갯수는 1개입니다. 해당 데이터는 nginx_up을 통해 확인하실 수 있습니다.

 

kubectl scale deployment nginx --replicas 2

 

위 명령어를 통해 nginx deployment의 수를 2개로 늘린 후 다시 확인해보겠습니다.

 

 

위처럼 2개로 정상적으로 확인하실 수 있습니다.

 

PromQL

PromQL은 Prometheus Query으로써 metric으로 수집된 데이터를 의미있는 값으로 가공할 수 있는 일종의 Query언어입니다.

 

프로메테우스 메트릭 종류에는 Counter, Gauge, Histogram, Summary가 있습니다.

- Gauge : 특정 시점의 값을 표현하기 위해서 사용하는 메트릭 타입, CPU 온도나 메모리 사용량에 대한 현재 시점 값

- Counter : 누적된 값을 표현하기 위해 사용하는 메트릭 타입, 증가 시 구간 별로 변화(추세) 확인, 계속 증가 → 함수 등으로 활용

- Summary : 구간 내에 있는 메트릭 값의 빈도, 중앙값 등 통계적 메트릭

- Histogram : 사전에 미리 정의한 구간 내에 있는 메트릭 값의 빈도를 측정 → 함수로 측정 포맷을 변경

 

 

Label Matchers

node_memory_Active_bytes
node_memory_Active_bytes{instance="192.168.1.188:9100"}
node_memory_Active_bytes{instance!="192.168.1.188:9100"}

 

 

정규표현식

node_memory_Active_bytes{instance=~"192.168.+"}
node_memory_Active_bytes{instance=~"192.168.1.+"}

 

다수 대상

node_memory_Active_bytes{instance=~"192.168.1.188:9100|192.168.2.170:9100"}
node_memory_Active_bytes{instance!~"192.168.1.188:9100|192.168.2.170:9100"}

 

여러 조건 AND

kube_deployment_status_replicas_available{namespace="kube-system"}
kube_deployment_status_replicas_available{namespace="kube-system", deployment="coredns"}

 

Aggregation Operators (집계 연산자)

sum : 조회된 값들을 모두 더함

min : 조회된 값에서 가장 작은 값을 선택

max : 조회된 값에서 가장 큰 값을 선택

avg : 조회된 값들의 평균 값을 계산

group : 조회된 값을 모두 ‘1’로 바꿔서 출력

stddev : 조회된 값들의 모 표준 편차를 계산

stdvar : 조회된 값들의 모 표준 분산을 계산

count : 조회된 값들의 갯수를 출력 / 인스턴스 벡터에서만 사용 가능

count_values : 같은 값을 가지는 요소의 갯수를 출력

bottomk : 조회된 값들 중에 가장 작은 값들 k 개 출력

topk : 조회된 값들 중에 가장 큰 값들 k 개 출력

quantile : 조회된 값들을 사분위로 나눠서 (0 < $ < 1)로 구성하고, $에 해당 하는 요소들을 출력

 

 

출력 값 중 Top 3

topk(3, node_memory_Active_bytes)

 

 

 

출력 값 중 하위 3

bottomk(3, node_memory_Active_bytes)

 

 

 

 

node 그룹별: by

avg(node_cpu_seconds_total) by (instance)

 

 

 

 

활용

파드별로 container가 사용중인 메모리를 MB 크기로 확인해보겠습니다.

sum(container_memory_working_set_bytes) by (pod)/1024/1024

 

 

 

 

 

 

 


Reference

- https://leehosu.github.io/kube-prometheus-stack