오픈서치(OpenSearch)를 클라우드 관리형(AWS OpenSearch Service)이 아닌, **자체 설치(Self-hosted)**해서 사용할 경우 가장 난감한 부분이 바로 **'노드 모니터링'**입니다.
과거(3.x 이전)에는 Performance Analyzer(PA)와 RCA를 연동하여 모니터링을 구성했지만, 3.x 버전부터 아키텍처가 변경되면서 이 방식이 더 이상 권장되지 않거나 불가능해졌습니다.
Elastic Stack(ELK)의 경우 Kibana에서 간편하게 Stack Monitoring을 켤 수 있지만, OpenSearch Dashboards에는 그런 기본 기능이 없습니다... (ㅠㅠ)
현재 OpenSearch 3.4 공식 문서 기준으로 추천하는 모니터링 아키텍처는 다음과 같습니다.
OpenTelemetry (수집) -> Data Prepper (가공) -> OpenSearch (저장/시각화)
지금부터 OpenShift (Kubernetes) 환경을 기준으로 이 세팅 과정을 하나씩 정리해 보겠습니다.
1. 아키텍처 및 개념 이해
우선 오픈서치 노드의 메트릭 데이터를 외부로 가져와야 합니다. 이때 **OpenTelemetry(OTel)**가 핵심적인 역할을 합니다.
OpenTelemetry 수집 데이터 3요소
- 메트릭 (Metrics): 시스템 상태나 성능을 숫자로 표현한 시계열 데이터 (예: CPU 사용률, 메모리 사용량, JVM 힙).
- 로그 (Logs): 애플리케이션에서 발생하는 개별 이벤트 기록. 보통 메트릭으로 이상 징후를 파악한 뒤, 로그를 통해 원인을 분석합니다.
- 트레이스 (Traces): 하나의 요청(Transaction)이 분산 시스템을 통과하는 전체 경로를 기록. 병목 지점 파악에 필수적입니다.
수집 방식: Pull vs Push
오픈서치 노드 상태를 수집하는 데는 두 가지 방법이 있습니다.
- Pull (Scraping): OTel이 주기적으로 오픈서치에 접속해 데이터를 긁어가는 방식. (추천)
- Push: 오픈서치 설정(yml)을 수정하여, 오픈서치가 스스로 OTel에게 데이터를 쏘는 방식.
선택: Push 방식은 오픈서치 설정을 건드려야 하고 재시작 리스크가 있습니다. 반면 Pull 방식은 오픈서치 수정 없이 외부에서 접근만 하면 되므로 훨씬 안전합니다. 따라서 Pull 방식을 선택했습니다. (단, Trace 데이터 수집이 필요하다면 Push 방식 설정이 필요할 수 있습니다.)
2. OpenTelemetry Collector 세팅
OpenTelemetry는 표준 API와 SDK를 제공하지만, 이를 직접 구현하기보다 이미 잘 만들어진 완제품인 OpenTelemetry Collector를 사용하는 것이 효율적입니다.
특히, 기본 이미지보다는 다양한 플러그인이 포함된 contrib 이미지를 사용해야 OpenSearch(Elasticsearch) 리시버를 사용할 수 있습니다.
2-1. 배포 설정 (Deployment)
YAML
kind: Deployment
apiVersion: apps/v1
metadata:
name: otel-collector
namespace: [내-프로젝트-이름] # OpenShift 네임스페이스 기입
labels:
app: otel-collector
spec:
replicas: 1
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
volumes:
- name: otel-config-vol
configMap:
name: otel-collector-config
defaultMode: 420
containers:
- name: otel-collector
# 다양한 리시버 사용을 위해 contrib 이미지 사용 필수
image: 'otel/opentelemetry-collector-contrib:0.143.0'
args:
- '--config=/conf/otel-collector-config.yaml'
resources:
limits:
cpu: 500m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: otel-config-vol
mountPath: /conf
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
2-2. ConfigMap 설정 (otel-collector-config.yaml)
OTel Collector가 오픈서치(Source)에서 데이터를 긁어서 Data Prepper(Destination)로 보내도록 설정합니다.
참고: OTel은 OpenSearch 전용 리시버가 별도로 없으므로, 호환되는 elasticsearch 리시버를 사용합니다.
YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-collector-config
data:
otel-collector-config.yaml: |
receivers:
elasticsearch:
# [중요] OpenSearch 서비스 주소 (Headless 서비스 권장)
endpoint: "https://opensearch-headless:9200"
tls:
# 사설 인증서(Self-signed) 사용 시 필수
insecure_skip_verify: true
username: "admin"
password: "admin_password" # 실제 비밀번호 입력
# 수집 주기 (너무 짧으면 부하 발생)
collection_interval: 60s
processors:
batch:
send_batch_size: 1000
timeout: 5s
# 불필요한 메트릭 제거 (용량 최적화)
filter:
error_mode: ignore
metrics:
exclude:
match_type: strict
metric_names:
- elasticsearch.node.fs.io_stats.total_reads
- elasticsearch.node.fs.io_stats.total_writes
- elasticsearch.node.http.connections.opened
- elasticsearch.node.http.connections.total
- elasticsearch.node.transport.packets.received
- elasticsearch.node.transport.packets.sent
- elasticsearch.node.thread_pool.completed
- elasticsearch.node.thread_pool.largest
exporters:
# 수집한 데이터를 Data Prepper로 전송
otlp:
endpoint: "data-prepper-service:21890" # Data Prepper OTLP 포트
tls:
insecure: true
service:
pipelines:
metrics:
receivers: [elasticsearch]
processors: [filter, batch] # filter 프로세서 추가됨
exporters: [otlp]
설정 포인트:
- collection_interval: 60s: 주기가 너무 짧으면 데이터 양이 폭증하여 스토리지 낭비가 심합니다. 1분 정도가 적당합니다.
- send_batch_size: 1000: 데이터를 한 번에 묶어서 보냅니다. 제한이 없으면 Data Prepper가 받아내지 못할 수 있습니다.
- metric_names (Filter): 모니터링 대시보드에서 보지 않을 세부적인 I/O나 스레드풀 정보는 과감히 제외하여 용량을 아낍니다.
- insecure: true: 내부 통신에 사설 인증서를 사용하는 경우 SSL 검증을 건너뛰어야 에러가 나지 않습니다.
수집되는 데이터 예시 -> 필자 기준 61개 칼럼이 수집된다.
| elasticsearch.node.thread_pool.tasks.finished |
| elasticsearch.node.thread_pool.threads |
| elasticsearch.node.thread_pool.tasks.queued |
| elasticsearch.node.operations.completed |
| elasticsearch.node.operations.time |
| elasticsearch.breaker.tripped |
| elasticsearch.breaker.memory.limit |
| elasticsearch.breaker.memory.estimated |
| jvm.memory.pool.used |
| elasticsearch.memory.indexing_pressure |
| jvm.memory.pool.max |
| elasticsearch.node.cluster.io |
3. Data Prepper 세팅
OTel Collector가 데이터를 수집했다면, 이를 받아 OpenSearch에 저장할 파이프라인이 필요합니다. 저같은 경우 Logstash로 로그 수집을 하고 있어서 이쪽으로 처리할 까 고민했지만
공식 가이드의 추천과
1. 추후 Otel을 활용해 Trace 데이터를 수집할 가능성
2. 로그스태시가 옵저빌리티 데이터까지 수집하면 비대함
3. Grok 패턴을 추가할 때 필요없는 옵저빌리티 로그로 인한 디버깅 어려움
이 세가지 이유로 DataPrepper를 세팅했습니다.
YAML
kind: Service
apiVersion: v1
metadata:
name: data-prepper-service
labels:
app: data-prepper
spec:
ipFamilies:
- IPv4
ports:
- protocol: TCP
port: 21890
targetPort: 21890
internalTrafficPolicy: Cluster
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: data-prepper
labels:
app: data-prepper
spec:
replicas: 1
template:
metadata:
labels:
app: data-prepper
spec:
volumes:
- name: config-volume
configMap:
name: dataprepper-config
defaultMode: 420
containers:
- resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: 500m
memory: 2Gi
terminationMessagePath: /dev/termination-log
name: data-prepper
env:
- name: JAVA_OPTS
value: '-Xms1g -Xmx1g'
ports:
- containerPort: 21890
protocol: TCP
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config-volume
mountPath: /usr/share/data-prepper/pipelines/pipelines.yaml
subPath: pipelines.yaml
image: '이미지 주소'
3-3. 파이프라인 설정 (dataprepper-config.yaml)
Data Prepper의 핵심인 pipelines.yaml 설정입니다. **Source(OTLP)**로 받아서 **Sink(OpenSearch)**로 내보냅니다.
metrics-pipeline:
source:
otlp:
ssl: false
port: 21890 # OTel Collector와 통신할 포트
buffer:
bounded_blocking:
buffer_size: 20000
batch_size: 1000
processor:
- otel_metrics:
sink:
- opensearch:
hosts: 주소
username: "admin"
password: "admin" # [필수수정] 실제 비밀번호
# [중요] 템플릿 적용을 위해 custom 타입 사용
index_type: "custom"
#인증서 검사 X
insecure: true
# [변경] 템플릿의 index_patterns 와 일치하도록 이름 변경
index: "ss4o_metrics-opensearch-%{yyyy.MM.dd}"
# 컨테이너에 마운트될 템플릿 파일 경로 -> 주석처리하고 오류나면 추가한 뒤 아래 파일도 추가해야함.
#template_file: "/usr/share/data-prepper/templates/ss4o_metrics.json"
- 최하단 template_file은 적용되지 않아서 주석처리했습니다.
- ss4o_metrics는 옵저빌리티 공식 인덱스 이름이기 때문에 지켜주는게 추후 호환에 더 좋습니다.
결론
위와 같이 설정했다면 ss4o_metrics로 데이터가 들어올 것입니다.
다만 이제 가장 중요한 대시보드를 세팅해야합니다. 본인이 필요한 지표로 대시보드를 세팅할 수 있다면 혼자하면되고 모르겠다면 다음편에 대시보드 세팅방법을 게시하겠습니다.