[DevOps] k8s에서의 모니터링 구성

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 k8s에서의 모니터링 구성은 어떤식으로 하는지 그리고 어떤 내용들을 모니터링의 대상으로 정하는지에 대해서 정리를 해보도록 하겠습니다.

필자가 속한 프로젝트에서는 기존에 k8s에서의 모니터링에 대한 체계가 제대로 갖춰져 있지 않았습니다. 모니터링의 대상의 선정이 먼저 진행이 되어야 했고, 수집된 대상을 기반으로 어떤 대시보드들이 필요한지에 대한 정의가 필요했습니다.

1. k8s 모니터링 4계층

쿠버네티스에서는 수집되어야 할 정보들이 레이어(계층)단위로 나뉩니다.

![](\k8s_monitoring_1 k8s_monitoring_1[/caption])

  • Host
    • Kubernetes Cluster를 구성하는 모든 Worker Node에 대한 CPU, 메모리, 디스트, 네트워크 사용량을 모니터링
  • Container
    • Noded에서 실행중인 Container의 CPU, 메모리, 디스크, 네트워크 사용량을 모니터링
  • Application
    • Container에서 구동되는 개별 어플리케이션에 대한 모니터링
    • 예를들어 컨테이너에서 기동되는 Spring Boot application의 JVM 사용률 현황
  • Kubernetes
    • Container를 컨트롤 하는 Kubernetes 자체에 대한 모니터링
    • Kubernetes의 자원인 Service, POD, Deployment, Daemonsets 등

레이어를 기준으로 가장크게는 Kubernetes > Host > Container > Application의 레이어로 메트릭 대상을 선정했습니다.

2. exporter 종류

위에서 선정한 레이어를 기준으로 exporter라는 별도의 어플리케이션을 설치 해야합니다. exporter는 k8s의 내부에서 Metric을 수집하여 외부로 노출시켜주는 일종의 API라고 볼 수 있습니다.

위에서 선정한 레이어별로 exporter의 종류가 다음과 같이 있습니다.

1) kube-state-metric (Kubernetes Metric)

쿠버네티스에서 조회되는 모든 정보를 가져올 수 있는 exporter 입니다.
쿠버네티스에서 존재하는 Deployments 갯수, Pod 갯수 등의 다양한 정보를 수집해야 하는 경우가 있습니다.

위와 같은 다양한 메트릭 정보를 수집해서 /metrics라는 엔드포인트로 제공해주는 exporter 입니다. 해당 exporter는 다음 깃헙에서 확인해 볼 수 있습니다.

kube-state-metic

kube-state-metrics Kubernetes 1.18 Kubernetes 1.19 Kubernetes 1.20 Kubernetes 1.21 Kubernetes 1.22
v1.9.8
v2.0.0 -/✓ -/✓ -/✓
v2.1.1 -/✓ -/✓
v2.2.4 -/✓
master -/✓

버전에 따라서 매핑되는 kube-state-metric을 확인 할 수 있습니다.

exporter_1

Kube-state-metric은 직접 kubernetes의 API에 접근을 하여 정보를 가져옵니다. 그렇다보니 하나의 Pod만 있어도 정보 조회가 가능합니다.

Deployment 타입으로 어플리케이션을 올리고, NodePort타입의 서비스를 통해서 외부로 메트릭을 노출합니다.

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: 1.8.0
  name: kube-state-http-metrics-nodeport
  namespace: kube-system
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: kube-state-metrics
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 31000 # 외부에 31000번 포트로 Pod의 8080번 포트를 라우팅
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: 2.1.0
  name: kube-state-metrics
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: kube-state-metrics
  template:
    metadata:
      labels:
        app.kubernetes.io/name: kube-state-metrics
        app.kubernetes.io/version: 2.1.0
    spec:
      containers:
      - image: k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.1.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          timeoutSeconds: 5
        name: kube-state-metrics
        ports:
        - containerPort: 8080
          name: http-metrics
        - containerPort: 8081
          name: telemetry
        readinessProbe:
          httpGet:
            path: /
            port: 8081
          initialDelaySeconds: 5
          timeoutSeconds: 5
        securityContext:
          runAsUser: 65534
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: kube-state-metrics

2) node-exporter

node-exporter는 CPU, Memory, Disk 사용량과 같은 호스트 관련 metric을 수집하여 API로 노출해주는 exporter입니다.
Prometheus는 정해진 주기로 지정한 Http endpoint에 접근하여 metric들을 스크랩합니다.

node-exporter

DaemonSet타입을 통해서 모든 Worker Node의 메트릭을 수집합니다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostIPC: true
      hostPID: true
      containers:
        - name: node-exporter
          image: prom/node-exporter
          imagePullPolicy: IfNotPresent
          args:
            - --path.procfs=/host/proc
            - --path.sysfs=/host/sys
          resources:
            requests:
              cpu: 10m
              memory: 100Mi
            limits:
              cpu: 100m
              memory: 100Mi
          ports:
            - name: scrape
              containerPort: 9100
              hostPort: 9100
          volumeMounts:
            - mountPath: /host/proc
              name: proc
              readOnly: true
            - mountPath: /host/sys
              name: sys
              readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc
            type: ""
        - name: sys
          hostPath:
            path: /sys
            type: ""

3) cadvisor

cAdvisor는 Kubernetes 에서 사용하는 기본적인 모니터링 Agent을 수행합니다. 모든 노드에 설치되서 노드에 대한 정보와 포트 (컨테이너)에 대한 지표를 수집합니다. 이렇게 수집된 내용은 다시 Kubelet에게 전달되는데 이 후 전달된 내용은 모니터링 툴 (메트릭 서버, 프로메테우스) 에서 다시 수집해 갑니다.

수집되는 데이터는 CPU, Memory, Filesystem, Network Used와 같은 통계를 수집하는 것입니다.

cAdvisor

DaemonSet 타입을 통해서 모든 Worker Node에 있는 Container의 정볼르 수집합니다.

apiVersion: apps/v1 
kind: DaemonSet
metadata:
  name: cadvisor
  namespace: kube-system
  labels:
    app: cadvisor
spec:
  selector:
    matchLabels:
      name: cadvisor
  template:
    metadata:
      labels:
        name: cadvisor
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: cadvisor
        image: google/cadvisor:latest
        volumeMounts:
        - name: rootfs
          mountPath: /rootfs
          readOnly: true
        - name: var-run
          mountPath: /var/run
          readOnly: false
        - name: sys
          mountPath: /sys
          readOnly: true
        - name: docker
          mountPath: /var/lib/docker
          readOnly: true
        ports:
          - name: http
            containerPort: 8080
            hostPort: 8080
            protocol: TCP
        args:
          - --housekeeping_interval=10s
      terminationGracePeriodSeconds: 30
      volumes:
      - name: rootfs
        hostPath:
          path: /
      - name: var-run
        hostPath:
          path: /var/run
      - name: sys
        hostPath:
          path: /sys
      - name: docker
        hostPath:
          path: /var/lib/docker

3. Grafana Dashboard 종류

프로메테우스 & 그라파나는 DevOps에서 가장 중요한 모니터링 툴입니다. 위에서 export되는 metric들을통해서 프로메테우스가 수집을 진행하고 그라파나를 통해서 대시보드로 표현을 합니다.

그럼 필자가 사용하는 대시보드들에 대해서 정리를 해보도록 하겠습니다.

3-1. Worker Node 대시보드

node-exporter를 통해서 수집된 데이터를 표현하는 것입니다. Grafana는 편리하게 직접 대시보드를 구축하지 않아도 손쉽게 구성이 가능하도록 여러 대시보드를 제공해주고 있습니다.

Node Exporter for Prometheus Dashboard

해당 대시보드를 import하게 되면 손쉽게 다음화면을 구성할 수 있습니다.

exporter_1

3-2. K8S Cluster 대시보드

cAdvisor를 통해서 수집되는 정보(container의 CPU, Memory, Network I/O 등) 에 대한 정보를 볼 수 있는 대시보드 입니다.

Kubernetes cluster monitoring

exporter_2

3-3. K8S State 대시보드

kube-state-metric으로부터 수집되는 정보들(k8s의 object 정보들)에 대해서 표현을 해줍니다. 예를들어 현재 클러스터의 Node, Deployment, Pods, Containers, HPA의 현황과 상태에 대해서 알 수 있습니다.

kube-state-metrics-v2

exporter_3

3-4. Java 어플리케이션 대시보드

대부분은 MSA구조로 시스템을 구성 할때는 Java기반의 어플리케이션, 그중에서도 스프링 부트를 많이 쓸 거라고 생각이 듭니다. 스프링을 쓰게 되면 기본적으로 jvm 현황에 대해서 메트릭을 export로 열어주고 해당 정보를 수집할 수 있습니다.

가령 현재 어플리케이션의 Heap, CPU, Load, GC등에 대한 정보를 얻을 수 있습니다.

JVM(Micrometer)

4. 마치며..

이번시간에는 k8s에서의 모니터링은 어떤식으로 구성을 하는지에 대해서 정리해보았습니다. 처음 k8s를 운영할때는 다소 어려움이 있었는데, 이제는 명확한 기준(Node, Cluster, Container, Application 등)을 갖고 모니터링을 수행 할 수 있었습니다.

그리고 매번 구성하는 모니터링 스택에 대해서는 git으로 관리를 하고있고, 신규 클러스터가 생성되면 바로 모니터링 스택(prometheus & grafana)을 설치하고 Dashboard를 import하면 바로 모니터링이 가능하도록 구성했습니다.

다음시간에는 Alert Manager의 활용법에 대해서 정리를 해보도록 하겠습니다.

5. 참조

Kubernetes Monitoring : Metrics
kube-state-metrics에 대해서
Monitoring exporter 정리

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다