IT/Container&k8s

[k8s] Monitoring(Prometheus, Grafana, Loki)

Hayley Shim 2023. 10. 29. 00:41

안녕하세요. CloudNet@ K8S Study를 진행하며 해당 내용을 이해하고 공유하기 위해 작성한 글입니다. DevOps 이정훈님의 도서 ‘24단계 실습으로 정복하는 쿠버네티스’ 의 내용을 바탕으로 스터디를 하며 어떻게 k8s에 적용할지 고민하며 정리해봤습니다.

사전 환경

# YAML 파일 다운로드
$ curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-oneclick-f1.yaml

# CloudFormation 스택 배포 : 노드 인스턴스 타입 변경 - MasterNodeInstanceType=t3.medium WorkerNodeInstanceType=c5d.large
$ aws cloudformation deploy --template-file kops-oneclick-f1.yaml --stack-name mykops --parameter-overrides KeyName=kp-hayley3 SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName='wellbeconnected.com' S3StateStore='hayley-bucket-test' MasterNodeInstanceType=c5a.2xlarge WorkerNodeInstanceType=c5a.2xlarge --region ap-northeast-2

# CloudFormation 스택 배포 완료 후 kOps EC2 IP 출력
$ aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text

# 13분 후 작업 SSH 접속
$ ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)

# EC2 instance profiles 에 IAM Policy 추가(attach) : 처음 입력 시 적용이 잘 안될 경우 다시 한번 더 입력 하자! - IAM Role에서 새로고침 먼저 확인!
$ aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME
$ aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME

# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴

Metric Server

쿠버네티스에서메트릭 API(Metrics API) 는 자동 스케일링 및 비슷한 사용 사례를 지원하기 위한 기본적인 메트릭 집합을 제공합니다. 이 API는 노드와 파드의 리소스 사용량 정보를 제공하며, 여기에는 CPU 및 메모리 메트릭이 포함됩니다. [참고]

리소스 메트릭 파이프라인 아키텍처

위 아키텍처 구성요소는 아래와 같습니다.

  • cAdvisor: kubelet에 포함된 컨테이너 메트릭을 수집, 집계, 노출하는 데몬
  • kubelet: 컨테이너 리소스 관리를 위한 노드 에이전트. 리소스 메트릭은 kubelet API 엔드포인트 /metrics/resource  /stats 를 사용하여 접근 가능하다.
  • 요약 API: /stats 엔드포인트를 통해 사용할 수 있는 노드 별 요약된 정보를 탐색 및 수집할 수 있도록 kubelet이 제공하는 API
  • metrics-server: 각 kubelet으로부터 수집한 리소스 메트릭을 수집 및 집계하는 클러스터 애드온 구성 요소. API 서버는 HPA, VPA 및 kubectl top 명령어가 사용할 수 있도록 메트릭 API를 제공한다. metrics-server는 메트릭 API에 대한 기준 구현(reference implementation) 중 하나이다.
  • 메트릭 API: 워크로드 오토스케일링에 사용되는 CPU 및 메모리 정보로의 접근을 지원하는 쿠버네티스 API. 이를 클러스터에서 사용하려면, 메트릭 API를 제공하는 API 확장(extension) 서버가 필요하다.
# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴
$ kubectl get pod -n kube-system -l k8s-app=metrics-server
NAME                              READY   STATUS    RESTARTS   AGE
metrics-server-5f65d889cd-2kczm   1/1     Running   0          122m
metrics-server-5f65d889cd-7djfg   1/1     Running   0          122m

$ kubectl get apiservices |egrep '(AVAILABLE|metrics)'
NAME                                   SERVICE                      AVAILABLE   AGE
v1beta1.metrics.k8s.io                 kube-system/metrics-server   True        122m

# 노드 메트릭 확인
$ kubectl top node
NAME                  CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
i-03fc63391c0173dfa   127m         1%     2199Mi          13%
i-050bf5be7d03f3f78   35m          0%     1047Mi          6%
i-0b0b3876e6b26f550   33m          0%     992Mi           6%

# 파드 메트릭 확인
$ kubectl top pod -A

# CPU 높은 순으로 정렬되는 것 확인
$ kubectl top pod -n kube-system --sort-by='cpu'
NAME                                           CPU(cores)   MEMORY(bytes)
kube-apiserver-i-03fc63391c0173dfa             37m          329Mi
etcd-manager-main-i-03fc63391c0173dfa          16m          109Mi
kube-controller-manager-i-03fc63391c0173dfa    12m          52Mi
etcd-manager-events-i-03fc63391c0173dfa        7m           31Mi

# Memory 높은 순으로 정렬되는 것 확인
$ kubectl top pod -n kube-system --sort-by='memory'
NAME                                           CPU(cores)   MEMORY(bytes)
kube-apiserver-i-03fc63391c0173dfa             36m          330Mi
etcd-manager-main-i-03fc63391c0173dfa          15m          108Mi
ebs-csi-controller-8bcf48fc-9j7rb              3m           52Mi
kube-controller-manager-i-03fc63391c0173dfa    10m          52Mi

프로메테우스

Prometheus  SoundCloud 사에서 만들어진 monitoring과 alerting toolkit open-source systems 입니다.

주요 특징 & 기능

  • a multi-dimensional data model with time series data(=TSDB, 시계열 데이터베이스)
  • PromQL, a flexible query language
  • 수집방식:Pull방식(에이전트는 메트릭을 수집하며, 중앙 시스템으로 데이터 전송을 위한 정보가 보통 에이전트에 포함되어있다.)
  • service discovery지원
프로메테우스 아키텍처

프로메테우스 설치

# 모니터링
$ 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"
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:903575331688:certificate/3f025fab-6859-4cad-9d60-0c5887053d70

# 설치
$ 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.$KOPS_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.$KOPS_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.$KOPS_CLUSTER_NAME

    paths:
      - /*

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


# 배포
$ helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 45.7.1 \
--set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s' \
-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,svc,ingress -n monitoring
$ kubectl get-all -n monitoring
$ kubectl get prometheus,alertmanager -n monitoring
NAME                                                                VERSION   DESIRED   READY   RECONCILED   AVAILABLE   AGE
prometheus.monitoring.coreos.com/kube-prometheus-stack-prometheus   v2.42.0   1         0       True         False       24s

NAME                                                                    VERSION   REPLICAS   READY   RECONCILED   AVAILABLE   AGE
alertmanager.monitoring.coreos.com/kube-prometheus-stack-alertmanager   v0.25.0   1          0       True         False       24s

$ kubectl get prometheusrule -n monitoring

$ kubectl get servicemonitors -n monitoring

$ kubectl get crd | grep monitoring
alertmanagerconfigs.monitoring.coreos.com   2023-04-02T06:37:48Z
alertmanagers.monitoring.coreos.com         2023-04-02T06:37:48Z
podmonitors.monitoring.coreos.com           2023-04-02T06:37:48Z
probes.monitoring.coreos.com                2023-04-02T06:37:48Z
prometheuses.monitoring.coreos.com          2023-04-02T06:37:48Z
prometheusrules.monitoring.coreos.com       2023-04-02T06:37:48Z
servicemonitors.monitoring.coreos.com       2023-04-02T06:37:48Z
thanosrulers.monitoring.coreos.com          2023-04-02T06:37:48Z


# 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

프로메테우스 기본 사용

  • 모니터링 대상이 되는 서비스는 일반적으로 자체 웹 서버의 /metrics 엔드포인트 경로에 다양한 메트릭 정보를 노출합니다.
  • 이후 프로메테우스는 해당 경로에 http get 방식으로 메트릭 정보를 가져와 TSDB 형식으로 저장합니다.
# 아래 처럼 프로메테우스가 각 서비스의 9100 접속하여 메트릭 정보를 수집
$ kubectl get node -owide
NAME                  STATUS   ROLES           AGE    VERSION    INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
i-03fc63391c0173dfa   Ready    control-plane   177m   v1.24.11   172.30.40.130   13.125.243.173   Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18
i-050bf5be7d03f3f78   Ready    node            175m   v1.24.11   172.30.49.70    13.125.235.86    Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18
i-0b0b3876e6b26f550   Ready    node            175m   v1.24.11   172.30.92.67    54.180.99.208    Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18

$ kubectl get svc,ep -n monitoring kube-prometheus-stack-prometheus-node-exporter
NAME                                                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/kube-prometheus-stack-prometheus-node-exporter   ClusterIP   100.65.94.228   <none>        9100/TCP   3m20s

NAME                                                       ENDPOINTS                                                AGE
endpoints/kube-prometheus-stack-prometheus-node-exporter   172.30.40.130:9100,172.30.49.70:9100,172.30.92.67:9100   3m20s

# 마스터노드에 lynx 설치
$ ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME hostname
$ ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME sudo apt install lynx -y

# 노드의 9100번의 /metrics 접속 시 다양한 메트릭 정보를 확인할수 있음 : 마스터 이외에 워커노드도 확인 가능
$ ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME lynx -dump localhost:9100/metrics

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

# ingress 확인
$ kubectl get ingress -n monitoring kube-prometheus-stack-prometheus
NAME                               CLASS   HOSTS                            ADDRESS                                                                PORTS   AGE
kube-prometheus-stack-prometheus   alb     prometheus.wellbeconnected.com   k8s-monitoring-0096407009-272894402.ap-northeast-2.elb.amazonaws.com   80      5m20s

$ kubectl describe ingress -n monitoring kube-prometheus-stack-prometheus

# 프로메테우스 ingress 도메인으로 웹 접속
$ echo -e "Prometheus Web URL = https://prometheus.$KOPS_CLUSTER_NAME"
Prometheus Web URL = https://prometheus.wellbeconnected.com

# 웹 상단 주요 메뉴 설명
1. 경고(Alert) : 사전에 정의한 시스템 경고 정책(Prometheus Rules)에 대한 상황
2. 그래프(Graph) : 프로메테우스 자체 검색 언어 PromQL을 이용하여 메트릭 정보를 조회 -> 단순한 그래프 형태 조회
3. 상태(Status) : 경고 메시지 정책(Rules), 모니터링 대상(Targets) 등 다양한 프로메테우스 설정 내역을 확인 > 버전(2.42.0)
4. 도움말(Help)
프로메테우스 접속 화면

쿼리 입력 옵션

  • Use local time : 출력 시간을 로컬 타임으로 변경
  • Enable query history : PromQL 쿼리 히스토리 활성화
  • Enable autocomplete : 자동 완성 기능 활성화
  • Enable highlighting : 하이라이팅 기능 활성화
  • Enable linter : ?

프로메테우스 설정(Configuration) 확인 : Status → Runtime & Build Information 클릭

  • Storage retention : 5d or 10GiB → 메트릭 저장 기간이 5일 경과 혹은 10GiB 이상 시 오래된 것부터 삭제 ⇒ helm 파라미터에서 수정 가능
  • 프로메테우스 설정(Configuration) 확인 : Status → Command-Line Flags 클릭

— log.level : info

— storage.tsdb.retention.size : 10GiB

— storage.tsdb.retention.time : 5d

  • 프로메테우스 설정(Configuration) 확인 : Status → Configuration ⇒ “node-exporter” 검색

— job name 을 기준으로 scraping

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        # 서비스 엔드포인트가 속한 네임 스페이스 이름을 지정, 서비스 네임스페이스가 속한 포트 번호를 구분하여 메트릭 정보를 가져옴
  • 전체 메트릭 대상(Targets) 확인 : Status → Targets

— 해당 스택은 ‘노드-익스포터’, cAdvisor, 쿠버네티스 전반적인 현황 이외에 다양한 메트릭을 포함

— 현재 각 Target 클릭 시 메트릭 정보 확인

# serviceMonitor/monitoring/kube-prometheus-stack-kube-proxy/0 (3/3 up) 중 마스터 노드에 Endpoint 접속 확인
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME curl -s http://localhost:10249/metrics

# 그외 다른 타켓의 Endpoint 로 접속 확인 가능 : 예시) 아래는 coredns 의 Endpoint 주소 (접속 주소는 실습 환경에 따라 다름)
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME curl -s http://172.30.60.50:9153/metrics
  • 프로메테우스 설정(Configuration) 확인 : Status → Service Discovery : 모든 endpoint 로 도달 가능 시 자동 발견!, 도달 규칙은 설정Configuration 파일에 정의

— 예) serviceMonitor/monitoring/kube-prometheus-stack-apiserver/0 경우 해당 address=”172.30.62.105:443" 도달 가능 시 자동 발견됨

  • 메트릭을 그래프(Graph)로 조회 : Graph — 아래 PromQL 쿼리(전체 클러스터 노드의 CPU 사용량 합계)입력 후 조회 → Graph 확인

그라파나

TSDB 데이터를 시각화, 다양한 데이터 형식 지원합니다.(메트릭, 로그, 트레이스 등)

  • 접속 정보 확인 및 로그인 : 기본 계정 — admin / prom-operator
# ingress 확인
$ kubectl get ingress -n monitoring kube-prometheus-stack-grafana
NAME                            CLASS   HOSTS                         ADDRESS                                                                PORTS   AGE
kube-prometheus-stack-grafana   alb     grafana.wellbeconnected.com   k8s-monitoring-0096407009-272894402.ap-northeast-2.elb.amazonaws.com   80      39m

$ kubectl describe ingress -n monitoring kube-prometheus-stack-grafana
kube-prometheus-stack-grafana
Name:             kube-prometheus-stack-grafana
Labels:           app.kubernetes.io/instance=kube-prometheus-stack
                  app.kubernetes.io/managed-by=Helm
                  app.kubernetes.io/name=grafana
                  app.kubernetes.io/version=9.3.8
                  helm.sh/chart=grafana-6.51.5
Namespace:        monitoring
Address:          k8s-monitoring-0096407009-272894402.ap-northeast-2.elb.amazonaws.com
Ingress Class:    alb
Default backend:  <default>
Rules:
  Host                         Path  Backends
  ----                         ----  --------
  grafana.wellbeconnected.com
                               /   kube-prometheus-stack-grafana:80 (172.30.93.53:3000)
Annotations:                   alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:903575331688:certificate/3f025fab-6859-4cad-9d60-0c5887053d70
                               alb.ingress.kubernetes.io/group.name: monitoring
                               alb.ingress.kubernetes.io/listen-ports: [{"HTTPS":443}, {"HTTP":80}]
                               alb.ingress.kubernetes.io/scheme: internet-facing
                               alb.ingress.kubernetes.io/success-codes: 200-399
                               alb.ingress.kubernetes.io/target-type: ip
                               meta.helm.sh/release-name: kube-prometheus-stack
                               meta.helm.sh/release-namespace: monitoring
Events:
  Type    Reason                  Age   From     Message
  ----    ------                  ----  ----     -------
  Normal  SuccessfullyReconciled  39m   ingress  Successfully reconciled


# ingress 도메인으로 웹 접속
$ echo -e "Grafana Web URL = https://grafana.$KOPS_CLUSTER_NAME"
Grafana Web URL = https://grafana.wellbeconnected.com
  • configuration -Data sources 스택의 경우 자동으로 프로메테우스를 데이터 소스로 추가해둠
# 서비스 주소 확인
$ kubectl get svc,ep -n monitoring kube-prometheus-stack-prometheus

NAME                                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/kube-prometheus-stack-prometheus   ClusterIP   100.68.135.113   <none>        9090/TCP   47m

NAME                                         ENDPOINTS           AGE
endpoints/kube-prometheus-stack-prometheus   172.30.83.64:9090   47m

해당 데이터 소스 접속 확인

# 테스트용 파드 배포
$ kubectl apply -f ~/pkos/2/netshoot-2pods.yaml
$ kubectl get pod

# 접속 확인
$ kubectl exec -it pod-1 -- nslookup kube-prometheus-stack-prometheus.monitoring
Server:  169.254.20.10
Address: 169.254.20.10#53

Name: kube-prometheus-stack-prometheus.monitoring.svc.cluster.local
Address: 100.68.135.113

$ kubectl exec -it pod-1 -- curl -s kube-prometheus-stack-prometheus.monitoring:9090/graph -v
> GET /graph HTTP/1.1
> Host: kube-prometheus-stack-prometheus.monitoring:9090
> User-Agent: curl/7.87.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 02 Apr 2023 07:27:45 GMT
< Content-Length: 734
< Content-Type: text/html; charset=utf-8
<
* Connection #0 to host kube-prometheus-stack-prometheus.monitoring left intact
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><script>const GLOBAL_CONSOLES_LINK="",GLOBAL_AGENT_MODE="false",GLOBAL_READY="true"</script><link rel="manifest" href="./manifest.json" crossorigin="use-credentials"/><title>Prometheus Time Series Collection and Processing Server</title><script defer="defer" src="./static/js/main.c1286cb7.js"></script><link href="./static/css/main.cb2558a0.css" rel="stylesheet"></head><body class="bootstrap"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div>

# 삭제
$ kubectl delete -f ~/pkos/2/netshoot-2pods.yaml

대시보드 사용

  • 기본 대시보드
  • 공식 대시보드 : [1 Kubernetes All-in-one Cluster Monitoring KR] 13370 처럼 대시보드 ID를 Import 해서 적용할 수 있습니다.
ID 13370 대시보드 화면

NGINX 웹서버 배포 및 애플리케이션 모니터링 설정 및 접속

nginx 웹 서버 helm 설치

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

# 파라미터 파일 생성 : 서비스 모니터 방식으로 nginx 모니터링 대상을 등록하고, export 는 9113 포트 사용, nginx 웹서버 노출은 AWS CLB 기본 사용
$ cat <<EOT > ~/nginx-values.yaml
metrics:
  enabled: true

  service:
    port: 9113

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

# 배포
$ helm install nginx bitnami/nginx --version 13.2.23 -f nginx-values.yaml

# CLB에 ExternanDNS 로 도메인 연결
$ kubectl annotate service nginx "external-dns.alpha.kubernetes.io/hostname=nginx.$KOPS_CLUSTER_NAME"

# 확인
$ kubectl get pod,svc,ep
NAME                         READY   STATUS              RESTARTS   AGE
pod/nginx-697fd655bf-wfscg   0/2     ContainerCreating   0          9s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                       AGE
service/kubernetes   ClusterIP      100.64.0.1       <none>        443/TCP                       3h52m
service/nginx        LoadBalancer   100.70.203.119   <pending>     80:30480/TCP,9113:30790/TCP   9s

NAME                   ENDPOINTS           AGE
endpoints/kubernetes   172.30.40.130:443   3h52m
endpoints/nginx        <none>              9s

$ kubectl get servicemonitor -n monitoring nginx
NAME    AGE
nginx   9s


$ kubectl get servicemonitor -n monitoring nginx -o json | jq

# nginx 파드내에 컨테이너 갯수 확인
$ kubectl get pod -l app.kubernetes.io/instance=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-697fd655bf-wfscg   2/2     Running   0          52s


$ kubectl describe pod -l app.kubernetes.io/instance=nginx

# 접속 주소 확인 및 접속
$ echo -e "Nginx WebServer URL = http://nginx.$KOPS_CLUSTER_NAME"
Nginx WebServer URL = http://nginx.wellbeconnected.com

$ curl -s http://nginx.$KOPS_CLUSTER_NAME
$ kubectl logs deploy/nginx -f
Defaulted container "nginx" out of: nginx, metrics
nginx 07:35:57.09
nginx 07:35:57.09 Welcome to the Bitnami nginx container
nginx 07:35:57.09 Subscribe to project updates by watching https://github.com/bitnami/containers
nginx 07:35:57.09 Submit issues and feature requests at https://github.com/bitnami/containers/issues
nginx 07:35:57.10
nginx 07:35:57.10 INFO  ==> ** Starting NGINX setup **
nginx 07:35:57.11 INFO  ==> Validating settings in NGINX_* env vars
nginx 07:35:57.11 INFO  ==> No custom scripts in /docker-entrypoint-initdb.d
nginx 07:35:57.11 INFO  ==> Initializing NGINX
realpath: /bitnami/nginx/conf/vhosts: No such file or directory
nginx 07:35:57.12 INFO  ==> ** NGINX setup finished! **

nginx 07:35:57.13 INFO  ==> ** Starting NGINX **

# 반복 접속
$ while true; do curl -s http://nginx.$KOPS_CLUSTER_NAME -I | head -n 1; date; sleep 1; done
  • 위와 같이 서비스 모니터링 생성 후 프로메테우스 웹서버-> status -> targets에 nginx 서비스 모니터가 추가된 것을 확인할 수 있습니다.

Nginx 애플리케이션 모니터링 대시보드 추가

  • ID 12708 을 Import 해줍니다.

Kwatch

  • kwatch는 Kubernetes(K8s) 클러스터의 모든 변경 사항을 모니터링하고, 실행 중인 앱의 충돌을 실시간으로 감지하고, 채널에 알림을 게시하도록 도와줍니다.
# configmap 생성
cat <<EOT > ~/kwatch-config.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: kwatch
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: kwatch
  namespace: kwatch
data:
  config.yaml: |
    alert:
      slack:
        webhook: '접근할 webhook 주소'
        #title:
        #text:
    pvcMonitor:
      enabled: true
      interval: 5
      threshold: 70
EOT

$ kubectl apply -f kwatch-config.yaml

# 배포
$ kubectl apply -f https://raw.githubusercontent.com/abahmed/kwatch/v0.8.3/deploy/deploy.yaml

잘못된 이미지 파드 배포 확인

# 터미널1
$ watch kubectl get pod

# 잘못된 이미지 정보의 파드 배포
$ kubectl apply -f https://raw.githubusercontent.com/junghoon2/kube-books/main/ch05/nginx-error-pod.yml
$ kubectl get events -w

# 이미지 업데이트 방안2 : set 사용 - iamge 등 일부 리소스 값을 변경 가능!
$ kubectl set 
$ kubectl set image pod nginx-19 nginx-pod=nginx:1.19

# 삭제
$ kubectl delete pod nginx-19

Alerting 프로메테우스 Alert Manager

프로메테우스의 임곗값 도달 시 경고 메시지를 얼럿매니저에 푸시 이벤트로 전달하고, 얼럿매니저는 이를 가공후 이메일/슬랙 등에 전달합니다.

# EC2 인스턴스 모니터링
$ while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output text | sort; echo "------------------------------" ;date; sleep 1; done

# 인스턴스그룹 정보 확인
$ kops get ig
NAME    ROLE  MACHINETYPE MIN MAX ZONES
control-plane-ap-northeast-2a ControlPlane c5a.2xlarge 1 1 ap-northeast-2a
nodes-ap-northeast-2a  Node  c5a.2xlarge 1 1 ap-northeast-2a
nodes-ap-northeast-2c  Node  c5a.2xlarge 1 1 ap-northeast-2c

# 노드 추가
$ kops edit ig nodes-ap-northeast-2a --set spec.minSize=2 --set spec.maxSize=2

# 적용
$ kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster
NAME    STATUS NEEDUPDATE READY MIN TARGET MAX NODES
control-plane-ap-northeast-2a Ready 0  1 1 1 11
nodes-ap-northeast-2a  Ready 0  1 2 2 21
nodes-ap-northeast-2c  Ready 0  1 1 1 11

# 워커노드 증가 확인
$ while true; do kubectl get node; echo "------------------------------" ;date; sleep 1; done
프로메테우스 target에 alermanager service 생성

Alert Manager 접속

# ingress 도메인으로 웹 접속
$ echo -e "Alertmanager Web URL = https://alertmanager.$KOPS_CLUSTER_NAME"

Alert Manager 대시보드 karma 컨테이너로 실행

# 실행
$ docker run -d -p 80:8080 -e ALERTMANAGER_URI=https://alertmanager.$KOPS_CLUSTER_NAME ghcr.io/prymitive/karma:latest

# 확인
$ docker ps
CONTAINER ID   IMAGE                            COMMAND    CREATED         STATUS         PORTS                                   NAMES
ff49a779f0e9   ghcr.io/prymitive/karma:latest   "/karma"   4 seconds ago   Up 3 seconds   0.0.0.0:80->8080/tcp, :::80->8080/tcp   wizardly_margulis

Alert Manager 대시보드 karma 웹 접속 주소 확인

$ echo -e "karma Web URL = http://$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)"
karma Web URL = http://13.124.253.31

프로메테우스 웹 Alert & Alert Manager 웹 karma

  • 프로메테우스 웹 접속 후 상단 Alert 메뉴 확인 : 시스템 경고 정책은 prometheusrules CRD로 관리합니다.
# 프로메테우스 룰 확인
$ kubectl get prometheusrules -n monitoring
$ kubectl get prometheusrules -n monitoring kube-prometheus-stack-kubernetes-system-controller-manager -o json | jq

# 룰 전체 확인
$ kubectl get prometheusrules -n monitoring -o json | more

# 메트릭 이름 확인
$ kubectl get prometheusrules -n monitoring -o json | grep '"record":' | sed 's/^ *//'
$ kubectl get prometheusrules -n monitoring -o json | grep '"record":' | sed 's/^ *//' | wc -l
85

# 얼럿 이름 확인
$ kubectl get prometheusrules -n monitoring -o json | grep '"alert":' | sed 's/^ *//'

# 얼럿 갯수 확인
$ kubectl get prometheusrules -n monitoring -o json | grep '"alert":' | sed 's/^ *//' | wc -l
134

아래와 같이 3개의 Alert 개수가 확인됩니다.

슬랙 채널 및 웹훅 URL 생성 및 얼럿매니저 설정 적용

# 웹훅 URL 정보
https://hooks.slack.com/services/XXXXXXX
WEBHOOK='https://hooks.slack.com/services/XXXXXXX'


# 샘플 메시지 보내기
curl -X POST --data-urlencode "payload={\"channel\": \"#webhook2\", \"username\": \"pkosbot\", \"text\": \"$KOPS_CLUSTER_NAME 다음주 종강! - 봇 제공\"}" $WEBHOOK
curl -X POST --data-urlencode "payload={\"channel\": \"#webhook2\", \"username\": \"pkosbot\", \"text\": \"$KOPS_CLUSTER_NAME 다음주 종강! - 봇 제공\", \"icon_emoji\": \":ghost:\"}" $WEBHOOK

얼럿매니저에 웹훅 URL 정보 반영

cat <<EOT > ~/alertmanager-slack.yaml
alertmanager:
  config:
    global:
      resolve_timeout: 5m
      slack_api_url: 'https://hooks.slack.com/services/XXXXXXX'
    route:
      group_by: ['job']  # namespace
      group_wait: 10s
      group_interval: 1m
      repeat_interval: 5m
      receiver: 'slack-notifications'
      routes:
      - receiver: 'slack-notifications'
        matchers:
          - alertname =~ "InfoInhibitor|Watchdog"
    receivers:
    - name: 'slack-notifications'
      slack_configs:
      - channel: '#webhook2'
        send_resolved: true
        title: '[{{.Status | toUpper}}] {{ .CommonLabels.alertname }}'
        text: |
          *Description:* {{ .CommonAnnotations.description }}
EOT

# helm 업그레이드로 얼럿매니저에 웹훅 URL 정보 반영
$ helm upgrade kube-prometheus-stack prometheus-community/kube-prometheus-stack --reuse-values -f alertmanager-slack.yaml --namespace monitoring

PLG 스택

  • Promtail + Loki + Grafana 여러 파드의 로그들을 중앙 서버에 저장하고 이를 조회할 수 있습니다.

Loki 설치

  • Loki에 저장한 로그는 LogQL(PromQL과 유사)을 이용해 조회 할 수 있으며, 그라파나 웹이나 logcli를 이용해 조회 가능합니다.
# 모니터링
$ kubectl create ns loki
$ watch kubectl get pod,pvc,svc,ingress -n loki

# Repo 추가
$ helm repo add grafana https://grafana.github.io/helm-charts

# 파라미터 설정 파일 생성
$ cat <<EOT > ~/loki-values.yaml
persistence:
  enabled: true
  size: 20Gi

serviceMonitor:
  enabled: true
EOT

# 배포
$ helm install loki grafana/loki --version 2.16.0 -f loki-values.yaml --namespace loki

# 설치 확인 : 데몬셋, 스테이트풀셋, PVC 확인
$ helm list -n loki
$ kubectl get pod,pvc,svc,ds,sts -n loki
$ kubectl get-all -n loki
$ kubectl get servicemonitor -n loki
$ kubectl krew install df-pv && kubectl df-pv

# curl 테스트 용 파드 생성
$ kubectl delete -f ~/pkos/2/netshoot-2pods.yaml
$ kubectl apply -f ~/pkos/2/netshoot-2pods.yaml

# 로키 gateway 접속 확인
$ kubectl exec -it pod-1 -- curl -s http://loki.loki.svc:3100/api/prom/label

# (참고) 삭제 시
$ helm uninstall loki -n loki
$ kubectl delete pvc -n loki --all

Promtail 설치

  • Promtail은 데몬셋으로 실행되며 각 로그에 로그를 중앙 로키 서버에 전달, Promtail 외에도 도커, FluentD 등 다른 로그수집 에이전트 사용 할 수 있습니다.

# 파라미터 설정 파일 생성
$ cat <<EOT > ~/promtail-values.yaml
serviceMonitor:
  enabled: true
config:
  serverPort: 3101
  clients:
    - url: http://loki-headless:3100/loki/api/v1/push
#defaultVolumes:
#  - name: pods
#    hostPath:
#      path: /var/log/pods
EOT

# 배포
$ helm install promtail grafana/promtail --version 6.0.0 -f promtail-values.yaml --namespace loki

# (참고) 파드 로그는 /var/log/pods에 저장
$ ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME ls /var/log/pods

# 설치 확인 : 데몬셋, 스테이트풀셋, PVC 확인
$ helm list -n loki
$ kubectl get pod,pvc,svc,ds,sts,servicemonitor -n loki
$ kubectl get-all -n loki

# (참고) 삭제 시
$ helm uninstall promtail -n loki

그라파나에서 로그 확인

  • 아래와 같이 그라파나 Configuration — Data Source에 데이터 소스를 추가해줍니다.
  • HTTP URL : http://loki-headless.loki:3100 ⇒ Save & Test
  • Logfilters : Job → default/nginx 값 선택 ⇒ 우측 상단 Run query 클릭
  • Loki 로그 확인 대시보드 : 15141

자원 삭제

# nginx 삭제
$ helm uninstall nginx

# promtail 삭제
$ helm uninstall promtail -n loki

# loki 삭제
$ helm uninstall loki -n loki
$ kubectl delete pvc -n loki --all

# 프로메테우스 스택 삭제
$ helm uninstall -n monitoring kube-prometheus-stack


$ kops delete cluster --yes && aws cloudformation delete-stack --stack-name mykops

 

blog migration project

written in 2023.4.2

https://medium.com/techblog-hayleyshim/k8s-monitoring-prometheus-grafana-loki-6fe7cb22b576

 

'IT > Container&k8s' 카테고리의 다른 글

[k8s] cluster install - cri-o runtime error  (0) 2023.10.29
[k8s] Security  (0) 2023.10.29
[k8s] GitOps(Image registy, Source repository, Continuous Delivery)  (0) 2023.10.29
[k8s] Storage  (0) 2023.10.29
[k8s] Network  (0) 2023.10.29