본 포스팅은 "Opentelemetry로 Kubernetes Observability 확보하기" 시리즈의 2번째 글입니다.
저번 포스팅에서 Opentelemetry를 사용해 Logging에 대한 가시성을 확보하는 방법에 대해 알아봤습니다.
이번에는 Three pillars of observability의 Logging, Metric, Tracing 중 Metric에 대한 가시성을 Opentelemetry로 확보하는 방법에 대해 알아보도록 하겠습니다.
기존에는 Metric을 수집,관리하기 위해 CNCF 재단의 Opensource 도구인 Prometheus를 주로 사용했는데요, 이번 포스팅에서는 Prometheus가 아닌 Grafana에서 출시한 Mimir를 사용해서 Metric을 관리해보겠습니다.
그래서 이번 포스팅에서 Prometheus가 아닌 Mimir를 사용하면 어떤 이점이 있는지, Mimir와 Opentelemetry를 사용해서 Kubernetes 환경의 Metric 가시성을 어떻게 확보할 수 있는지 알아보겠습니다.
1. Mimir
1-1. Mimir란?
Mimir는 Grafana Labs에서 출시한 고가용성, 확장성과 높은 쿼리 성능을 위한 Opensource Metric 관리 도구입니다.
Mimir를 사용하면 기존 Prometheus에서 사용하던 시계열 DB인 TSDB를 더욱 가용성있고 확장성있는 아키텍쳐로 사용할 수 있습니다.
Mimir는 Horizontal하게 확장이 가능하고, 저렴하며 장기간 보관할 수 있는 Object Storage에 Metric을 보관하기 떄문에 이 같은 이점을 얻을 수 있습니다.
이는 Prometheus가 확장성의 한계를 극복하기 위해 federation을 구성하고, Thanos와 같은 별도의 Backend storage를 구성했던 작업을 하지 않아도 된다는 것을 의미합니다.
게다가 Prometheus의 TSDB를 사용하기 때문에 기존에 구성했던 Metric 아키텍쳐를 그대로 사용할 수 있으며, Grafana의 다양한 도구들과 호환성이 좋다는 이점도 가지고 있습니다.
1-2. Mimir와 Prometheus의 비교
Mimir와 Prometheus는 Metric을 관리하기 위한 Time series DB가 핵심 요소라는 공통점이 있습니다.
하지만 메트릭 수집 방법, Storage, 부가 기능 등 많은 차이점 또한 존재합니다.
아래 테이블을 통해 Mimir와 Prometheus의 공통점 및 차이점을 확인할 수 있습니다.
Feature | Prometheus | Mimir |
Data Model | Time series (TSDB) | Time series (TSDB) |
Query Language | PromQL | PromQL |
Storage | Block Storage | Object Storage |
Metric Collecting | Pull-based | Push-based |
Alerting | Built-in Alert | Not Supported |
Scalability | Limited Scalability | High Scalability (Horizontal Scale, Object Storage support..) |
위 테이블을 정리하자면, Mimir와 Prometheus는 둘 다 TSDB라는 Time series DB를 Data model로 가지고 있으며, PromQL을 Query Language로 사용한다는 공통점이 있습니다.
하지만 Promtheus와 Mimir는 Metric storage로 Local Block Storage와 외부 Remote Object Storage를 지원한다는 차이점이 있으며, 이로 인해 Mimir의 확장성이 더 월등합니다.
Metric 수집 방식은 Prometheus가 Pull-based 방식을 사용해 특정 경로로 노출된 Metric을 Prometheus가 가져오는 방식을 지원하고, Push gateway를 통해 Push-based 방식도 사용 가능하지만, Mimir는 Push-based 방식만을 지원해 Client가 직접 Mimir로 데이터를 넣어야 한다는 차이점이 존재합니다.
Alerting은 Prometheus가 자체적으로 지원하는 Alert 기능이 존재해 별도의 Alerting 도구가 필요없지만, Mimir는 Alerting을 지원하지 않아 외부 도구에 의존한다는 차이점이 있습니다.
확장성 측면에서 Prometheus는 주로 단일 노드에서 Vertical Scale을 사용하도록 설계되었기 때문에 확장성에 한계가 존재하는데, 이 같은 단점을 극복하기 위해 Thanos나 Federation과 같은 기능을 별도로 구성해야 합니다.
하지만 Mimir는 외부 Object stoage를 Backend storage로 사용할 수 있고, Horizontal scaling을 지원하기 때문에 확장성이 용이하다는 차이점이 존재합니다.
이 같은 차이점을 기반으로 Prometheus와 Mimir의 장,단점을 비교하면 아래와 같습니다.
Prometheus
Pros : Pull-based 방식 Metric 수집 사용 가능, 비교적 간편한 구성, 소,중규모 모니터링 시스템에 적합, 자체적으로 Alert 및 Query 기능 사용 가능, 활발한 커뮤니티
Cons : 낮은 확장성, 대규모 시스템을 위해선 확장성을 위한 별도의 구성 필요
Mimir
Pros : 높은 확장성, 대규모 모니터링 시스템에 적합, Grafana 도구와의 높은 연동성, Prometheus 호환 가능
Cons : Pull-based 방식 Metric 수집 불가, 대규모 시스템 구축시 비교적 구성이 복잡, 최근 출시되어 커뮤니티 자원 부족
1-3. Mimir 설치 및 구성
Mimir는 Kubernetes 환경에 설치할시 helm을 통해 간편하게 설치할 수 있습니다.
Helm으로 Mimir를 설치하기 전, 먼저 Value 파일을 아래와 같이 구성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
structuredConfig:
common:
storage:
backend: s3
s3:
endpoint: s3.us-east-1.amazonaws.com
region: us-east-1
blocks_storage:
storage_prefix: mimir
s3:
bucket_name: BUCKET_NAME
endpoint: s3.us-east-1.amazonaws.com
alertmanager_storage:
storage_prefix: alertmanager
s3:
bucket_name: BUCKET_NAME
endpoint: s3.us-east-1.amazonaws.com
ruler_storage:
storage_prefix: ruler
s3:
bucket_name: BUCKET_NAME
endpoint: s3.us-east-1.amazonaws.com
|
cs |
위 Value 명세는 Mimir가 Backend storage로 사용할 Object storage를 정의한 부분입니다.
역할별로 각각 Block, Alertmanager ,Ruler 데이터가 쌓일 Object storage를 정의할 수 있습니다.
모든 데이터를 하나의 Object storage에 쌓을 수 있지만, 이렇게 사용할시 storage_prefix 값을 통해 접두사를 정의해야 합니다.
이제 아래 명령어를 입력해 helm으로 Mimir를 설치할 수 있습니다.
1
|
helm install mimir grafana/mimir-distributed -n mimir --create-namespace --values ./VALUE_FILE.yaml
|
cs |
아래와 같이 모든 Pod가 동작한다면 Mimir가 정상적으로 설치된 것입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
$ kubectl get pods -n mimir
NAME READY STATUS RESTARTS AGE
mimir-alertmanager-0 1/1 Running 0 10s
mimir-compactor-0 1/1 Running 0 10s
mimir-distributor-65d65cd96b-hxzsl 1/1 Running 0 10s
mimir-ingester-zone-a-0 1/1 Running 0 10s
mimir-ingester-zone-b-0 1/1 Running 0 10s
mimir-ingester-zone-c-0 1/1 Running 0 10s
mimir-nginx-689bb54498-ttnzv 1/1 Running 0 12s
mimir-overrides-exporter-7b89c68ff-6h6s8 1/1 Running 0 10s
mimir-querier-579b89b4c6-2q9ms 1/1 Running 0 10s
mimir-querier-579b89b4c6-j7bcs 1/1 Running 0 10s
mimir-query-frontend-56dccd8f65-9xrjd 1/1 Running 0 10s
mimir-query-scheduler-cb86c75dd-8ntv2 1/1 Running 0 10s
mimir-query-scheduler-cb86c75dd-hzq7q 1/1 Running 0 10s
mimir-rollout-operator-7b96d4558d-z7n6m 1/1 Running 0 10s
mimir-ruler-55ddd9774-9c774 1/1 Running 0 10s
mimir-store-gateway-zone-a-0 1/1 Running 0 10s
mimir-store-gateway-zone-b-0 1/1 Running 0 10s
mimir-store-gateway-zone-c-0 1/1 Running 0 10s
|
cs |
2. Kubernetes 환경 Monitoring의 특징
Kubernetes Metrics
Kubernetes 환경에서는 Application에서 수집할 수 있는 Metric 외에 Pod, Deployment 등 Kubernetes Object와 관련된 Metric을 수집해야 합니다.
이 Metric들은 Deployment Counts, CPU Resource Request, Desired Replica Count 등 주로 Kubernetes 클러스터의 상태를 나타내는 Stats 데이터입니다.
이렇게 기존의 환경과 달리 Kubernetes 환경에서는 Application metric 외에 Kubernetes 클러스터의 상태를 모니터링하기 위한 Kubernertes Stats 데이터가 필요하다는 특징이 있습니다.
다양한 Layer가 존재
Monitoring 관점에서 Kubernetes는 크게 Application, Container, Host, Cluster라는 4가지 Layer로 구분할 수 있습니다.
Logging과 마찬가지로 Metric 또한 위의 3 Layer에 해당되는 데이터를 적절히 수집해야 합니다.
아래 테이블은 Layer별 수집할 수 있는 Metric과 Source입니다.
Layer | Target | Source | Example |
Application level | Container | Application | JVM memory, Tomcat active session.. |
Container level | Container | Kubelet | Container CPU, Memory, Disk usage.. |
Host level | Linux Host | Kubelet | Host CPU, Memory, Disk usage.. |
Cluster level | Kubernetes cluster | Kubernetes API | Daemonset pods count, Deplotment pods available.. |
3. Monitoring Architecture
위에서 다룬 Kubernetes 환경의 특성을 고려해 OTel Collector와 Mimir를 사용해서 Monitoring Architecture를 구성할 수 있습니다.
본 구성은 OTel Collector를 이용해서 Metric을 수집한 뒤, 이를 Mimir에 Remote-write 형태로 Push하는 방식의 Monitoring 아키텍쳐입니다.
Application metric은 OTel Instrumentation을 통해 Metric을 OTel Collector로 Push하거나, Application단에서 Metric을 노출시켜 OTel Collector에서 Pull하는 방식 모두 가능합니다. 이를 통해 Application단에서 수집할 수 있는 Metric 데이터를 수집합니다.
추가적으로 ServiceMonitor, PodMonitor와 같은 Prometheus CR을 사용해서 Metric을 수집할 수 있습니다. 이 경우 TargetAllocator를 사용해 OTel Collector가 중복된 Metric을 수집하지 않도록 Telemetry data를 Sharding해야 합니다.
Container metric은 각 Kubernetes Node마다 설치되어 있는 Kubelet에서 Daemonset으로 배포된 OTel Collector에서 수집합니다.
Kubernetes는 Kubelet을 구성하고 있는 cAdvisor를 통해 Container Metric 데이터를 수집 및 관리하는데, OTel Collector의 kubelet receiver를 통해서 해당 데이터를 가져올 수 있습니다.
Cluster metric은 Kubernetes API에서 Deployment로 배포된 OTel Collector에서 수집합니다.
Kubernetes API는 주로 Stats Metrics이라고 하는 상태 데이터를 수집 및 관리하며, OTel Collector의 k8s_cluster receiver를 통해 해당 데이터를 가져올 수 있습니다.
위 방법으로 수집한 각종 Metric들을 시계열 DB인 Mimir로 Push해 Mimir가 관리하는 Object storage에 저장하게 합니다.
이를 통해 대량의 Metric 데이터를 장기간 저렴하게 보관할 수 있으며, Grafana를 이용해 수집한 데이터를 시각화할 수 있습니다.
위 내용을 아래와 같이 테이블로 정리할 수 있습니다.
Layer | Component | Role | Deploy |
Application level | Otel Collector (OTel instrumentation) | Application metric | Daemonset Or Deployment |
Container level | Otel Collector (kubelet receiver) | Container metric | Daemonset |
Host level | Otel Collector (kubelet receiver) | Host metric | Daemonset |
Cluster level | Otel Collector (k8s_cluster receiver) | Cluster metric | Deployment |
4. Opentemetry Collector Configuration
이제 위의 Monitoring Architecture를 구현하기 위한 OTel Collector 설정에 대해 알아보겠습니다.
4-1. Opentelemetry Collector Daemonset
먼저 Daemonset 형태로 배포되는 OTel Collector 설정을 보겠습니다.
Daemonset 형태로 배포되는 OTel Collector는 kubelet에서 Host metric과 Container metric을 수집하는 역할을 합니다.
kubelet은 Kubernetes Node당 1개씩 설치되어 있기 때문에, kubelet Metric의 중복 및 생략을 피하기 위해 Daemonset 형태로 배포되어야 합니다.
Overall Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
exporters:
prometheusremotewrite:
endpoint: "http://mimir-nginx.mimir.svc:80/api/v1/push"
processors:
batch: {}
memory_limiter:
check_interval: 5s
limit_percentage: 80
spike_limit_percentage: 25
receivers:
kubeletstats:
collection_interval: 20s
auth_type: "serviceAccount"
insecure_skip_verify: true
service:
pipelines:
metrics:
exporters:
- prometheusremotewrite
processors:
- memory_limiter
- batch
receivers:
- kubeletstats
|
cs |
Receiver Configuration
1
2
3
4
5
|
receivers:
kubeletstats:
collection_interval: 20s
auth_type: "serviceAccount"
insecure_skip_verify: true
|
cs |
Receiver는 Kubelet으로부터 Metric을 수집할 수 있는 kubeletstats를 사용합니다.
Kubelet에 대한 인증 방식으로 serviceaccount의 Token을 사용하는 "ServiceAccount", kubeconfig를 사용하는 "kubeConfig"와TLS Certificate를 사용하는 "tls"를 지원합니다.
Processor Configuration
1
2
3
4
5
6
|
processors:
batch: {}
memory_limiter:
check_interval: 5s
limit_percentage: 80
spike_limit_percentage: 25
|
cs |
Processor는 별도의 Labeling이나 Drop같은 가공이 필요하지 않다면 "batch"와 "memory_limiter"로도 충분합니다.
"batch"는 OTel Collector의 Telemetry 데이터를 배치 형태로 처리하도록 하는 구성요소이며, "memory_limiter"는 OTel Collector의 메모리 사용 제한을 제어할 수 있는 구성요소입니다.
Exporter Configuration
1
2
3
|
exporters:
prometheusremotewrite:
endpoint: "http://mimir-nginx.mimir.svc:80/api/v1/push"
|
cs |
Exporter는 mimir로 Metric을 Push할 수 있는 prometheusremotewrite를 사용합니다.
"prometheusremotewrite" Exporter는 Prometheus로 Metric을 Push할때 사용하는 구성요소이지만, Mimir와도 호환이 가능하기 때문에 이를 사용할 수 있습니다.
endpoint 값의 path가 /api/v1/push 임에 주의해야 합니다.
Pipeline Configuration
1
2
3
4
5
6
7
8
9
10
|
service:
pipelines:
metrics:
exporters:
- prometheusremotewrite
processors:
- memory_limiter
- batch
receivers:
- kubeletstats
|
cs |
마지막으로 위에서 정의한 Receiver, Processor, Exporter를 순서에 맞게 조합하는 Pipeline을 정의합니다.
이를 통해 kubelet에서 수집한 Container, Host Metric을 Mimir로 Push해 적재할 수 있습니다.
결과적으로 아래와 같은 파이프라인이 구성됩니다.
4-2. Opentelemetry Collector Deployment
다음으로 Deployment 형태로 배포되는 OTel Collector 설정을 보겠습니다.
Deployment 형태로 배포되는 OTel Collector는 Application 및 Kubernetes API에서 Application metric과 Cluster metric을 수집하는 역할을 합니다.
단 Cluster metric은 중복을 피하기 위해 1개만 배포되어야 함에 주의합니다.
Overall Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
exporters:
prometheusremotewrite:
endpoint: "http://mimir-nginx.mimir.svc:80/api/v1/push"
processors:
batch: {}
memory_limiter:
check_interval: 5s
limit_percentage: 80
spike_limit_percentage: 25
receivers:
prometheus:
config:
scrape_configs:
- job_name: 'otel-collector'
target_allocator:
endpoint: http://demo-targetallocator
interval: 30s
collector_id: "${POD_NAME}"
otlp:
protocols:
http:
grpc:
k8s_cluster:
auth_type: serviceAccount
node_conditions_to_report: [Ready, MemoryPressure]
allocatable_types_to_report: [cpu, memory, ephemeral-storage, storage]
service:
pipelines:
metrics:
exporters:
- prometheusremotewrite
- debug
processors:
- memory_limiter
- batch
receivers:
- otlp
- k8s_cluster
- prometheus
|
cs |
Receiver Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
receivers:
prometheus:
config:
scrape_configs:
- job_name: 'otel-collector'
target_allocator:
endpoint: http://demo-targetallocator
interval: 30s
collector_id: "${POD_NAME}"
otlp:
protocols:
http:
grpc:
k8s_cluster:
auth_type: serviceAccount
node_conditions_to_report: [Ready, MemoryPressure]
allocatable_types_to_report: [cpu, memory, ephemeral-storage, storage]
|
cs |
Receiver는 Application에서 Metric을 Pull-based 방식으로 수집하기 위한 prometheus, Application에서 Metric을 Push-based 방식으로 수집하기 위한 otlp와 Kubernetes API에서 Cluster Metric을 수집하기 위한 k8s_cluster를 사용합니다.
“prometheus” Receiver는 Target Allocator로부터 수집한 데이터를 Pull하는 방식으로 Metric을 수집합니다. endpoint 주소는 Target Allocator의 ClusterIP이며, Target Allocator를 사용하기 위해서는 spec.targetAllocator.enabled 값이 “true”여야 합니다.
"otlp" Receiver는 HTTP와 gRPC 프로토콜 2가지 방식으로 OTel Collector에 OTLP 프로토콜 데이터를 받을 수 있는 endpoint를 생성합니다.
"k8s_cluster"는 Kubernetes API로부터 다양한 Cluster Layer의 데이터를 수집할 수 있으며, Attribute를 통해 수집하는 Metric을 커스텀할 수 있습니다.
Processor Configuration
1
2
3
4
5
6
|
processors:
batch: {}
memory_limiter:
check_interval: 5s
limit_percentage: 80
spike_limit_percentage: 25
|
cs |
Processor는 동일하게 사용합니다.
Exporter Configuration
1
2
3
|
exporters:
prometheusremotewrite:
endpoint: "http://mimir-nginx.mimir.svc:80/api/v1/push"
|
cs |
Exporter 또한 동일하게 사용합니다.
Pipeline Configuration
1
2
3
4
5
6
7
8
9
10
11
12 |
pipelines:
metrics:
exporters:
- prometheusremotewrite
- debug
processors:
- memory_limiter
- batch
receivers:
- otlp
- k8s_cluster
- prometheus |
cs |
위의 구성요소들을 조합하는 Pipeline을 정의합니다.
이 설정을 통해 Kubernetes 환경의 Cluster, Application Metric을 수집할 수 있습니다.
TargetAllocator Configuration
1
2
3
4
5
6
7
8
9
10
11
12
|
spec:
targetAllocator:
allocationStrategy: per-node
enabled: true
filterStrategy: relabel-config
observability:
metrics: {}
prometheusCR:
enabled: true
scrapeInterval: 30s
replicas: 1
resources: {}
|
cs |
위는 OTel Collector spec의 일부분으로, Target Allocator를 사용하기 위해 정의해야 합니다.
prometheusCR.enabled: true 설정을 통해 podMonitor, serviceMonitor를 이용해 Metric을 수집하는 TargetAllocator를 구성할 수 있습니다.
allocationStrategy를 통해 수집한 Metric을 OTel Collector들에게 분배하는 전략을 선택할 수 있습니다.
least-weighted, consistent-hashing, per-node 중 하나를 지정할 수 있으며, OTel Collector가 Daemonset으로 배포된 경우 per-node를 사용해야만 합니다.
ServiceMonitor Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: karpenter
namespace: otel
spec:
endpoints:
- targetPort: http-metrics
jobLabel: karpenter
namespaceSelector:
matchNames:
- karpenter
selector:
matchLabels:
app.kubernetes.io/instance: karpenter
app.kubernetes.io/name: karpenter
|
cs |
마지막으로 Application에서 Pull-based 방식으로 Metric을 수집하기 위한 ServiceMonitor를 정의합니다.
위 예시는 “karpenter” Application의 Metric을 수집하기 위한 Manifest로, namespaceSelector, selector 등의 어트리뷰트를 사용해 Karpenter Pod를 지정할 수 있습니다.
결과적으로 아래와 같은 파이프라인이 구성됩니다.
5. 마무리
Mimir는 Prometheus보다 확장성이 뛰어난 Metric 관리 도구입니다.
OTel Collector와 Mimir를 사용하여 Kubernetes 환경의 Metric 가시성을 확보할 수 있습니다.
Kubernetes는 Application, Container, Host, Cluster 4가지 Layer의 Metric을 수집하여 Monitoring Architecture를 구축할 수 있습니다.
이번 포스팅에서는 OTel Collector와 Mimir를 사용해서 Monitoring Architecture를 구성해봤습니다.
이 포스팅을 보는 분들이 Monitoring 시스템을 구성하는데 도움을 받으셨으면 합니다.
'Observability' 카테고리의 다른 글
Opentelemetry로 Kubernetes Observability 확보하기 : Correlation (0) | 2024.05.11 |
---|---|
Opentelemetry로 Kubernetes Observability 확보하기 : Tracing (0) | 2024.04.30 |
Opentelemetry로 Kubernetes Observability 확보하기 : Logging (0) | 2024.03.07 |
Prometheus Operator를 사용해 Kubernetes 환경에서 Prometheus 구성하기 (8) | 2022.03.31 |
트레이싱 관측 도구 Grafana Tempo로 트레이스를 관측해보자 (0) | 2022.01.27 |