모니터링이 어떤 것인지 간단히 살펴보겠습니다.
m-k8s 노드에서 bpytop 명령을 실행하면 다음 그림과 같이 시스템 상태 정보가 보입니다.
화면에서 리소스의 상태 및 문제가 될 가능성이 있는 정보를 한눈에 파악할 수 있습니다.
bpytop
그러나 bpytop은 현재 노드에 대한 정보만 보여줄 뿐,
다수의 노드로 구성된 클러스터 정보를 모두 표현하기는 어렵습니다.
그래서 이러한 정보를 수집하고 분류해서 따로 저장해야 합니다.
거의 모든 모니터링 도구는 다음과 같이 수집 -> 통합 -> 시각화 구조로 돼 있습니다.
우리가 구축한 컨테이너 인프라 환경에서는 모니터링 데이터를 프로메테우스로 수집하고,
수집한 정보를 한 곳에 모아(통합), 그라파나로 시각화합니다.
여기서 사용하는 프로메테우스와 그라파나는 오픈 소스 도구입니다.
오픈 소스는 가능한 한 단일 도구에서 단일 기능만을 구현하는 것을 선호합니다.
데이터 수집과 통합, 시각화는 서로 다른 영역이므로 이를 함꼐 구현하지 않으려는 경향이 있습니다.
물론 서비스형 모니터링 도구는 사용자 편의를 위해 이러한 기능을 모아서 한꺼번에 제공합니다.
그런데 왜 하나의 도구로 처리하지 않고 이런 혼합 구조를 사용할까요?
프로메테우스와 그라파나의 혼합 구조를 사용하는 이유는 크게 두 가지입니다.
그럼 다른 데이터 수집과 통합, 시각화에 사용하는 도구들은 무엇이 있을까요?
여러 모니터링 도구를 비교하며 프로메테우스를 선택한 이유를 알아보겠습니다.
메트릭이란?
메트릭(Metric)은 간단히 말해 현재 시스템의 상태를 알 수 있는 측정값입니다.
컨테이너 인프라 환경에서는 크게 2가지 상태로 메트릭을 구분합니다.
파드 같은 오브젝트에서 측정되는 CPU와 메모리 사용량을 나타내는 시스템 메트릭(System Metric),
HTTP 상태 코드 같은 서비스 상태를 나타내는 지표인 서비스 메트릭(Service Metric) 입니다.
시계열 데이터베이스란?
시계열 DB는 시간을 축(키)으로 시간의 흐름에 따라 발생하는 데이터를 저장하는 데 최적화된 데이터베이스입니다.
예를 들어 네트워크 흐름을 알 수 있는 패킷과 각종 기기로부터 전달받는 IoT 센서 값, 이벤트 로그 등이 있습니다.
이 책에서는 프로메테우스의 시계열 DB에 쿠버네티스와 노드에서 공개하는 메트릭을 저장하고,
이를 효과적으로 조합해 사용자가 원하는 모니터링을 구성합니다.
데이터 수집과 통합 도구의 기능을 간단히 정리하면 다음과 같습니다.
구분 | 프로메테우스 | 데이터독 | 뉴 렐릭 | 인플럭스DB |
---|---|---|---|---|
가격 | 무료 | 유료 | 유료 | 유/무료 |
형태 | 설치형 | 서비스형 | 서비스형 | 서비스형/설치형 |
참고 자료 | 매무 많음 | 많음 | 많음 | 많음 |
기능 확장성 | 매우 좋음 | 좋음 | 좋음 | 좋음 |
프로메테우스와 인플럭스DB가 제공하는 대시보드는
서비스형으로 사용하는 데이터톡과 뉴 렐릭보다 시각화 부분이 다소 약합니다.
그래서 부족한 시각화 기능을 보강하는 다음과 같은 도구를 사용합니다.
구분 | 그라파나 | 키바나 | 크로노그래프 |
---|---|---|---|
가격 | 유/무료 | 유/무료 | 유/무료 |
형태 | 서비스/설치형 | 서비스/설치형 | 서비스/설치형 |
시각화 대상 | 다양한 대상 시각화 가능 | 엘라스틱서치 | 인플럭스DB |
정보량 | 많음 | 많음 | 적음 |
기능 확장성 | 좋음 | 좋음 | 적음 |
엘라스틱 제품들을 설치형으로 구성하면 무료로 사용할 수 있지만, 엘라스틱서치로 저장해야 해서 필요한 도구가 늘어납니다.
자유도가 높은 오픈 소스를 활용해 컨테이너 인프라 환경을 구현하고 실습하는 것이 목적이라면
기능이 부족하지 않고, 확장성도 뛰어난 프로메테우스와 그라파나의 조합으로 모니터링 시스템을 구축하는게 좋습니다.
쿠버네티스 노드는 kubelet을 통해 파드를 관리하며,
파드의 CPU나 메모리 같은 메트릭 정보를 수집하기 위해 kubelet에 내장된 cAdvisor를 사용합니다.
cAdvisor는 구글이 만든 컨테이너 메트릭 수집 도구로, 쿠버네티스 클러스터 위에 배포된
여러 컨테이너가 사용하는 메트릭 정보를 수집한 후 이를 가공해서 kubelet에 전달하는 역할을 합니다.
하지만 cAdvisor로 수집되고 kubelet으로 공개되는 데이터가 있어도 외부에서 이를 모아서 표현해주는 도구가 없다면 의미가 없습니다.
그래서 메트릭 데이터를 수집하는 목적으로 메티륵 서버를 설치해 HPA와 같은 기능을 구현하고
쿠버네티스 대시보드를 설치해 현재 상태를 확인할 수도 있습니다.
쿠버네티스 대시보드에 관한 내용은 추후 포스팅 하겠습니다.
이렇게 메트릭 서버에서 수집한 데이터로 여러 기능을 수행하도록 구성한 것을
리소스 메트릭 파이프라인(Resource Metric Pipeline) 이라고 합니다.
하지만 메트릭 서버는 집계한 데이터를 메모리에만 저장하므로 데이터를 영구적으로 보존하기 어렵고 현재 시점의 데이터만 출력됩니다.
그래서 메트릭 데이터를 저장 공간에 따로 저장하는 완전한 모니터링 파이프라인(Full Monitoring Pipeline) 으로 구축하기를 권장합니다.
이 설계 방식을 반영한 도구가 프로메테우스입니다.
완전한 모니터링 파이프라인으로 구성한 프로메테우스는 여러 수집 대상이 공개하는 메트릭 데이터를 모아 시계열 데이터베이스에 저장합니다.
저장된 데이터는 시간이 지나도 확인할 수 있는 영속적인 데이터입니다.
누적된 메트릭 데이터로는 쿠버네티스 인프라의 상태 변화를 파악할 수 있고, 적절한 위험 감지 및 조치를 취할 수 있습니다.
프로메테우스는 많은 종류의 오브젝트를 설치합니다.
다음과 같은 오브젝트를 설치하며, 오브젝트를 통해 설치된 요소로 모니터링에 필요한 데이터를 수집하고 저장합니다.
프로메테우스의 주요 기능을 수행하는 요소로 3가지 역할을 맡습니다.
노드 익스포터 외 여러 대상에서 공개된 메트릭을 수집해오는 수집기,
수집한 시계열 메트릭 데이터를 저장하는 시계열 데이터베이스,
저장된 데이터를 질의하거나 수집 대상의 상태를 확인할 수 있는 웹 UI입니다.
프로메테우스를 사용하려면 웹 UI를 가장 먼저 알아야합니다.
프로메테우스의 수집기는 매우 독특한 방법으로 수집 대상을 찾습니다.
서비스 디스커버리(Service Discovery) 라는 방법입니다.
노드의 시스템 메트릭 정보를 HTTP로 공개하는 역할을 합니다.
설치된 노드에서 특정 파일들을 읽고, 이를 프로메테우스 서버가 수집할 수 있는 메트릭 데이터로 변환한 후에
노드 익스포터에서 HTTP 서버로 공개합니다.
공개된 내용을 프로메테우스 서버에서 수집해 가게 됩니다.
API 서버로 쿠버네티스 클러스터의 여러 메트릭 데이터를 수집한 후,
이를 프로메테우스 서버가 수집할 수 있는 메트릭 데이터로 변환해 공개하는 역할을 합니다.
프로메테우스가 쿠버네티스 클러스터의 여러 정보를 손쉽게 획득할 수 있는 것이 이 쿠버 스테이트 메트릭 덕분입니다.
얼럿매니저는 프로메테우스에 경보(alert) 규칙을 설정하고, 경보 이벤트가 발생하면 설정된 경보 메세지를 대상에서 전달하는 기능을 제공합니다.
프로메테우스에 설치하면 프로메테우스 서버에서 주기적으로 경보를 보낼 대상을 감시해 시스템을 안정적으로 운영할 수 있게 합니다.
배치와 스케줄 작업 시 수행되는 일회성 작업들의 상태를 저장하고 모아서 프로메테우스가 주기적으로 가져갈 수 있도록 공개합니다.
일반적으로 짧은 시간 동안 실행되고 종료되는 배치성 프로그램의 메트릭을 저장하거나
외부망에서 접근할 수 없는 내부 시스템의 메트릭을 프록시 형태로 제공하는 용도로 사용합니다.
helm
을 통해 ingress-nginx 컨트롤러 설치```
# 헬름 저장소 추가
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# 저장소 정보 갱신
$ helm repo update
# 저장소 리스트 확인
$ helm repo list
# k8s 에 ingress-nginx 컨트롤러 설치
# helm install [RELEASE_NAME] ingress-nginx/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx
```
```
# window에서 namespace가 자동 생성되지 않아서 수동으로 생성해줘야 한다.
$ kubectl create namespace ingress-nginx
$ helm upgrade -i ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.metrics.enabled=true \
--set-string controller.podAnnotations."prometheus\.io/scrape"="true" \
--set-string controller.podAnnotations."prometheus\.io/port"="10254"
```
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: simple-app-deployment
labels:
app: simple-app
spec:
replicas: 3
selector:
matchLabels:
app: simple-app
template:
metadata:
labels:
app: simple-app
spec:
containers:
- name: simple-app
image: cozserver/simple-node-app:v1
ports:
- containerPort: 80
#ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
labels:
app: simple-app
spec:
ingressClassName: nginx
rules:
- host: "localhost"
http:
paths:
- path: /test
- path: /
pathType: Prefix
backend:
service:
name: simple-app-service
port:
number: 8055
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: simple-app-service
namespace: default
spec:
selector:
app: simple-app
type: ClusterIP
ports:
- protocol: TCP
port: 8055
targetPort: 80
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# metadata:
# name: arbitrary
# Example configuration for the webserver
# at https://github.com/monopole/hello
commonLabels:
app: test-k8s
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
ingress의 hostname을 적어줘야 그라파나에서 정확하게 정보를 얻어올 수 있다.
[Ingress, Deployment, Service].yaml
들을 적용한다. # deployment.yaml, ingress.yaml, service.yaml 을 모두 적용한다.
# service, deployment, ingress 생성됨
$ kubectl apply --kustomize .
# 'kubectl kustomize . ' 명령어를 치면 어떻게 반영이 될 예정인 지 확인할 수 있다.
# 리소스 확인
$ kubectl get all,ingress
여기까지 하면 HTTP 인그래스 , node-app 서비스, Pod 리스트 가 만들어진다.
포트포워딩
을 통해 로컬호스트의 포트와 쿠버네틱스의 ingress-controller 의 포트를 연결한다.# localhost 의 8080포트에 접속 시 nginx-controller 의 80포트에 전달되도록 한다.
$ kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8080:80
GET /test
터미널 명령어를 통한 확인$ curl -X GET localhost:8080/test
# 정상적으로 받아진 것이 확인됨.
reponsed for 'GET /test'
localhost:8080
(GET /
) 으로 접속한다.참고: ingress.yaml 을 통해 hostname 을 통한 라우팅과 path 를 통한 라우팅이 가능하다.
$ kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/prometheus/
$ kubectl get all -n ingress-nginx
# 프로메테우스가 정상적으로 설치되었음을 확인할 수 있다.
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 2d
deployment.apps/prometheus-server 1/1 1 1 2d
kubectl --namespace ingress-nginx port-forward svc/prometheus-server 9090
프로메테우스
가 ingress-controller
로부터 메트릭 정보를 받아올 수 있는 지 확인한다.ingress-nginx 컨트롤러 환경변수 설정
을 진행하였었다면 확인이 가능해야한다.nginx_ingress_controller_success
검색 시 GET /
등의 메소드 성공 관련 정보를 받을 수 있다. k8s
에 그라파나
를 배포한다.$ kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/grafana/
# 결과:
service/grafana created
deployment.apps/grafana created
k8s
에 그라파나
가 정상적으로 설치되었는 지 확인한다.$ kubectl get all -n ingress-nginx | grep grafana
# 그라파나가 정상적으로 설치되었음을 확인할 수 있다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/grafana NodePort 10.109.147.15 <none> 3000:31922/TCP 2d
service/ingress-nginx-controller LoadBalancer 10.107.148.172 localhost 80:32619/TCP,443:30300/TCP 2d
service/ingress-nginx-controller-admission ClusterIP 10.105.3.33 <none> 443/TCP 2d
service/ingress-nginx-controller-metrics ClusterIP 10.111.99.250 <none> 10254/TCP 2d
service/prometheus-server NodePort 10.106.250.37 <none> 9090:32565/TCP 2d
$ kubectl --namespace ingress-nginx port-forward svc/grafana 3000
그라파나
에 접속한다.localhost:3000
그라파나 대시보드는 아래 다음을 보고 활성화 할 수 있다.