본문 바로가기

DevOps

[AWS EKS] Observability (3) Metric Server / Cadvisor / Prometheus Stack

CloudNet@팀의 EKS 스터디 AEWS 2기에 작성된 자료를 토대로 작성합니다.

 

옵저버빌리티에 모니터링 부분과 Alert 부분을 Prometheus Stack을 기반으로 활용하여 EKS 클러스터의 메트릭을 수집하고 모니터링 하는데 이번 포스팅에 목적이 있습니다.

 

cAdvisor                                                                                                                              

 

쿠버네티스를 사용하다 보면 수많은 컨테이너와 그에 대한 리소스들을 어떻게 인프라 영역과 컨테이너 영역에서 

모니터링 할수 있을가에 대한 고민을 하게됩니다.

 

다양한 오케스트레이션 작업(스케줄링, 컨테이너 자원 요청및 제한, HPA) 을 수행 하는 쿠버네티스는 스케줄러,

Kubelet 및 컨트롤러같은 클러스터 구성요소에서 클러스터 메트릭을 수집, 분석해야 합니다.

 

특히 클러스터의 다양한 애플리케이션 및 구성 요소가 현재 얼마나 많은 CPU, 메모리 및 네트워크

리소스를 사용하고 있는지 알아야 합니다.

리눅스에서는 top , mpstat 등의 명령어로 확인하던 리소스 사용률을 쿠버네티스에서는 어떻게 관리할까요?

 

Kubernetes는 이러한 메트릭(cpu,memory,network) 을 제공하는 모니터링 솔루션인 cAdvisor를 기본으로 제공합니다.

cAdvisor는 컨테이너에 대한 정보를 수집, 처리 및 내보내는 데몬입니다.

특히 cAdvisor는 컨테이너 기간별 리소스 사용량, 현재 또는 과거 리소스 사용량, 전체 리소스 사용량 히스토그램 및 네트워크 통계 등에 대한 정보를 유지합니다.

 

cAdvisor는 Kubelet 바이너리의 일부이므로 Kubelet과 긴밀하게 결합됩니다. Kubelet은 노드에서 컨테이너를 실행하고 관리하는 기본 노드 에이전트 입니다.

 

또한 , cAdvisor는 cgroups에 관한 메트릭을 제공한다. cgroups는 리눅스 커널 격리 기능으로서, 일반적으로 리눅스 상의 컨테이너를 구현하기 위해 사용되며, systemd 같은 런타임 환경에서도 쓰인다.

cAdvisor을 계측하고자 하는 어플리케이션에 설치하고 정상적으로 로드가 되면, container의 cpu와 메모리에 대한 메트릭을 수집할수 있다.

Metric Server                                                                                                                                        

  • Metric server은 Kubelet으로 수집한리소스 메트릭을 수집 및 집계하는 클러스터 애드온 구성 요소이다

  • 기본적으로 native k8s와 eks 환경에서 모두 인스톨 base 설치할수 있는데 해당 메트릭은 cAdvisor을 통해 가져온다
# 배포
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴
kubectl get pod -n kube-system -l k8s-app=metrics-server
kubectl api-resources | grep metrics
kubectl get apiservices |egrep '(AVAILABLE|metrics)'

# 노드 메트릭 확인
kubectl top node

# 파드 메트릭 확인
kubectl top pod -A
kubectl top pod -n kube-system --sort-by='cpu'
kubectl top pod -n kube-system --sort-by='memory'

Prometheus                                                                                                                                    

실제 운영단계의 쿠버네티스 클러스터를 계획하고 있다면, 모니터링 시스템은 반드시 구축해야 하며, 어떠한 상황에서 어떠한 모니터링 데이터를 확인 해야 하는지를 알고 있어야 합니다.

 

  • 프로메테우스는 성능, 사용성 및 다른 도구와의 호환성 등 여러 측면에서 우수하다고 평가되는 시계열 데이터 베이스입니다. 
  • PromQL : 유연한 쿼리 언어로서 활용성이 높습니다.
  • 분산 저장에 의존하지 않음 - 단일 서버 노드가 자립적으로 작동합니다.
  • HTTP를 통한 풀 모델: 시계열 데이터 수집이 HTTP를 통해 이루어집니다.

Pull-Based Monitoring

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

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

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

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

 

 

Exporter

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

Prometheus Server

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

Grafana

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

Alertmanager

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

 

 

 

 Prometheus Stack                                                                                                                                  

 Prometheus Stack                                                                                                                                  

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

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

 Prometheus Stack 실습                                                                                                                                  

✅ Helm을 통한 고가용성을 고려한 Prometheus Stack 설치
 

Helm 저장소 추가 
# helm repo add <저장소> https://{{ 다운로드 받을 helm chart}}


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

설치 
# 모니터링
kubectl create ns monitoring
watch kubectl get pod,pvc,svc,ingress -n monitoring

# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo "alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN"

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

# 파라미터 파일 생성
cat <<EOT > ~/monitor-values.yaml
alertmanager:
  ingress:
    enabled: true
    ingressClassName: alb
    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/group.name: "monitoring"
    hosts:
      - alertmanager.$CLUSTER_NAME
    paths:
      - /*

grafana:
  defaultDashboardsTimezone: Asia/Seoul
  adminPassword: prom-operator
  ingress:
    enabled: true
    ingressClassName: alb
    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/group.name: "monitoring"
    hosts:
      - grafana.$CLUSTER_NAME
    paths:
      - /*

prometheus:
  ingress:
    enabled: true
    ingressClassName: alb
    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/group.name: "monitoring"
    hosts:
      - prometheus.$CLUSTER_NAME
    paths:
      - /*
  prometheusSpec:
    serviceMonitorSelectorNilUsesHelmValues: false
    retention: 5d
    retentionSize: "10GiB"
EOT

# 배포
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 45.0.0 -f monitor-values.yaml --namespace monitoring

# 확인
## alertmanager-0 : 사전에 정의한 정책 기반(예: 노드 다운, 파드 Pending 등)으로 시스템 경고 메시지를 생성 후 경보 채널(슬랙 등)로 전송
## grafana : 프로메테우스는 메트릭 정보를 저장하는 용도로 사용하며, 그라파나로 시각화 처리
## prometheus-0 : 모니터링 대상이 되는 파드는 ‘exporter’라는 별도의 사이드카 형식의 파드에서 모니터링 메트릭을 노출, pull 방식으로 가져와 내부의 시계열 데이터베이스에 저장
## node-exporter : 노드익스포터는 물리 노드에 대한 자원 사용량(네트워크, 스토리지 등 전체) 정보를 메트릭 형태로 변경하여 노출
## operator : 시스템 경고 메시지 정책(prometheus rule), 애플리케이션 모니터링 대상 추가 등의 작업을 편리하게 할수 있게 CRD 지원
## kube-state-metrics : 쿠버네티스의 클러스터의 상태(kube-state)를 메트릭으로 변환하는 파드
helm list -n monitoring
kubectl get pod,pvc,svc,ingress -n monitoring
kubectl get-all -n monitoring
kubectl get prometheus,alertmanager -n monitoring
kubectl get prometheusrule -n monitoring
kubectl get servicemonitors -n monitoring
kubectl krew install df-pv && kubectl df-pv

 

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

 

grafana

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

 

prometheus-0

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

 

node-exporter

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

 

operator

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

 

kube-state-metrics

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

 

 Prometheus 설치 확인                                                                                                                                 

  • 프로메테우스는 PromQL을 사용하여 시계열 메트릭을 수집한다.
  • Pod 와 서비스 단위의 모니터링을 개발해야 할때, 프로메테우스에서는 container_cpu_seconds_total 데이터와 container_memory_work_bytes 데이터를 가공하여 PromQL을 적용시켜 원하는 데이터를 추출 
  • 메모리는 정량적인 사용량 기반으로 메트릭을 단순하게 뽑아낼수 있는데,  cpu는 core에 대한 영향을 받기 때문에 함수 이용
kubectl get node -owide
kubectl get svc,ep -n monitoring kube-prometheus-stack-prometheus-node-exporter

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

  • External DNS로 ingress 도메인에 접속할수 있음
kubectl get ingress -n monitoring kube-prometheus-stack-prometheus
kubectl get pod,svc,ingress,pvc -n monitoring
kubectl get-all -n monitoring

 

  • AWS ELB(ALB) 갯수 확인 → Rule 확인(어떻게 여러 도메인 처리를 하는 걸까?) ⇒ HTTP(80) 인입 시 어떻게 처리하나요?

  • 접속 화면 출력 ( 접속화면 상단 Status - Targets )

 

 

 PromQL 쿼리 작성해보기                                                                                                                

  • 컨테이너 cpu 평균 사용 시간을 구하는 이유? 

CPU는 메모리나 디스크처럼 현재 사용량을 정량적으로 나타내기 어렵다. 단일 CPU 코어는 1초동안 다양한 애플리케이션에서 오는 요청을 처리할수 있다. 이는 운영체제의 스케쥴러 덕분인데, 스케쥴러는 CPU 시간을 여러 프로세스 및 스레드 간에 공평하게 분배하는 역할을 한다.

운영 체제는 각 애플리케이션을 실행하는데 필요한 작업을 작은 '시간 조각(time slice)'으로 나눈다. 이 시간 조각은 보통 밀리세컨드(ms) 단위로, 운영 체제의 스케줄러는 이러한 시간 조각을 사용하여 각 애플리케이션에 CPU의 사용 시간을 할당한다.

이 과정을 통해 CPU 코어는 동시에 여러 애플리케이션을 처리하는 것처럼 보이게 된다. 그러나 실제로는 CPU 코어가 매우 빠른 속도로 각 애플리케이션의 작업을 전환하면서 이루어지고, 이를 컨텍스트 스위칭이라 한다. 이러한 방식으로, 단일 CPU 코어는 1초 동안 수천 개의 작업을 처리할 수 있다.

이 때문에 cpu의 사용량은 초 단위로 구해진다.
예를 들어 한 시간(3600초) 동안 cpu가 실제로 사용된 시간은(!=idle mode) 100초인 경우 실제 사용량은 100 / 3600 것이다.

프로메테우스에서 cpu 사용량을 알 수 있는 쿼리는 다음과 같다

 

 

  • "container_cpu_usage_seconds_total" 지표의 값은 초 (seconds) 단위입니다
# ---컨테이너 전부다
container_cpu_usage_seconds_total


# ---컨테이너 namespace 

container_cpu_usage_seconds_total{namespace="istio-system"}

# ---컨테이너 / namespace ^ pod name 분류해서 가져오기

container_cpu_usage_seconds_total{namespace="default",pod="nginx-7f7b5d655f-wqsrn"}

전체 컨테이너 cpu 사용량
특정 네임스페이스의 컨테이너 cpu 사용량

 

 

 

top으로 확인 하면 현재 사용하고 있는 코어의 단위가 나오는데 이 단위와 위에 프로메테우스에서 이용한 cpu 사용량은 왜 값이 

정확히 다를까? 그것은 단위의 문제이다.

 CPU(cores)의 단위는 1/1000코어이다.

  • 338m means 338 millicpu. 1000m is equal to 1 CPU, hence 338m means 33.8% of 1 CPU.

하지만 PromQL은 cpu의 사용량을 구한것이다. 이 사용량은 시간이 단위이다. 

값은 노드(또는 POD )가 실행된 이후부터 지금까지의 cpu사용량을 초단위로 나타낸 것이다.

 

(koo@myeks:N/A) [root@myeks-bastion ~]# kubectl top node
NAME                                               CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ip-192-168-1-216.ap-northeast-2.compute.internal   101m         2%     1228Mi          8%
ip-192-168-2-194.ap-northeast-2.compute.internal   89m          2%     1237Mi          8%
ip-192-168-3-61.ap-northeast-2.compute.internal    101m         2%     1008Mi          6%

 

top으로 node를 확인해보면 CPU 사용률도  나와있는것도 볼수있다.