교육, 커뮤니티 후기/PKOS 쿠버네티스 스터디

PKOS 쿠버네티스 스터디 6주차 - 얼럿매니저 로깅시스템

Somaz 2023. 2. 19. 22:07
728x90
반응형

스터디원 이현수님 제공

 

Overview

가시다님이 진행하시는 쿠버네티스 스터디 6주차가 되었다.

 

오늘은 얼럿매니저와 로깅시스템에 대하여 공부하는 시간이 되었다.

 

그림 실습 시라니오는 '24단계 실습으로 정복하는 쿠버네티스' 책을 기준으로 정리하였습니다.

 

 

 

6주차 과제 내용

 

[과제1]

책 367~372페이지(24단계 실습으로 정복하는 쿠버네티스)

사용자 정의 prometheusrules 정책 설정 : 파일 시스템 사용률 80% 초과 시 시스템 경고 발생시키기 ⇒ 직접 실습 후 관련 스샷을 올려주세요

 

먼저 Alert에서 Filesystem을 검색
기존 파일시스템 관련 정책을 확인하면 5% 미만일 경우 시스템 경고를 발생시키토록 되어있다.

 

# git cone
(somaz:monitoring) [root@kops-ec2 ~]# git clone https://github.com/wikibook/kubepractice.git

(somaz:monitoring) [root@kops-ec2 ~]# cd kubepractice/ch19/
(somaz:monitoring) [root@kops-ec2 ch19]# ls
node-exporter-prometheusrules.yaml

(somaz:monitoring) [root@kops-ec2 ch19]# kubectl krew install neat

# 확인하기
(somaz:monitoring) [root@kops-ec2 ch19]# k get prometheusrules.monitoring.coreos.com |grep node-exporter
kube-prometheus-stack-node-exporter                          3h28m
kube-prometheus-stack-node-exporter.rules                    3h28m

# 주의해서 작성(책이랑 다름)
(somaz:monitoring) [root@kops-ec2 ch19]# k get prometheusrules.monitoring.coreos.com kube-prometheus-stack-node-exporter -o yaml|k neat > node-exporter-prometheusrules.yaml

# 수정
$ vi node-exporter-prometheusrules.yaml

# 해당 정책 복사
    - alert: NodeFilesystemAlmostOutOfSpace
      annotations:
        description: Filesystem on {{ $labels.device }} at {{ $labels.instance }}
          has only {{ printf "%.2f" $value }}% available space left.
        runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemalmostoutofspace
        summary: Filesystem has less than 5% space left.
      expr: |-
        (
          node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 5
        and
          node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0
        )
      for: 30m
      labels:
        severity: warning

# 아래와 같이 변경

## 이름 변경
    - alert: NodeFilesystemAlmostOutOfSpace-20
      annotations:
        description: Filesystem on {{ $labels.device }} at {{ $labels.instance }}
          has only {{ printf "%.2f" $value }}% available space left.
        runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemalmostoutofspace
## summary 변경
        summary: Filesystem has less than 20% space left.
      expr: |-
        (
## 해당 100 < 5 -> 100 /20 으로 변경
          node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 20
        and
          node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0
        )
      for: 10m
      labels:
        severity: warning
        
        
 # 기존 kube-prometheus-stack-node-exporter 삭제 후 재생성
 (somaz:monitoring) [root@kops-ec2 ch19]# k get prometheusrules.monitoring.coreos.com |grep node-exporter
kube-prometheus-stack-node-exporter                          3h46m
kube-prometheus-stack-node-exporter.rules                    3h46m

(somaz:monitoring) [root@kops-ec2 ch19]# k delete prometheusrules.monitoring.coreos.com kube-prometheus-stack-node-exporter
prometheusrule.monitoring.coreos.com "kube-prometheus-stack-node-exporter" deleted

(somaz:monitoring) [root@kops-ec2 ch19]# ls
node-exporter-prometheusrules.yaml

(somaz:monitoring) [root@kops-ec2 ch19]# k apply -f node-exporter-prometheusrules.yaml
prometheusrule.monitoring.coreos.com/kube-prometheus-stack-node-exporter created

 

이제 아무 노드나 접속해 임의의 큰 파일을 생성해 여유공간이 20% 미만이 되게 한다.

# 워커 노드 퍼블릭 IP 확인
(somaz:monitoring) [root@kops-ec2 ch19]# aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table
-----------------------------------------------------------------
|                       DescribeInstances                       |
+--------------------------------------------+------------------+
|                InstanceName                |   PublicIPAdd    |
+--------------------------------------------+------------------+
|  nodes-ap-northeast-2c.somaz.link          |  15.164.221.204  |
|  nodes-ap-northeast-2a.somaz.link          |  13.125.199.131  |
|  nodes-ap-northeast-2a.somaz.link          |  3.39.229.111    |
|  master-ap-northeast-2a.masters.somaz.link |  3.36.78.41      |
|  kops-ec2                                  |  3.36.127.208    |
+--------------------------------------------+------------------+

# 워거 노드 접속
(somaz:monitoring) [root@kops-ec2 ch19]# W1PIP=13.125.199.131

# 용량 80% 넘기기

ubuntu@i-0da9df20f40730970:~$ sudo fallocate /var/100g -l 100g

ubuntu@i-0da9df20f40730970:~$ df -h
Filesystem       Size  Used Avail Use% Mounted on
/dev/root        124G  105G   19G  85% /

 

프로메테우스 확인

 

얼럿매니저 확인
karma 확인

 

슬랙 확인~

 

 

[과제2]

책 386~389페이지(24단계 실습으로 정복하는 쿠버네티스)

 

LogQL 사용법 익히기 ⇒ 직접 실습 후 관련 스샷을 올려주세요

 

아래의 사이트 참고하기

Introduction to Loki: Like Prometheus, but for Logs | Grafana Labs

 

먼저 grafana - explore - LOKI 선택

 

error log만 검색

error log만 검색

DEBUG log만 검색

 

DEBUG log만 검색

 

[과제3]

아래 1,2 과제 중 하나를 해주시면 됩니다

  1. Awesome Prometheus alerts 를 참고해서 스터디에서 배우지 않은 Alert Rule 생성 및 적용 후 관련 스샷을 올려주세요
  2. 그라파나에서 그래프 이미지를 포함한 알람을 슬랙에 전달하게 설정 후 관련 스샷을 올려주세요

Awesome Prometheus alerts 를 참고해서 스터디에서 배우지 않은 Alert Rule 생성 및 적용 후 관련 스샷 올리기

 

Awesome Prometheus alerts

Collection of alerting rules

awesome-prometheus-alerts.grep.to

 

링크 주소

https://awesome-prometheus-alerts.grep.to/

 

과제 1에서 사용했던 node-exporter-prometheusrules.yaml 사용하여 작성

(somaz:monitoring) [root@kops-ec2 ch19]# vi node-exporter-prometheusrules.yaml
...
spec:
  groups:
  - name: node-exporter
    rules:
    - alert: HostUnusualDiskReadRate
      expr: sum by (instance) (rate(node_disk_read_bytes_total[2m])) / 1024 / 1024 > 50
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: Host unusual disk read rate (instance {{ $labels.instance }})
        description: Disk is probably reading too much data (> 50 MB/s)\n  VALUE = {{ $value }}\n  LABELS = {{ $labels }}

(somaz:monitoring) [root@kops-ec2 ch19]# k delete prometheusrules.monitoring.coreos.com kube-prometheus-stack-node-exporter

(somaz:monitoring) [root@kops-ec2 ch19]# k apply -f node-exporter-prometheusrules.yaml
prometheusrule.monitoring.coreos.com/kube-prometheus-stack-node-exporter created

성공!!

 

 

스터디 주요내용

 

실습 환경 배포

 

실습 환경

 

kops 인스턴스 t3.small & 노드 c5.2xlarge (vCPU 8, Memory 16GiB) 배포 

 

이번주 실습에서 성능을 요구하는 파드를 사용한다.

  • Tip. 실행하는 PC에 aws cli 설치되어 있고, aws configure 자격증명 설정 상태.

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

# CloudFormation 스택 배포 : 노드 인스턴스 타입 변경 - MasterNodeInstanceType=c5.2xlarge WorkerNodeInstanceType=c5.2xlarge
aws cloudformation deploy --template-file kops-oneclick.yaml --stack-name mykops --parameter-overrides KeyName=somazkey SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName='somaz.link' S3StateStore='somaz-k8s-s3' MasterNodeInstanceType=c5.2xlarge WorkerNodeInstanceType=c5.2xlarge --region ap-northeast-2

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

# 마스터노드 SSH 접속
ssh -i ~/.ssh/somazkey.pem ec2-user@$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)

 

 

EC2 instance profiles 설정 및 AWS LoadBalancer 배포 & ExternalDNS & Metrics-server 설치 및 배포

  • 13분 정도 추가 시간 필요
# EC2 instance profiles 에 IAM Policy 추가(attach)
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
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name masters.$KOPS_CLUSTER_NAME
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name nodes.$KOPS_CLUSTER_NAME

# kOps 클러스터 편집 : 아래 내용 추가
# kubeproxy.metricsBindAddress 설정은 프로메테우스 kube-proxy 메트릭 수집을 위해서 설정 : 기본값 127.0.0.1 -> 수정 0.0.0.0 - 링크
kops edit cluster
-----
spec:
  certManager:
    enabled: true
  awsLoadBalancerController:
    enabled: true
  externalDns:
    provider: external-dns
  metricsServer:
    enabled: true
  kubeProxy:
    metricsBindAddress: 0.0.0.0
-----

# 업데이트 적용 : 모든 노드 롤링업데이트 필요 >> 마스터 EC2인스턴스 삭제 후 재생성 후 정상 확인 후, 워커노드 EC2인스턴스 생성 후 Join 후 삭제 과정 진행됨
kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster --yes

# 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

 

Auto scaling 그룹 error 발생

I0219 21:28:39.447535    7072 instancegroups.go:533] Cluster did not pass validation, will retry in "30s": InstanceGroup "nodes-ap-northeast-2a" did not have enough nodes 0 vs 2.
I0219 21:29:10.139571    7072 instancegroups.go:533] Cluster did not pass validation, will retry in "30s": InstanceGroup "nodes-ap-northeast-2a" did not have enough nodes 0 vs 2.
I0219 21:29:40.775766    7072 instancegroups.go:533] Cluster did not pass validation, will retry in "30s": InstanceGroup "nodes-ap-northeast-2a" did not have enough nodes 0 vs 2.
I0219 21:30:11.515068    7072 instancegroups.go:533] Cluster did not pass validation, will retry in "30s": InstanceGroup "nodes-ap-northeast-2a" did not have enough nodes 0 vs 2.
I0219 21:30:42.282717    7072 instancegroups.go:533] Cluster did not pass validation, will retry in "30s": InstanceGroup "nodes-ap-northeast-2a" did not have enough nodes 0 vs 2.

 

 

해결이 되지 않아 동막골 - 김예준님께서 도움을 주셧다.

아래의 사이트에서 quota 증설을 요청했다.

https://support.console.aws.amazon.com/support/home#/case/create?issueType=service-limit-increase&limitType=service-code-ec2-instances&serviceLimitIncreaseType=ec2-instances&type=service_limit_increase

 

 

요청을 하면 바로 답변메일이 온다.

 

I0222 18:07:14.394387    3754 instancegroups.go:443] waiting for 15s after terminating instance
I0222 18:07:29.403317    3754 instancegroups.go:477] Validating the cluster.
I0222 18:07:30.142086    3754 instancegroups.go:513] Cluster validated; revalidating in 10s to make sure it does not flap.
I0222 18:07:40.806417    3754 instancegroups.go:510] Cluster validated.
I0222 18:07:40.806452    3754 rollingupdate.go:214] Rolling update completed for cluster "somaz.link"!

(somaz:N/A) [root@kops-ec2 ~]# kubectl get nodes
NAME                  STATUS                        ROLES           AGE     VERSION
i-015147519888a394a   NotReady,SchedulingDisabled   node            19m     v1.24.10
i-0691c03e2cd60796b   Ready                         node            9m31s   v1.24.10
i-0b531baf902cefeee   Ready                         node            3m11s   v1.24.10
i-0df291c5a3d9ad47f   Ready                         control-plane   14m     v1.24.10

 

  • 메트릭 서버 확인
# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴
kubectl get pod -n kube-system -l k8s-app=metrics-server
kubectl top node
kubectl top pod -A

(somaz:N/A) [root@kops-ec2 ~]# kubectl get pod -n kube-system -l k8s-app=metrics-server
NAME                              READY   STATUS    RESTARTS      AGE
metrics-server-6d48674cf8-dlxrm   1/1     Running   2 (50s ago)   3m6s
metrics-server-6d48674cf8-n8jgw   1/1     Running   2 (63s ago)   3m6s

(somaz:N/A) [root@kops-ec2 ~]# kubectl top node
NAME                  CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
i-000aab9321c2967a2   29m          0%     1044Mi          6%
i-03b033157083165e0   103m         1%     2219Mi          14%
i-07c20a6b6de51f97e   22m          0%     1000Mi          6%

(somaz:N/A) [root@kops-ec2 ~]# kubectl top pod -A
NAMESPACE     NAME                                            CPU(cores)   MEMORY(bytes)
kube-system   aws-cloud-controller-manager-qp6c4              2m           20Mi
kube-system   aws-load-balancer-controller-68c78954d9-7lfbw   1m           31Mi
kube-system   aws-node-4jf8z                                  3m           33Mi
kube-system   aws-node-cq6rz                                  3m           34Mi
kube-system   aws-node-mzt58                                  3m           34Mi
kube-system   cert-manager-6b55fb8f96-cllvm                   1m           24Mi
kube-system   cert-manager-cainjector-5cf5bd97fc-kfjkd        1m           18Mi
kube-system   cert-manager-webhook-66ccfc975d-rrxkp           1m           13Mi
kube-system   coredns-6897c49dc4-tptcj                        1m           13Mi
kube-system   coredns-6897c49dc4-zk2cg                        1m           14Mi
kube-system   coredns-autoscaler-5685d4f67b-9tw97             1m           3Mi
kube-system   dns-controller-6f8cbcbb69-8zmbd                 1m           15Mi
kube-system   ebs-csi-controller-657d666f54-mmtlh             2m           50Mi
kube-system   ebs-csi-node-c7zcd                              1m           22Mi
kube-system   ebs-csi-node-hjzmx                              1m           20Mi
kube-system   ebs-csi-node-qq5dt                              1m           22Mi
kube-system   etcd-manager-events-i-03b033157083165e0         5m           30Mi
kube-system   etcd-manager-main-i-03b033157083165e0           14m          62Mi
kube-system   external-dns-844d94fdd8-8bjwf                   1m           18Mi
kube-system   kops-controller-qthz4                           1m           18Mi
kube-system   kube-apiserver-i-03b033157083165e0              31m          387Mi
kube-system   kube-controller-manager-i-03b033157083165e0     6m           60Mi
kube-system   kube-proxy-i-000aab9321c2967a2                  1m           12Mi
kube-system   kube-proxy-i-03b033157083165e0                  1m           12Mi
kube-system   kube-proxy-i-07c20a6b6de51f97e                  1m           12Mi
kube-system   kube-scheduler-i-03b033157083165e0              2m           19Mi
kube-system   metrics-server-6d48674cf8-dlxrm                 2m           16Mi
kube-system   metrics-server-6d48674cf8-n8jgw                 2m           14Mi

 

 

프로메테우스-스택 설치 및 웹 접속 : 모니터링에 필요한 여러 요소를 단일 차트(스택)으로 제공 ← 시각화(그라파나), 이벤트 메시지 정책(경고 임계값, 경고 수준) 등

# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`

# 설치
kubectl create ns monitoring
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:
    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 monitoringhelm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 45.0.0 --set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s'  -f monitor-values.yaml --namespace monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 45.0.0 -f monitor-values.yaml --namespace monitoring

# 확인
## alertmanager-0 : 사전에 정의한 정책 기반(예: 노드 다운, 파드 Pending 등)으로 시스템 경고 메시지를 생성 후 경보 채널(슬랙 등)로 전송
helm list -n monitoring
kubectl get-all -n monitoring
kubectl get prometheus,alertmanager -n monitoring
kubectl get prometheusrule -n monitoring
kubectl get servicemonitors -n monitoring

(somaz:N/A) [root@kops-ec2 ~]# helm list -n monitoring
NAME                    NAMESPACE       REVISION        UPDATED
        STATUS          CHART                           APP VERSION
kube-prometheus-stack   monitoring      1               2023-02-19 21:25:39.389880109 +0900 KST     deployed        kube-prometheus-stack-45.0.0    v0.63.0

 

프로메테우스 기본 사용 : 모니터링 그래프 → 경고 Alert 클릭 확인

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

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

(somaz:N/A) [root@kops-ec2 ~]# echo -e "Prometheus Web URL = https://prometheus.$KOPS_CLUSTER_NAME"
Prometheus Web URL = https://prometheus.somaz.link

프로메테우스 접속완료!

 

워커 노드 3번 추가

# 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

# 인스턴스그룹 정보 확인
(somaz:N/A) [root@kops-ec2 ~]# kops get ig
NAME                    ROLE    MACHINETYPE     MIN     MAX     ZONES
master-ap-northeast-2a  Master  c5.2xlarge      1       1       ap-northeast-2a
nodes-ap-northeast-2a   Node    c5.2xlarge      1       1       ap-northeast-2a
nodes-ap-northeast-2c   Node    c5.2xlarge      1       1       ap-northeast-2c

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

# 확인
(somaz:N/A) [root@kops-ec2 ~]# kops get ig
NAME                    ROLE    MACHINETYPE     MIN     MAX     ZONES
master-ap-northeast-2a  Master  c5.2xlarge      1       1       ap-northeast-2a
nodes-ap-northeast-2a   Node    c5.2xlarge      2       2       ap-northeast-2a
nodes-ap-northeast-2c   Node    c5.2xlarge      1       1       ap-northeast-2c

# 수동으로 수정 가능
kops edit ig nodes-ap-northeast-2a


# 적용
kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster


# 워커노드 증가 확인
while true; do kubectl get node; echo "------------------------------" ;date; sleep 1; done

(somaz:N/A) [root@kops-ec2 ~]# kubectl get nodes
NAME                  STATUS   ROLES           AGE     VERSION
i-0691c03e2cd60796b   Ready    node            16m     v1.24.10
i-0b531baf902cefeee   Ready    node            9m50s   v1.24.10
i-0da9df20f40730970   Ready    node            2m1s    v1.24.10
i-0df291c5a3d9ad47f   Ready    control-plane   21m     v1.24.10

 

 

 

 

 

그라파나 웹 접속 및 대시보드 추가 : TSDB 데이터를 시각화, 다양한 데이터 형식 지원(메트릭, 로그, 트레이스 등)

  • 링크
  • 접속 정보 확인 및 로그인 : 기본 계정 - admin / prom-operator
# ingress 도메인으로 웹 접속
echo -e "Grafana Web URL = https://grafana.$KOPS_CLUSTER_NAME"

(somaz:N/A) [root@kops-ec2 ~]# echo -e "Grafana Web URL = https://grafana.$KOPS_CLUSTER_NAME"
Grafana Web URL = https://grafana.somaz.link
  • 대시보드 사용 : 기본 대시보드 사용
    • 스택을 통해서 설치된 기본 대시보드 확인 : Dashboards → Browse
    • (대략) 분류 : 자원 사용량 - Cluster/POD Resources, 노드 자원 사용량 - Node Exporter, 주요 애플리케이션 - CoreDNS 등
      • 확인해보자 - K8S / CR / Cluster, Node Exporter / Use Method / Cluster

접속완료!

  • 공식 대시보드 가져오기 - 링크
    • [1 Kubernetes All-in-one Cluster Monitoring KR] Dashboard → Import → 13770 입력 후 Load ⇒ 데이터소스(Prometheus 선택) 후 Import 클릭
    • [Node Exporter Full] Dashboard → Import → 1860 입력 후 Load ⇒ 데이터소스(Prometheus 선택) 후 Import 클릭

13770
1860

 

 

 

얼럿매니저 웹 접속 & 얼럿매니저 대시보드 karma 사용

  • 링크
  • 얼럿매니저 웹 접속
# ingress 도메인으로 웹 접속
echo -e "Alertmanager Web URL = https://alertmanager.$KOPS_CLUSTER_NAME"

(somaz:N/A) [root@kops-ec2 ~]# echo -e "Alertmanager Web URL = https://alertmanager.$KOPS_CLUSTER_NAME"
Alertmanager Web URL = https://alertmanager.somaz.link
  1. Alerts 경고: 시스템 문제 시 프로메테우스가 전달한 경고 메시지 목록을 확인
  2. Silences 일시 중지 : 계획 된 장애 작업 시 일정 기간 동안 경고 메시지를 받지 않을 때, 메시지별로 경고 메시지를 일시 중단 설정
  3. Statue 상태 : 얼럿매니저 상세 설정 확인

얼럿매니저도 완료!

 

그리고 프로메테우스에 Watchdog이 얼럿매니저에 표현이 되어 있는 걸 볼 수 있다.

프로메테우스
얼럿매니저

 

 

[kops-ec2] 얼럿매니저 대시보드 karma 컨테이너로 실행

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

(somaz:N/A) [root@kops-ec2 ~]# docker run -d -p 80:8080 -e ALERTMANAGER_URI=https://alertmanager.$KOPS_CLUSTER_NAME ghcr.io/prymitive/karma:latest
Unable to find image 'ghcr.io/prymitive/karma:latest' locally
latest: Pulling from prymitive/karma
fc251a6e7981: Pull complete
7be4d3667295: Pull complete
dcbf1cb4e3a6: Pull complete
Digest: sha256:94b432c69901ae7916acea2c6c4a2e9942176b0e57451a290639a9d6c3517ab1
Status: Downloaded newer image for ghcr.io/prymitive/karma:latest
26e5d83badb07dee7501b74a8ea018fa87790db2d2ac132aaab2b29c2c97657f

# 확인
docker ps

(somaz:N/A) [root@kops-ec2 ~]# docker ps
CONTAINER ID   IMAGE                            COMMAND    CREATED          STATUS         PORTS                                   NAMES
26e5d83badb0   ghcr.io/prymitive/karma:latest   "/karma"   10 seconds ago   Up 9 seconds   0.0.0.0:80->8080/tcp, :::80->8080/tcp   friendly_jackson

 

[자신의 PC] 얼럿매니저 대시보드 karma 웹 접속 주소 확인

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

(somaz:N/A) [root@kops-ec2 ~]# echo -e "karma Web URL = http://$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)"
karma Web URL = http://3.36.127.208
 

GitHub - prymitive/karma: Alert dashboard for Prometheus Alertmanager

Alert dashboard for Prometheus Alertmanager. Contribute to prymitive/karma development by creating an account on GitHub.

github.com

karma 접속 완료!

 

Alerting 얼럿매니저

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

https://www.oreilly.com/library/view/prometheus-up/9781492034131/ch18.html

 

https://prometheus.io/docs/introduction/overview/

 

프로메테우스 웹 Alert & 얼럿매니저 웹 karma

 

슬랙 채널 및 웹훅 URL 생성 및 얼럿매니저 설정 적용 : 책 350~360페이지, 참고

# 웹훅 URL 정보
WEBHOOK='https://xxxxxx'(비공개)

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

(somaz:N/A) [root@kops-ec2 ~]# curl -X POST --data-urlencode "payload={\"channel\": \"#webhook\", \"username\": \"pkosbot\", \"text\": \"$KOPS_CLUSTER_NAME 다음주 종강! - 봇 제공\"}" $WEBHOOK
(somaz:N/A) [root@kops-ec2 ~]# curl -X POST --data-urlencode "payload={\"channel\": \"#webok\", \"username\": \"pkosbot\", \"text\": \"$KOPS_CLUSTER_NAME 다음주 종강! - 봇 제공\"}" $WEBHOOK

성공!

 

 

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

cat <<EOT > ~/alertmanager-slack.yaml
alertmanager:
  config:
    global:
      resolve_timeout: 5m
      slack_api_url: 'https://hooks.slack.com/services/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'
    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: '#webhook'
        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 --version 45.0.0 --reuse-values -f alertmanager-slack.yaml --namespace monitoring

# 반영 확인 : 얼럿매니저 설정 파일에 반영(config reload)
kubectl describe pod -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0
kubectl exec -it -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0 -- ls /etc/alertmanager/config
alertmanager.yaml.gz

(somaz:N/A) [root@kops-ec2 ~]# kubectl describe pod -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0
Name:             alertmanager-kube-prometheus-stack-alertmanager-0
Namespace:        monitoring
Priority:         0
Service Account:  kube-prometheus-stack-alertmanager
Node:             i-0691c03e2cd60796b/172.30.41.180
Start Time:       Wed, 22 Feb 2023 18:10:30 +0900
Labels:           alertmanager=kube-prometheus-stack-alertmanager
                  app.kubernetes.io/instance=kube-prometheus-stack-alertmanager
                  app.kubernetes.io/managed-by=prometheus-operator
                  app.kubernetes.io/name=alertmanager
                  app.kubernetes.io/version=0.25.0
                  controller-revision-hash=alertmanager-kube-prometheus-stack-alertmanager-659cbdf54d
                  statefulset.kubernetes.io/pod-name=alertmanager-kube-prometheus-stack-alertmanager-0
Annotations:      kubectl.kubernetes.io/default-container: alertmanager
Status:           Running
IP:               172.30.51.3
IPs:
  IP:           172.30.51.3
Controlled By:  StatefulSet/alertmanager-kube-prometheus-stack-alertmanager
Containers:
  alertmanager:
    Container ID:  containerd://6857066521745df9dda0a676698fa8ab99c8abcff299382431c9ccdbd1d88105
    Image:         quay.io/prometheus/alertmanager:v0.25.0
    Image ID:      quay.io/prometheus/alertmanager@sha256:fd4d9a3dd1fd0125108417be21be917f19cc76262347086509a0d43f29b80e98
    Ports:         9093/TCP, 9094/TCP, 9094/UDP
    Host Ports:    0/TCP, 0/TCP, 0/UDP
    Args:
      --config.file=/etc/alertmanager/config_out/alertmanager.env.yaml
      --storage.path=/alertmanager
      --data.retention=120h
      --cluster.listen-address=
      --web.listen-address=:9093
      --web.external-url=http://alertmanager.somaz.link/
      --web.route-prefix=/
      --cluster.peer=alertmanager-kube-prometheus-stack-alertmanager-0.alertmanager-operated:9094
      --cluster.reconnect-timeout=5m
      --web.config.file=/etc/alertmanager/web_config/web-config.yaml
    State:       Running
      Started:   Wed, 22 Feb 2023 18:10:40 +0900
    Last State:  Terminated
      Reason:    Error
      Message:   ts=2023-02-22T09:10:35.499Z caller=main.go:240 level=info msg="Starting Alertmanager" version="(version=0.25.0, branch=HEAD, revision=258fab7cdd551f2cf251ed0348f0ad7289aee789)"
ts=2023-02-22T09:10:35.499Z caller=main.go:241 level=info build_context="(go=go1.19.4, user=root@abe866dd5717, date=20221222-14:51:36)"
ts=2023-02-22T09:10:35.525Z caller=coordinator.go:113 level=info component=configuration msg="Loading configuration file" file=/etc/alertmanager/config_out/alertmanager.env.yaml
ts=2023-02-22T09:10:35.525Z caller=coordinator.go:118 level=error component=configuration msg="Loading configuration file failed" file=/etc/alertmanager/config_out/alertmanager.env.yaml err="open /etc/alertmanager/config_out/alertmanager.env.yaml: no such file or directory"

      Exit Code:    1
      Started:      Wed, 22 Feb 2023 18:10:35 +0900
      Finished:     Wed, 22 Feb 2023 18:10:35 +0900
    Ready:          True
    Restart Count:  1
    Requests:
      memory:   200Mi
    Liveness:   http-get http://:http-web/-/healthy delay=0s timeout=3s period=10s #success=1 #failure=10
    Readiness:  http-get http://:http-web/-/ready delay=3s timeout=3s period=5s #success=1 #failure=10
    Environment:
      POD_IP:   (v1:status.podIP)
    Mounts:
      /alertmanager from alertmanager-kube-prometheus-stack-alertmanager-db (rw)
      /etc/alertmanager/certs from tls-assets (ro)
      /etc/alertmanager/config from config-volume (rw)
      /etc/alertmanager/config_out from config-out (ro)
      /etc/alertmanager/web_config/web-config.yaml from web-config (ro,path="web-config.yaml")
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-6kmtd (ro)
  config-reloader:
    Container ID:  containerd://80c4ec6754524db2e61fc0eb2fe5145c081811f8d9bafa4716e22a84c7d7a10e
    Image:         quay.io/prometheus-operator/prometheus-config-reloader:v0.63.0
    Image ID:      quay.io/prometheus-operator/prometheus-config-reloader@sha256:3f976422884ec7744f69084da7736927eb634914a0c035d5a865cf6a6b8eb1b0
    Port:          8080/TCP
    Host Port:     0/TCP
    Command:
      /bin/prometheus-config-reloader
    Args:
      --listen-address=:8080
      --reload-url=http://127.0.0.1:9093/-/reload
      --config-file=/etc/alertmanager/config/alertmanager.yaml.gz
      --config-envsubst-file=/etc/alertmanager/config_out/alertmanager.env.yaml
    State:          Running
      Started:      Wed, 22 Feb 2023 18:10:39 +0900
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     200m
      memory:  50Mi
    Requests:
      cpu:     200m
      memory:  50Mi
    Environment:
      POD_NAME:  alertmanager-kube-prometheus-stack-alertmanager-0 (v1:metadata.name)
      SHARD:     -1
    Mounts:
      /etc/alertmanager/config from config-volume (ro)
      /etc/alertmanager/config_out from config-out (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-6kmtd (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  config-volume:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  alertmanager-kube-prometheus-stack-alertmanager-generated
    Optional:    false
  tls-assets:
    Type:                Projected (a volume that contains injected data from multiple sources)
    SecretName:          alertmanager-kube-prometheus-stack-alertmanager-tls-assets-0
    SecretOptionalName:  <nil>
  config-out:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     Memory
    SizeLimit:  <unset>
  web-config:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  alertmanager-kube-prometheus-stack-alertmanager-web-config
    Optional:    false
  alertmanager-kube-prometheus-stack-alertmanager-db:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  kube-api-access-6kmtd:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age                From               Message
  ----    ------     ----               ----               -------
  Normal  Scheduled  46m                default-scheduler  Successfully assigned monitoring/alertmanager-kube-prometheus-stack-alertmanager-0 to i-0691c03e2cd60796b
  Normal  Pulling    46m                kubelet            Pulling image "quay.io/prometheus/alertmanager:v0.25.0"
  Normal  Pulled     46m                kubelet            Successfully pulled image "quay.io/prometheus/alertmanager:v0.25.0" in 3.308438903s
  Normal  Pulling    46m                kubelet            Pulling image "quay.io/prometheus-operator/prometheus-config-reloader:v0.63.0"
  Normal  Pulled     46m                kubelet            Successfully pulled image "quay.io/prometheus-operator/prometheus-config-reloader:v0.63.0" in 3.6196947s
  Normal  Created    46m                kubelet            Created container config-reloader
  Normal  Started    46m                kubelet            Started container config-reloader
  Normal  Created    46m (x2 over 46m)  kubelet            Created container alertmanager
  Normal  Started    46m (x2 over 46m)  kubelet            Started container alertmanager
  Normal  Pulled     46m                kubelet            Container image "quay.io/prometheus/alertmanager:v0.25.0" already present on machine

(somaz:N/A) [root@kops-ec2 ~]# kubectl exec -it -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0 -- ls /etc/alertmanager/config
alertmanager.yaml.gz
  • 얼럿매니저 웹 → Status : 아래 config 부분에 위 슬랙 정보, 타이머 정보 확인

프로메테우스 down!
얼럿 매니저에 알람이 왓다!

 

Slack에도 알람이 전달 되었다! Repeat 인터벌은 5분이다!

 

 

 

얼럿매니저 웹에서 일시 중지 Silence 기능 사용 : repeat_interval 5분 설정으로 경고 알람 미조치 시 5분 마다 반복 발생

  • 웹 확인 : 프로메테우스 Alert, 얼럿매니지 웹, karma 웹
  • KubeClientCertificateExpiration(버그로 보임) → Silence 클릭 후 설정 기간(Duration), 작성자(admin) 입력 후 아래 Create 선택 ⇒ 해당 기간 동안 알람 발생하지 않음
  • Watchdog(탐지견, 얼럿매니저 정상 동작 여부 확인 용도) → Silence 클릭 후 설정 기간(Duration), 작성자(admin) 입력 후 아래 Create 선택

 

얼럿매니저 웹에서 일시 중지 Silence 기능 설정

  • 10분 후 TargetDown 경보 알람 → Silence 클릭 후 설정 기간(Duration), 작성자(admin) 입력 후 아래 Create 선택 ⇒ 해당 기간 동안 알람 발생하지 않음

일시중지 상태이다.

 

현재 2개의 장애(경보) 이슈 해결 : kube-controller-manager, kube-scheduler

  • 프로메테우스 웹 → Status → Targets 확인 : kube-controller-manager, kube-scheduler 없음 확인
# 상태확인
(somaz:N/A) [root@kops-ec2 ~]# k get po -n kube-system | grep kube-scheduler
kube-scheduler-i-0df291c5a3d9ad47f              1/1     Running   0             66m

(somaz:N/A) [root@kops-ec2 ~]# k get po -n kube-system | grep kube-controller
kube-controller-manager-i-0df291c5a3d9ad47f     1/1     Running   1 (68m ago)   68m

# 레이블 셀렉터 Selector 정보 확인!
kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-controller-manager
kubectl describe svc -n kube-system kube-prometheus-stack-kube-controller-manager

# 해당 서비스에 endpoint가 없다!
(somaz:N/A) [root@kops-ec2 ~]# kubectl exec -it -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0 -- ls /etc/alertmanager/config
alertmanager.yaml.gz
(somaz:N/A) [root@kops-ec2 ~]# kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-controller-manager
NAME                                                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
service/kube-prometheus-stack-kube-controller-manager   ClusterIP   None         <none>        10257/TCP   51m

NAME                                                      ENDPOINTS   AGE
endpoints/kube-prometheus-stack-kube-controller-manager   <none>      51m

# kube-controller-manager 파드의 레이블 확인
kubectl get pod -n kube-system --show-labels | grep kube-controller-manager

# 레이블 셀렉터 Selector 정보 확인!
kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-scheduler
kubectl describe svc -n kube-system kube-prometheus-stack-kube-scheduler

# 파드의 레이블 확인
kubectl get pod -n kube-system --show-labels | grep kube-scheduler

(somaz:N/A) [root@kops-ec2 ~]# kubectl get pod -n kube-system --show-labels | grep kube-scheduler
kube-scheduler-i-0df291c5a3d9ad47f              1/1     Running   0             68m   k8s-app=kube-scheduler
  • 해결 : 방안1(파드에 레이블 추가), 방안2(프로메테우스-스택 배포 때 파리미터에 기입)

 

방안1 : 파드에 레이블 추가

# 추가
kubectl label $(kubectl get pod -n kube-system -l k8s-app=kube-controller-manager -oname) -n kube-system component=kube-controller-manager

(somaz:N/A) [root@kops-ec2 ~]# kubectl label $(kubectl get pod -n kube-system -l k8s-app=kube-controller-manager -oname) -n kube-system component=kube-controller-manager
pod/kube-controller-manager-i-0df291c5a3d9ad47f labeled

# 확인
kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-controller-manager

# 앤드포인트에 IP가 생겼다!
(somaz:N/A) [root@kops-ec2 ~]# kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-controller-manager
NAME                                                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
service/kube-prometheus-stack-kube-controller-manager   ClusterIP   None         <none>        10257/TCP   53m

NAME                                                      ENDPOINTS             AGE
endpoints/kube-prometheus-stack-kube-controller-manager   172.30.37.245:10257   53m

# 추가
kubectl label $(kubectl get pod -n kube-system -l k8s-app=kube-scheduler -oname) -n kube-system component=kube-scheduler

(somaz:N/A) [root@kops-ec2 ~]# kubectl label $(kubectl get pod -n kube-system -l k8s-app=kube-scheduler -oname) -n kube-system component=kube-scheduler
pod/kube-scheduler-i-0df291c5a3d9ad47f labeled

# 확인
kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-scheduler

(somaz:N/A) [root@kops-ec2 ~]# kubectl get svc,ep -n kube-system kube-prometheus-stack-kube-scheduler
NAME                                           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
service/kube-prometheus-stack-kube-scheduler   ClusterIP   None         <none>        10259/TCP   54m

NAME                                             ENDPOINTS             AGE
endpoints/kube-prometheus-stack-kube-scheduler   172.30.37.245:10259   54m
  • 프로메테우스 웹 Status → Targets 확인

firing이 하나로 바뀌었다!
up 으로 변경 된거 확인
up 변경 확인
Slack에도 날라왓다!

 

 

방안2 : 프로메테우스-스택 helm 배포 때 파리미터에 기입 혹은 스택 helm 업그레이드로 적용

...
kubeControllerManager:
    enabled: true

    service:
      enabled: true
      selector:
        k8s-app: kube-controller-manager
...
kubeScheduler:
    enabled: true

    service:
      enabled: true
      selector:
        k8s-app: kube-controller-manager
...

 

 

 

[장애 재현] 워커 노드 3번 kubelet down → 얼럿매니저 기능 검증 : 워커 노드 3번 다운 감지(TargetDown → Kube…)

# 모니터링
while true; do kubectl get node; echo "------------------------------" ;date; sleep 1; done

(somaz:N/A) [root@kops-ec2 ~]# while true; do kubectl get node; echo "------------------------------" ;date; sleep 1; done
NAME                  STATUS   ROLES           AGE   VERSION
i-0691c03e2cd60796b   Ready    node            71m   v1.24.10
i-0b531baf902cefeee   Ready    node            65m   v1.24.10
i-0da9df20f40730970   Ready    node            57m   v1.24.10
i-0df291c5a3d9ad47f   Ready    control-plane   76m   v1.24.10
------------------------------

#
WNODE3=<자신의 워커노드 3번 퍼블릭 IP>
WNODE3=13.125.162.198
ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 hostname

(somaz:default) [root@kops-ec2 ~]# ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 hostname
The authenticity of host '13.125.199.131 (13.125.199.131)' can't be established.
ECDSA key fingerprint is SHA256:MGI4H3x/hHypxiI1/ihUvPUzwO18bnFX5BWmKAnsROk.
ECDSA key fingerprint is MD5:40:eb:63:5a:86:16:c2:10:7c:1b:9b:3a:9f:19:ee:d0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '13.125.199.131' (ECDSA) to the list of known hosts.
i-0da9df20f40730970

(somaz:default) [root@kops-ec2 ~]#

# 워커노드 3번 kubelet 강제 stop
ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 sudo systemctl stop kubelet
ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 sudo systemctl status kubelet

(somaz:default) [root@kops-ec2 ~]# ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 sudo systemctl status kubelet
● kubelet.service - Kubernetes Kubelet Server
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Wed 2023-02-22 10:13:29 UTC; 4s ago
       Docs: https://github.com/kubernetes/kubernetes
    Process: 3679 ExecStart=/usr/local/bin/kubelet $DAEMON_ARGS (code=exited, status=0/SUCCESS)
   Main PID: 3679 (code=exited, status=0/SUCCESS)
        CPU: 33.442s
  • 프로메테우스 Alerts(Pending 도 체크) vs 얼럿매니저 웹 상태 변화를 잘 관찰해보자!
# 모니터링 확인
while true; do kubectl get node; echo "------------------------------" ;date; sleep 1; done

Wed Feb 22 19:14:22 KST 2023
NAME                  STATUS     ROLES           AGE   VERSION
i-0691c03e2cd60796b   Ready      node            74m   v1.24.10
i-0b531baf902cefeee   Ready      node            68m   v1.24.10
i-0da9df20f40730970   NotReady   node            60m   v1.24.10
i-0df291c5a3d9ad47f   Ready      control-plane   80m   v1.24.10
------------------------------

 

https://awesome-prometheus-alerts.grep.to/

 

Awesome Prometheus alerts

Collection of alerting rules

awesome-prometheus-alerts.grep.to

 

(참고) 그라파나 얼럿 Docs - 링크

https://grafana.com/docs/grafana/latest/alerting/

  • Grafana - Image Render Plugin & Slack Alert 연동 - 링크
  • 그라파나 이미지를 포함한 슬랙 알럿 설정 - 링크

 

 

슬랙 채널 알람 확인 → 프로메테우스 Alerts , 얼럿매니저 웹, karma 에서 확인

# TargetDown 은 10분간 Pending 상태에 있다가 지속시 Firing 으로 변경 -> 이후 얼럿매니저를 통해서 슬랙 알람 발생
kubectl get prometheusrules -n monitoring -o json | grep TargetDown -B1 -A11
                            {
                                "alert": "TargetDown",
                                "annotations": {
                                    "description": "{{ printf \"%.4g\" $value }}% of the {{ $labels.job }}/{{ $labels.service }} targets in {{ $labels.namespace }} namespace are down.",
                                    "runbook_url": "https://runbooks.prometheus-operator.dev/runbooks/general/targetdown",
                                    "summary": "One or more targets are unreachable."
                                },
                                "expr": "100 * (count(up == 0) BY (job, namespace, service) / count(up) BY (job, namespace, service)) \u003e 10",
                                "for": "10m",
                                "labels": {
                                    "severity": "warning"
                                }
                            },

프로메테우스 알람
얼럿 매니저 알람!
karma 알람!
Slack 알람!

 

 

 

 

장애 정보 확인 후 워커 노드 3번 kubelet 다시 start ⇒ Silence Expire 로 제거

(somaz:default) [root@kops-ec2 ~]# ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 sudo systemctl start
kubelet

(somaz:default) [root@kops-ec2 ~]# kubectl get nodes
NAME                  STATUS   ROLES           AGE    VERSION
i-0691c03e2cd60796b   Ready    node            103m   v1.24.10
i-0b531baf902cefeee   Ready    node            97m    v1.24.10
i-0da9df20f40730970   Ready    node            89m    v1.24.10
i-0df291c5a3d9ad47f   Ready    control-plane   109m   v1.24.10

(somaz:default) [root@kops-ec2 ~]# ssh -i ~/.ssh/id_rsa ubuntu@$WNODE3 sudo systemctl status kubelet
● kubelet.service - Kubernetes Kubelet Server
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-02-22 10:42:57 UTC; 44s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 22011 (kubelet)
      Tasks: 20 (limit: 18627)
     Memory: 38.7M
        CPU: 777ms

 

 

 

PLG 스택

 

NGINX 웹서버 배포

#
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.27 -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

(somaz:default) [root@kops-ec2 ~]# kubectl get pod,svc,ep
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-5b589b7644-jcdwb   2/2     Running   0          3m1s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP
                                        PORT(S)                       AGE
service/kubernetes   ClusterIP      100.64.0.1       <none>
                                        443/TCP                       3h6m
service/nginx        LoadBalancer   100.66.227.175   a0a5d72568a214215b5930d3f9ea24a0-1681479890.ap-northeast-2.elb.amazonaws.com   80:32530/TCP,9113:31643/TCP   3m1s

NAME                   ENDPOINTS                               AGE
endpoints/kubernetes   172.30.37.245:443                       3h6m
endpoints/nginx        172.30.52.132:9113,172.30.52.132:8080   3m1s

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

# nginx 파드내에 컨테이너 갯수 확인
kubectl get pod -l app.kubernetes.io/instance=nginx
kubectl describe pod -l app.kubernetes.io/instance=nginx

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

(somaz:default) [root@kops-ec2 ~]# echo -e "Nginx WebServer URL = http://nginx.$KOPS_CLUSTER_NAME"
Nginx WebServer URL = http://nginx.somaz.link

curl -s http://nginx.$KOPS_CLUSTER_NAME

(somaz:default) [root@kops-ec2 ~]# curl -s http://nginx.$KOPS_CLUSTER_NAME
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

kubectl logs deploy/nginx -f

# 반복 접속
while true; do curl -s http://nginx.$KOPS_CLUSTER_NAME -I | head -n 1; date; sleep 1; done

# (참고) 삭제 시
helm uninstall nginx

nginx 접속 완료!

 

 

컨테이너 로그 환경의 로그는 표준 출력 stdout과 표준 에러 stderr로 보내는 것을 권고 - 링크

  • 해당 권고에 따라 작성된 컨테이너 애플리케이션의 로그는 해당 파드 안으로 접속하지 않아도 사용자는 외부에서 kubectl logs 명령어로 애플리케이션 종류에 상관없이, 애플리케이션마다 로그 파일 위치에 상관없이, 단일 명령어로 조회 가능
# 로그 모니터링
kubectl logs deploy/nginx -c nginx -f

# nginx 웹 접속 시도

# 컨테이너 로그 파일 위치 확인
kubectl exec -it deploy/nginx -c nginx -- ls -l /opt/bitnami/nginx/logs/
total 0
lrwxrwxrwx 1 root root 11 Feb 18 13:35 access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 Feb 18 13:35 error.log -> /dev/stderr

 

(참고) nginx docker log collector 예시 - 링크 링크

 

RUN ln -sf /dev/stdout /opt/bitnami/nginx/logs/access.log
RUN ln -sf /dev/stderr /opt/bitnami/nginx/logs/error.log
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
 && ln -sf /dev/stderr /var/log/nginx/error.log
  • 또한 종료된 파드의 로그는 kubectl logs로 조회 할 수 없다
  • kubelet 기본 설정은 로그 파일의 최대 크기가 10Mi로 10Mi를 초과하는 로그는 전체 로그 조회가 불가능함

 

PLG Stack 소개

Promtail + Loki + Grafana 여러 파드의 로그들을 중앙 서버에 저장하고 이를 조회- 링크

https://www.infracloud.io/blogs/logging-in-kubernetes-efk-vs-plg-stack/

 

Loki에 저장한 로그는 LogQL(PromQL과 유사)을 이용해 조회 할 수 있으며, 그라파나 웹이나 logcli를 이용해 조회 가능 - 링크

  • 전체 로그 기반 인덱스를 생성하지 않고, 메타데이터를 기준으로 인덱스를 생성하여 자원 사용량이 현저히 적음

https://grafana.com/docs/loki/latest/fundamentals/architecture/components/

 

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

 

Loki & Promtail 헬름 차트로 설치 - Helm Single & Helm

현재 Loki 최신 버전으로 설치(파라미터)가 실패해서, 책 설치 버전으로 진행합니다

(24단계 실습으로 정복하는 쿠버네티스)

 

Loki 설치

# 모니터링
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

(somaz:default) [root@kops-ec2 ~]# kubectl get pod,pvc,svc,ds,sts -n loki
NAME         READY   STATUS    RESTARTS   AGE
pod/loki-0   1/1     Running   0          89s

NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/storage-loki-0   Bound    pvc-2165c9ff-de6a-4960-834d-a6c1a679c389   20Gi       RWO            kops-csi-1-21   89s

NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/loki              ClusterIP   100.71.72.42   <none>        3100/TCP   89s
service/loki-headless     ClusterIP   None           <none>        3100/TCP   89s
service/loki-memberlist   ClusterIP   None           <none>        7946/TCP   89s

NAME                    READY   AGE
statefulset.apps/loki   1/1     89s

kubectl get-all -n loki
kubectl get servicemonitor -n loki
kubectl krew install df-pv && kubectl df-pv

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

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

(somaz:default) [root@kops-ec2 ~]# 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 설치

# 파라미터 설정 파일 생성
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

(somaz:default) [root@kops-ec2 ~]# kubectl get-all -n loki |grep promtail
endpoints/promtail-metrics                             loki       29s
pod/promtail-6tt6s                                     loki       29s
pod/promtail-bl6tb                                     loki       29s
pod/promtail-db97p                                     loki       29s
pod/promtail-ldml5                                     loki       29s
secret/promtail                                        loki       29s
secret/sh.helm.release.v1.promtail.v1                  loki       29s
serviceaccount/promtail                                loki       29s
service/promtail-metrics                               loki       29s
controllerrevision.apps/promtail-7dd7844cc5            loki       29s
daemonset.apps/promtail                                loki       29s
endpointslice.discovery.k8s.io/promtail-metrics-nwgsb  loki       29s
servicemonitor.monitoring.coreos.com/promtail          loki       29s

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

https://grafana.com/docs/loki/latest/getting-started/

 

그라파나에서 로그 확인

  • 그라파나 → Configuration → Data Source : 데이터 소스 추가 ⇒ Loki 클릭
  • nginx 반복 접속
# 접속 주소 확인 및 접속
kubectl logs deploy/nginx -f

# 반복 접속
while true; do curl -s http://nginx.$KOPS_CLUSTER_NAME -I | head -n 1; date; sleep 1; done

 

  • 그라파나 → Explore : 상단 데이터 소스 Loki 선택
    • Logfilters : Job → default/nginx 값 선택 ⇒ 우측 상단 Run query 클릭

log 확인 , pod가 재시작하거나 죽어도 영속성있게 log가 저장된다.

 

  • Logfilters : node_name → 아무 노드 선택 ⇒ 우측 상단 Run query 클릭

node에서 발생된 log내용을 볼 수 있다.

 

스터디 6주차 후기

6주차에는 프로메테우스와 그라파나를 사용하여 Alertmanager, karma 등에 대하여 공부하였다.

Monitoring Tool 공부는 처음이라서 상당히 도움이 많이 된 것 같다.

사내에도 Zabbix를 사용하여 텔레그램으로 알람을 주고 있는데, 비슷한 원리일 것으로 보인다.

이제 마지막 주차가 다가오고 있다. 

다들 마지막까지 힘냅시다~~

728x90
반응형