Kubernetes

kubernetes 스터디 4주차

들어가며

  4주차에 배운 내용은 모니터링입니다. DevOps에서 모니터링은 매우 중요합니다. DevOps 접근 방식은 스테이징, 테스트 및 더 나아가 개발 환경까지 지속적 모니터링을 확장합니다. 최근 애자일 개발론이 유행하며 개발자의 잦은 코드 변경과 지속적 통합 및 배포로 인한 잦은 코드 변경으로 인해 변경 속도가 빨라지고 프로덕션 환경이 점점 더 복잡해졌습니다. 이러한 이유로 DevOps 팀에게 모니터링 시스템을 구축하는 것은 선택이 아닌 필수라 할 수 있습니다.

 

시스템 모터링

시스템 운영에 모니터링이 필요한 이유는 다음과 같습니다. 

특히 마이크로 서비스를 도입한 조직은 대부분의 서비스를 컨테이너 기반의 쿠버네티스 플랫폼위에서 실행할 것입니다. 

현재 쿠버네티스에서 가장 많이 사용하고 있는 모니터링 도구는 당연히 Prometheus 입니다. 

쿠버네티스에서 prometheus를 사용하는 이유는 클러스터에 배포되어 있는 오브젝트를 관리자가 항상 지켜보고 있을수 없기 때문입니다.

이러한 이유로, 

시스템 메트릭 수집에 Prometheus 를 사용하고,

시각화에 Grafana 를 사용합니다. 

 

kube prometheus stack 

프로메테우스는 노드, 컨테이너, 파드의 메트릭 값을 시계열 데이터 베이스에 저장하고 분석과 알림 등 모니터링에 필요한 기능을 제공합니다. 중앙 서버에서 노드의 데이터를 pull 하는 방식을 사용합니다. node_exporter가 실제 매트릭을 수집합니다. 프로메테우스가 서버에 데이터를 요청하면 요청받은 서버에서 데이터를 보내줌 (pull방식)

 

  *메트릭이란? 시스템의 상태를 알수있는 측정값으로 시스템 메트릭(서버 자원 사용량)과 서비스 메트릭(HTTP같은 상태코드)으로 나뉩니다.

 

 

그럼, 프로메테우스가 수집하는 지표의 종류와 지표를 노출하는 것에는 무엇이 있을까요 ? 

- cAdvisor

컨테이너의 지표를 노출하는 역할을 담당
cAdvisor 란 쿠버네티스에서 사용하는 기본적인 모니터링 에이전트로, kubelet 에 통합되어 개별 컨테이너의 메트릭 정보를 가져올 수 있습니다. 수집된 메트릭 값은 메모리에 잠시 저장되고 장시간 저장하진 않기 때문에 프로메테우스와 같은 시계열 DB에 메트릭 값을 저장해야 할 필요가 있습니다.

 

- kube-state-metrics

프로메테우스를 배포하면 kube-state-metrics가 설치되는데, 쿠버네티스 클러스터의 다양한 매트릭 정보를 수집하여 HTTP 엔드포인트를 통해 제공하는 작업을 수행합니다. API 서버로 쿠버네티스 클러스터의 메트릭 정보를 수집한 후, 이를 프로메테우스 서버가 수집할 수 있는 메트릭 데이터로 변환해 공개하는 역할을 합니다.

즉 kubelet(cadvisor) 메트릭 수집 → k8s api server ← kube-state-metrics 수집 후 HTTP로 노출 ← 프로메테우스 서버에서 수집

 

- node exporter

노드의 시스템 메트릭 정보를 프로메테우스가 수집할 수 있게 http로 공개하는 역할을 한다. Daemonsets으로 배포되어 각 노드의 메트릭을 수집한다. ( 노드를 구성하는 하드웨어와 관련된 정보)

 

- dcgm exporter

데몬셋으로 배포되어 각 노드에 탑재된 GPU 매트릭 정보를 수집한다.

 

 

프로메테우스를 설치하는 방법은 여러가지가 있습니다. 그중에 operator 패턴으로 prometheus, grafana를 관리하는 kube-prometheus-stack에 대해서 알아보겠습니다. 

 

kube-prometheus-stack구성요소

  • prometheus : 데이터를 요청하고 가져온 데이터를 저장하고 쿼리함
  • exporter: 요청을 받으면 데이터를 만들어서 요청자에게 리턴해 준다. 노드의 시스템 정보를 http로 공개하는 역할
  • push gateway : 데몬형태로 프로그램이 떠있는게 아니고 배치형태로 실행되고 사라지는 프로세스는 pull을 할수가 없으므로 이걸 이용해서 prometheus에 보내준다.
  • alarm manager : 데이터가 특정 조건이 되면 알림을 알려준다. (슬랙 또는 이메일 등등 많다.)
  • dashboard : 웹화면으로 데이터를 보여준다. 기본적인 화면이 prometheus가 가지고 있으니 Grafana를 대부분 사용한다.

 

설치

# kube-prometheus-stack repo 추가
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# repo update
$ helm repo update

# values 파일 작성
$ git clone https://github.com/prometheus-community/helm-charts.git
$ cd /charts/kube-prometheus-stack
$ vi monitor-values.yaml

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:
      - {domain 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:
      - {domain 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:
      - {domain name}

    paths:
      - /*

  prometheusSpec:
    podMonitorSelectorNilUsesHelmValues: false
    serviceMonitorSelectorNilUsesHelmValues: false
    retention: 5d
    retentionSize: "10GiB"
EOT


$ helm install -n prometheus prom prometheus-community/kube-prometheus-stack --values monitor-values.yaml

 

설치 확인

 

kube-prometheus-stack을 설치하면 grafana, prometheus, alertmanger가 기본적으로 설치됩니다. 

 

GPU 모니터링

최근 머신러닝 워크로드에 대한 수요가 늘면서 GPU 매트릭 모니터링도 중요하게되었다. NVIDIA는 DCGM (data center gpu manager) 라는 익스포터를 제공하는데, 이를 통해 GPU매트릭을 수집하여 Grafana에서 시각화 할 수 있다. 기본 매트릭 정보는 grafan에 설치된 dashboard 를 확인하면 되니 여기서는 GPU 매트릭 시각화에 대해서 확인해 보겠습니다. 

 

먼저 DCGM exporter를 설치합니다. 

helm repo add gpu-helm-charts \
https://nvidia.github.io/gpu-monitoring-tools/helm-charts

helm repo update

helm fetch --untar gpu-helm-charts/dcgm-exporter

# values.yaml 수정
# node affinity 추가 (gpu node에만 배포되도록)
  # node에 label 추가
# dcgm 메트릭 수집 주기가 30s 인데, probe 보다 높아서 에러가 발생한 것
  # 메트릭 수집주기를 아래처럼 낮춰준다. 
extraEnv:
  - name: "DCGM_EXPORTER_INTERVAL"
    value: "5000"
# operator차트를 통해 등록하지 않은 대상은 모니터링에서 제외하는 옵션이 true로 되어있는데 false로 바꿔주고 배포를 해야한다.
serviceMonitorSelectorNilUsesHelmValues: false

helm install -f values.yaml dcgm-exporter gpu-helm-charts/dcgm-exporter

# upgrad
helm upgrade -f values.yaml dcgm-exporter gpu-helm-charts/dcgm-exporter

dcgm exporter는 node exporter와 같이 데몬셋으로 gpu가 있는 노드에만 배포됩니다. 

dcgm exporter가 노출하는 매트릭값은 다음과 같습니다. ( https://github.com/NVIDIA/gpu-monitoring-tools/blob/master/etc/dcgm-exporter/dcp-metrics-included.csv )

 

수집한 매트릭을 Grafana를 사용해 시각화 해보겠습니다. 

 

그라파나 대시보드에 접속하여 11752 대시보드를 import 합니다

 

data source 로 prometheus 를 선택하고 설치를 완료합니다.

 

아래와 같이 수집한 GPU 매트릭을 대시보드에서 확인할 수 있습니다 ! 

 

(참고) 설치한 kube-prometheus-stack 을 삭제할 때 crd가 남이있는데 삭제가 필요합니다.

# helm 삭제
helm uninstall -n monitoring kube-prometheus-stack

# crd 삭제
kubectl delete crd alertmanagerconfigs.monitoring.coreos.com
kubectl delete crd alertmanagers.monitoring.coreos.com
kubectl delete crd podmonitors.monitoring.coreos.com
kubectl delete crd probes.monitoring.coreos.com
kubectl delete crd prometheuses.monitoring.coreos.com
kubectl delete crd prometheusrules.monitoring.coreos.com
kubectl delete crd servicemonitors.monitoring.coreos.com
kubectl delete crd thanosrulers.monitoring.coreos.com

 

Grafana 알람 기능 사용해보기

grafana에서 자체적으로 지원하는 알람 기능을 사용하여 알람을 보내는 테스트를 해보겠습니다. 

먼저, grafana 알람은 타임시리즈 패널에만 적용이 가능합니다. 

 

알람 시나리오 : 노드가 문제가 있을 때 알람이 오도록 설정

 

먼저 알람을 보낼 slack 채널 정보를 grafana 에 등록합니다.

slack 이라는 이름의 alert를 생성해 보겠습니다. webhook url은 slack채널에서 생성한 url을 입력합니다.

URL 입력 후 test 를 누르면 웹훅이 정상 작동하는지 테스트 메시지를 보냅니다. 

아래처럼 테스트 알람이 온것을 확인할 수 있습니다. 

 

다음은 notification policies 를 수정합니다. 

root policy의 기본값이 email로 되어 있는데 위에서 만든 슬랙 contact point 로 변경하고 저장합니다.

Specific routing을 사용해서 특정 알림은 정해진 contact point로만 알림이 가도록 설정할 수 있다.

 

Grafana대시보드에서 타임시리즈 패널을 하나 생성하고, metrics browser에 아래 쿼리를 입력합니다. 

ready 상태가 아니거나 , unknown 상태일 경우 체크하는 쿼리 입니다. 

kube_node_status_condition{condition="Ready",status="false",cluster=~""} or kube_node_status_condition{condition="Ready",status="unknown",cluster=~""}

쿼리를 작성하고  alert 를 눌러 알람을 생성합니다. 

알람 룰의 기본 정보를 입력합니다

conditions 을 B 쿼리의 값중 1이 (다운된노드) 확인되면 알람을 가도록 조건을 걸어줍니다. 

A 조건이 5분동안 지속되면 알람을 보내도록 시간을 설정합니다.

알람에 대한 추가정보를 입력할 수 있습니다. 기본값으로 두고 custom label에 알람을 slack으로 가도록 "alert=slack" 라벨을 추가해줍니다. 

알람을 적용하면 타임시리즈 패널의 타이틀에 하트가 표시됩니다. 초록색은 정상, 빨간색은 장애 발생을 의미합니다. 

 

마무리하며,

이상 쿠버네티스 환경에서 모니터링 및 알람에 대해서 간략하게 알아봤습니다. 

운영레벨에서 prometheus 가 다운될경우를 대비해서 thanos와 같은 도구도 검토해보면 좋을것 같다. 

(thanos는 multi prometheus를 대상으로 전역 쿼리를 제공하고, Prometheus 서버의 HA를 제공합니다. )