Overview
이번 글에서는 로그 수집 및 시각화 시스템인 ELK Stack (Elasticsearch, Logstash, Kibana, Filebeat)을 Kubernetes 환경에서 직접 구축하는 방법을 정리해보았다.
기본적인 ELK 스택의 아키텍처와 각 컴포넌트의 역할, 그리고 실제 운영 환경에서 구성한 Helm 기반 배포 방식과 커스텀 파서 적용 방법까지 상세히 다루며, 실무에서 필요한 구조적인 로그 파싱과 동적 인덱스 설정, 메트릭 처리 및 로그 필터링 방법도 함께 설명하였다.
또한 Filebeat와 Logstash 설정 시 JSON 처리, 로그 필드 가공, 조건 분기 등의 활용 예제를 포함하여 Kibana에서 쉽게 분석 가능한 구조로 만드는 방법도 공유하였다. 마지막으로 운영 시 주의할 점과 성능 부담을 줄이기 위한 수집 범위 제한 등도 언급하였다.
ELK 스택을 활용한 로그 플랫폼을 처음 구축하거나, 기존 시스템을 Helm 기반으로 이식하려는 사용자에게 실질적인 도움을 줄 수 있도록 구성된 글이다.
- ElasitSearch
- Logstash
- Kibana
- Filebeat
📅 관련 글
2024.03.05 - [Monitoring] - Fluent Bit (With Loki)
2024.09.12 - [Monitoring] - Prometheus와 Thanos란?
2024.09.12 - [Monitoring] - Prometheus 와 Thanos 설치 및 구성
2024.09.12 - [Monitoring] - Loki란?
2024.09.13 - [Monitoring] - Loki와 Promtail 설치
2025.01.13 - [Monitoring] - ELK Stack 구축해보기
ELK Stack 이란?
- Elasticsearch + Logstash + Kibana의 세 가지 구성 요소를 결합하여 ELK 스택이라 부른다.
- 최근에는 더 가벼운 EFK(Fluentd) 스택이 자주 사용된다.
- LogFlow만 이해하면 구성 방식은 크게 다르지 않다.
ELK Stack 아키텍처
- Log Pipeline:
- Filebeat(log shipper) -> Logstash(data processor) -> Elasticsearch(storage) <- Kibana(visualization)
- Metric Pipeline:
- Metricbeat(metric collector) -> Elasticsearch(storage) <- Kibana(visualization)
- APM Pipeline:
- Applications(APM agents) -> APM Server -> Elasticsearch(storage) <- Kibana(visualization)
ELK Stack 컴포넌트
- Elasticsearch: 로그 데이터를 저장하고 검색하는 검색 엔진
- Logstash: 로그를 저장하고 변환하는 데이터 처리 파이프라인(=Fluentd)
- Kibana: 로그 데이터 분석을 위한 시각화 대시보드
- Filebeat: 로그 파일 수집 및 전달(=Fluent-bit)
- Apmserver: 애플리케이션 추적 수집 및 처리를 위한 애플리케이션 성능 모니터링 서버
- Metricbeat: 시스템 및 서비스 메트릭을 위한 메트릭 전달
EFK Stack 컴포넌트
나머지 컴포넌트는 유사하다.
- Fluentd : 로그를 저장하고 변환하는 데이터 처리 파이프라인(=Logstash)
- Fluent-bit : 로그 파일 수집 및 전달(=Filebeat)
ELK Stack 구축
2023년 5월 16일에 archived 된 Helm Chart를 사용하여 설치하였다. 그리고 내부 개발 서버용이라서 Single Mode로 설치하였다.
구축방법은 크게 어렵지 않다. 아래의 Github를 참고하길 바란다.
최신버전으로 설치해보고 싶다면 아래의 operator chart를 사용하면 된다.
- https://github.com/elastic/cloud-on-k8s/tree/main/deploy/eck-operator
- https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-install-helm.html
elasticsearch , kibana, logstash, filebeat 순서로 설치해주면 된다.
filebeat와 logstash에는 내가 원하는 tag와 field를 추출하기 위한 parser를 설정할 수 있다.
`filebeat-values.yaml` 참고 (github repo에는 없습니다.)
...
filebeatConfig:
filebeat.yml: |
filebeat.inputs:
- type: log
paths:
- /usr/share/filebeat/app/somaz/dev/app/logs/* # 마운트된 경로의 로그 파일
- /usr/share/filebeat/app/somaz/dev/app/logs/**/*
fields:
log_source: "dev-somaz-app" # 이 값이 Elasticsearch 인덱스 이름이 됨
environment: "dev"
app: "somaz"
component: "app"
fields_under_root: true
json.keys_under_root: true # JSON 필드를 루트 레벨로 승격
json.add_error_key: true # JSON 파싱 에러 시 에러 필드 추가
json.expand_keys: true # 추가: 중첩된 JSON 문자열을 객체로 확장
processors:
- decode_json_fields:
fields: ["data"]
process_array: true
max_depth: 2
target: ""
overwrite_keys: true
- script:
lang: javascript
source: |
function process(event) {
if (event.data && event.data.requestBody) {
try {
event.data.requestBody = JSON.parse(event.data.requestBody);
} catch (e) {}
}
if (event.data && event.data.responseBody) {
try {
event.data.responseBody = JSON.parse(event.data.responseBody);
} catch (e) {}
}
if (event.stack && Array.isArray(event.stack)) {
try {
event.stack = event.stack.map(function(str) {
return str.replace(/\\n/g, '\n');
});
} catch (e) {}
}
return event;
}
`logstash-values.yaml` 참고 (github repo에는 없습니다.)
logstashPipeline:
logstash.conf: | # uptime.conf를 logstash.conf로 변경
input {
beats { # beats input만 사용
port => 5044
}
}
filter {
if [log_source] { # [fields][log_source]에서 변경
# log_source 값을 index_name 필드로 저장
mutate {
add_field => { "index_name" => "%{log_source}" } # [fields][log_source]에서 변경
}
} else {
# 기본값 설정
mutate {
add_field => { "index_name" => "default" }
}
}
# requestBody, responseBody, stack 문자열 처리
ruby {
code => '
# stack 처리
if event.get("stack").is_a?(Array)
event.set("stack", event.get("stack").map { |str|
str.gsub(/\\n/, "\n").gsub(/\\"/, "\"")
})
end
# requestBody와 responseBody를 문자열로 저장
if event.get("data")
if event.get("data")["requestBody"]
event.set("[data][requestBody]", event.get("data")["requestBody"].to_json)
end
if event.get("data")["responseBody"]
event.set("[data][responseBody]", event.get("data")["responseBody"].to_json)
end
end
# 루트 레벨 필드 제거
event.remove("requestBody")
event.remove("responseBody")
'
}
date {
match => [ "[timestamp]", "ISO8601" ]
target => "@timestamp"
remove_field => [ "timestamp" ]
}
}
output {
elasticsearch {
hosts => ["https://elasticsearch-master:9200"]
user => "${ELASTICSEARCH_USERNAME}"
password => "${ELASTICSEARCH_PASSWORD}"
ssl_certificate_verification => true
cacert => '/usr/share/logstash/config/certs/ca.crt'
# 동적 인덱스 이름 설정
index => "%{index_name}"
# 인덱스 설정을 직접 지정
manage_template => true
template => "/usr/share/logstash/config/template.json"
template_overwrite => true
}
# # 디버깅을 위한 stdout 출력
# stdout { codec => rubydebug }
# # S3 output 추가
# s3 {
# aws_access_key_id => "${AWS_ACCESS_KEY_ID}"
# aws_secret_access_key => "${AWS_SECRET_ACCESS_KEY}"
# region => "ap-northeast-2" # AWS 리전
# bucket => "your-bucket-name"
# prefix => "logstash-backup/%{+YYYY}/%{+MM}/%{+dd}"
# rotation_strategy => "size_and_time"
# size_file => 5242880 # 5MB
# time_file => 15 # 15분
# encoding => "gzip" # 압축 적용
# codec => json_lines
# }
}
parser 부분은 kibana에서 보고싶은 구조로 구성해주면 된다.
구축을 완료하고 나면 curl로 인덱스를 조회해 볼 수 있다.
curl -k -u "elastic:somaz123!" "http://elasticsearch.somaz.link/_cat/indices?v"
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open .kibana-event-log-8.5.1-000002 0YwfADLHQryK5bYlBpBm5Q 1 1 0 0 225b 225b
yellow open dev-somaz-app 9zip7n0sdfasdfsadfsdfsdaf 1 1 24161 0 6.5mb 6.5mb
그리고 Kibana에서 해당 index에 맞는 discover를 생성해주면 아래와 같이 확인가능하다.
주의할점
1. elasitsearch health check 에는 yellow와 green이 있다. single node로 사용해도, green을 유지할 수는 있지만 정신건강에 좋지않다. yellow로 유지해도 무방하다.
# https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html#request-params wait_for_status
# multiple node cluster will be green
clusterHealthCheckParams: "wait_for_status=green&timeout=1s"
# # single node cluster will be yellow
clusterHealthCheckParams: "wait_for_status=yellow&timeout=1s"
2. kibana와 elasitcsearch는 한몸이라고 보면 된다. elasticsearch에 문제가 생기면, kibana 웹은 접속조차 되지 않는다.
3. 생각보다 filebeat로 모든 로그를 가져오게 되면 부하가 심하다. 필자는 특정 pod의 로그만 수집하여 logstash 그리고 elasticsearch로 전달하였다.
4. operator를 사용해서 설치해보고 싶다면 eck-operator-crds를 잘 분석해보길 바란다.
마무리
ELK Stack은 강력한 로그 수집 및 분석 플랫폼으로, Kubernetes 기반의 마이크로서비스 환경에서도 여전히 널리 사용되고 있다. 특히 Helm과 연동하여 배포를 자동화하고, Filebeat → Logstash → Elasticsearch 파이프라인 구조에 유연한 파서를 적용하면 매우 직관적이고 확장 가능한 로그 시스템을 구성할 수 있다.
단, 실무에서 사용할 경우 다음과 같은 점에 유의해야 한다.
- Elasticsearch의 노드 구성과 Health 상태는 시스템 안정성에 큰 영향을 준다. single-node 환경에서는 yellow 상태도 허용 가능하지만, production에서는 multi-node 구성을 권장한다.
- 수집 범위 제한 및 필드 정제를 통해 Filebeat와 Logstash의 과부하를 방지하고, 필요한 로그만 선별적으로 저장하는 것이 중요하다.
- Kibana의 Discover 및 Index Pattern 구성은 운영자의 관찰 효율성과 직결되므로 초기 설계가 매우 중요하다.
향후에는 Elastic Cloud Operator (ECK)를 이용한 자동화 및 GitOps 기반 배포 전략도 함께 고민해보면, 더 견고하고 운영 효율적인 ELK 환경을 구축할 수 있을 것이다.
Reference
https://github.com/elastic/helm-charts
https://github.com/somaz94/helm-chart-template/tree/main/k8s-service/monitoring/elk-stack
'Monitoring' 카테고리의 다른 글
Loki와 Promtail 설치 (5) | 2024.10.02 |
---|---|
Loki란? (4) | 2024.09.26 |
Prometheus 와 Thanos 설치 및 구성 (0) | 2024.09.19 |
Prometheus와 Thanos란? (4) | 2024.09.12 |
Fluent Bit (With Loki) (4) | 2024.03.08 |