# 로그를 수집하면 생기는 이점
1. 사용자 행동 분석 로그 데이터를 통해 사용자의 행동 패턴을 파악하고 이를 바탕으로 서비스 개선 및 마케팅 전략을 세울 수 있다.
2. 오류 및 버그 추적 로그를 통해 시스템 내 발생한 오류나 문제를 확인하고 추적할 수 있어, 소프트웨어의 안정성과 품질을 개선할 수 있다.
3. 성능 최적화 로그 데이터를 분석하여 데이터 베이스 작업, API 호출, 시스템 리소스 사용 등 시스템의 성능 상태를 파악하고, 이를 통해 성능 문제점을 찾아 수정할 수 있다.
4. 보안 감시 로그를 통해 시스템 내의 비정상적인 활동, 해킹 시도, 인증 실패 등을 식별하고, 보안 취약점을 찾아낼 수 있다.
이는 시스템 보안의 유지를 도울 뿐만 아니라, 사이버 공격에 대한 대응 역시 가능하게 한다.
모두 중요하지만, 여기서 필요하다고 느낀 점은 사용자 행동을 분석하여 어떤 서비스를 많이 활용하는 지 분석하는 것이라고 생각한다. 새로운 서비스가 출시또는 변경할 때, A/B 테스트를 확인하여, 변경된 서버 환경의 이점을 확인할 수 있기 때문이다. 왜냐하면 오류들은 QA를 통해 찾으면 그 에러 로직은 최근 log를 통해 쉽게 볼 수 있기 때문입니다.
# ELK 스택이란?
Elasticsearch: JSON 기반의 분산형 오픈 소스 검색 및 분석 엔진, 주로 REST API를 통해 처리한다.
Logastsh: 여러 소스에서 동시에 데이터를 수집하여 변환한 후, Elasticsearch 같은 "stash"로 전송하는 서버사이드 데이터 처리 파이프라인이다.
Kibana: Elasticsearch에서 색인된 데이터를 검색하고 보고 시각화하며 막대 차트, 원형차트, 표, 히스토그램, 지도 등을 생성하여 데이터를 분석할 수 있게 해준다.
# 아키텍처

# Spring boot 서버 설정
dependencies의 logstash 관련 종속성을 추가한다.
## build.gradle
implementation 'net.logstash.logback:logstash-logback-encoder:8.0'
또한 logbak-spring.xml을 설정해주어야 한다.
## src/main/resources/loback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash_container:50000</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<mdc />
<context />
<logLevel />
<loggerName />
<pattern>
<pattern>
{
"app": "test-log"
}
</pattern>
</pattern>
<threadName />
<message />
<logstashMarkers />
<stackTrace />
</providers>
</encoder>
</appender>
<root level="info">
<appender-ref ref="logstash" />
</root>
</configuration>
여기서 destination 에 lostash_container를 연결했다. 이는 spring 서버와 같은 docker network이기 때문에 logstash의 컨테이너이름과 내부 포트를 썼다.
root level은 info 로 해서 info>warn>error 로그가 모두 logstash로 전달되게 구현했다.
# elk 서버 설정 (with. docker)
https://github.com/deviantony/docker-elk
GitHub - deviantony/docker-elk: The Elastic stack (ELK) powered by Docker and Compose.
The Elastic stack (ELK) powered by Docker and Compose. - deviantony/docker-elk
github.com
이 사이트를 참고해서 구현했다.
## elk 각각 설정 파일 구성한다.
위 github repo를 가져와서 설정하면 된다.
│ .env
│ .gitignore
│ docker-compose.yml
│
├─elasticsearch
│ │ .dockerignore
│ │ Dockerfile
│ │
│ └─config
│ elasticsearch.yml
│
├─filebeat
│ │ Dockerfile
│ │
│ └─config
│ filebeat.yml
│
├─kibana
│ │ .dockerignore
│ │ Dockerfile
│ │
│ └─config
│ kibana.yml
│
├─logstash
│ │ .dockerignore
│ │ Dockerfile
│ │
│ ├─config
│ │ logstash.yml
│ │
│ └─pipeline
│ logstash.conf
│
│
└─setup
│ .dockerignore
│ Dockerfile
│ entrypoint.sh
│ lib.sh
│
└─roles
filebeat_writer.json
heartbeat_writer.json
logstash_writer.json
metricbeat_writer.json
## docker-compose로 elk 서버 배포
services:
app:
build:
context: ../Owing-Api
dockerfile: Dockerfile
container_name: owing-backend-dev
ports:
- "8080:8080"
env_file:
- ../.env
setup:
container_name: setup-container
profiles:
- setup
build:
context: setup/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
init: true
volumes:
- ./setup/entrypoint.sh:/entrypoint.sh:ro,Z
- ./setup/lib.sh:/lib.sh:ro,Z
- ./setup/roles:/roles:ro,Z
environment:
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
METRICBEAT_INTERNAL_PASSWORD: ${METRICBEAT_INTERNAL_PASSWORD:-}
FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
HEARTBEAT_INTERNAL_PASSWORD: ${HEARTBEAT_INTERNAL_PASSWORD:-}
MONITORING_INTERNAL_PASSWORD: ${MONITORING_INTERNAL_PASSWORD:-}
BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
depends_on:
- elasticsearch
- kibana
- logstash
elasticsearch:
container_name: elastic_container
build:
context: elasticsearch/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,Z
- elasticsearch:/usr/share/elasticsearch/data:Z
ports:
- 9200:9200
- 9300:9300
environment:
node.name: elasticsearch
ES_JAVA_OPTS: -Xms512m -Xmx512m
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
discovery.type: single-node
restart: unless-stopped
logstash:
container_name: logstash_container
build:
context: logstash
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z
- ./logstash/pipeline:/usr/share/logstash/pipeline:ro,Z
ports:
- 5044:5044
- 50000:50000/tcp
- 50000:50000/udp
- 9600:9600
environment:
LS_JAVA_OPTS: -Xms256m -Xmx256m
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
depends_on:
- elasticsearch
restart: unless-stopped
kibana:
container_name: kibana_container
build:
context: kibana
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro,Z
ports:
- 5601:5601
environment:
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
depends_on:
- elasticsearch
restart: unless-stopped
volumes:
elasticsearch:
## kibana 접속
위 flow를 따라가면 아이디 비번은 다음과 같을 것이다.
id : elastic
pw : changeme
여기서 Observability의 log를 확인해서 로그들을 시각적으로 확인한다.
또한 elastic search를 활용하여서 빠른 검색과 logstash를 통해 로그를 분류하고, kibana를 통해 시각화 할 수 있다.
# 결과

# 참고 (cicd에서 spring - logstash 연결)
서버에서 docker network를 통해 내부로 연결을 했다면 다른 팀원분들은 무수히 많은 에러 로그를 볼 것이다.
왜냐하면 lostash가 안 설치된 분들은 에러가 나기 때문이다.
이를 위해 서버에 올라간 환경에만 연결이 되도록 jenkins에서 git clone을 받고, 필요한 코드를 추가하는 방식으로 구현했다.
jenkins pipeline에 아래와 같이 설정하면 된다.
stage('Infra adaptor Logstash') {
steps {
script {
// 1. build.gradle 파일 수정
def gradleFilePath = "Owing-Infrastructure/build.gradle"
def gradleFileContent = readFile(gradleFilePath)
// 의존성 추가
def gradleLines = gradleFileContent.split('\n')
gradleLines[1] = gradleLines[1] + "\nimplementation 'net.logstash.logback:logstash-logback-encoder:8.0'"
writeFile(file: gradleFilePath, text: gradleLines.join('\n'))
// 2. logback-spring.xml 파일 배치
withCredentials([file(credentialsId: 'logbakXML', variable: 'LOGBACK_SECRET')]) {
// 지정된 경로로 파일 복사
sh """
cp $LOGBACK_SECRET Owing-Infrastructure/src/main/resources/logback-spring.xml
"""
}
}
}
}
# 출처
'Infra > 네트워크' 카테고리의 다른 글
[Infra] 시스템 메트릭 모니터링 구축 (with. spring) (0) | 2024.11.22 |
---|---|
[Infra] 포워드 프록시와 리버스 프록시 차이점 (6) | 2024.10.19 |
# 로그를 수집하면 생기는 이점
1. 사용자 행동 분석 로그 데이터를 통해 사용자의 행동 패턴을 파악하고 이를 바탕으로 서비스 개선 및 마케팅 전략을 세울 수 있다.
2. 오류 및 버그 추적 로그를 통해 시스템 내 발생한 오류나 문제를 확인하고 추적할 수 있어, 소프트웨어의 안정성과 품질을 개선할 수 있다.
3. 성능 최적화 로그 데이터를 분석하여 데이터 베이스 작업, API 호출, 시스템 리소스 사용 등 시스템의 성능 상태를 파악하고, 이를 통해 성능 문제점을 찾아 수정할 수 있다.
4. 보안 감시 로그를 통해 시스템 내의 비정상적인 활동, 해킹 시도, 인증 실패 등을 식별하고, 보안 취약점을 찾아낼 수 있다.
이는 시스템 보안의 유지를 도울 뿐만 아니라, 사이버 공격에 대한 대응 역시 가능하게 한다.
모두 중요하지만, 여기서 필요하다고 느낀 점은 사용자 행동을 분석하여 어떤 서비스를 많이 활용하는 지 분석하는 것이라고 생각한다. 새로운 서비스가 출시또는 변경할 때, A/B 테스트를 확인하여, 변경된 서버 환경의 이점을 확인할 수 있기 때문이다. 왜냐하면 오류들은 QA를 통해 찾으면 그 에러 로직은 최근 log를 통해 쉽게 볼 수 있기 때문입니다.
# ELK 스택이란?
Elasticsearch: JSON 기반의 분산형 오픈 소스 검색 및 분석 엔진, 주로 REST API를 통해 처리한다.
Logastsh: 여러 소스에서 동시에 데이터를 수집하여 변환한 후, Elasticsearch 같은 "stash"로 전송하는 서버사이드 데이터 처리 파이프라인이다.
Kibana: Elasticsearch에서 색인된 데이터를 검색하고 보고 시각화하며 막대 차트, 원형차트, 표, 히스토그램, 지도 등을 생성하여 데이터를 분석할 수 있게 해준다.
# 아키텍처

# Spring boot 서버 설정
dependencies의 logstash 관련 종속성을 추가한다.
## build.gradle
implementation 'net.logstash.logback:logstash-logback-encoder:8.0'
또한 logbak-spring.xml을 설정해주어야 한다.
## src/main/resources/loback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash_container:50000</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<mdc />
<context />
<logLevel />
<loggerName />
<pattern>
<pattern>
{
"app": "test-log"
}
</pattern>
</pattern>
<threadName />
<message />
<logstashMarkers />
<stackTrace />
</providers>
</encoder>
</appender>
<root level="info">
<appender-ref ref="logstash" />
</root>
</configuration>
여기서 destination 에 lostash_container를 연결했다. 이는 spring 서버와 같은 docker network이기 때문에 logstash의 컨테이너이름과 내부 포트를 썼다.
root level은 info 로 해서 info>warn>error 로그가 모두 logstash로 전달되게 구현했다.
# elk 서버 설정 (with. docker)
https://github.com/deviantony/docker-elk
GitHub - deviantony/docker-elk: The Elastic stack (ELK) powered by Docker and Compose.
The Elastic stack (ELK) powered by Docker and Compose. - deviantony/docker-elk
github.com
이 사이트를 참고해서 구현했다.
## elk 각각 설정 파일 구성한다.
위 github repo를 가져와서 설정하면 된다.
│ .env
│ .gitignore
│ docker-compose.yml
│
├─elasticsearch
│ │ .dockerignore
│ │ Dockerfile
│ │
│ └─config
│ elasticsearch.yml
│
├─filebeat
│ │ Dockerfile
│ │
│ └─config
│ filebeat.yml
│
├─kibana
│ │ .dockerignore
│ │ Dockerfile
│ │
│ └─config
│ kibana.yml
│
├─logstash
│ │ .dockerignore
│ │ Dockerfile
│ │
│ ├─config
│ │ logstash.yml
│ │
│ └─pipeline
│ logstash.conf
│
│
└─setup
│ .dockerignore
│ Dockerfile
│ entrypoint.sh
│ lib.sh
│
└─roles
filebeat_writer.json
heartbeat_writer.json
logstash_writer.json
metricbeat_writer.json
## docker-compose로 elk 서버 배포
services:
app:
build:
context: ../Owing-Api
dockerfile: Dockerfile
container_name: owing-backend-dev
ports:
- "8080:8080"
env_file:
- ../.env
setup:
container_name: setup-container
profiles:
- setup
build:
context: setup/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
init: true
volumes:
- ./setup/entrypoint.sh:/entrypoint.sh:ro,Z
- ./setup/lib.sh:/lib.sh:ro,Z
- ./setup/roles:/roles:ro,Z
environment:
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
METRICBEAT_INTERNAL_PASSWORD: ${METRICBEAT_INTERNAL_PASSWORD:-}
FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
HEARTBEAT_INTERNAL_PASSWORD: ${HEARTBEAT_INTERNAL_PASSWORD:-}
MONITORING_INTERNAL_PASSWORD: ${MONITORING_INTERNAL_PASSWORD:-}
BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
depends_on:
- elasticsearch
- kibana
- logstash
elasticsearch:
container_name: elastic_container
build:
context: elasticsearch/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,Z
- elasticsearch:/usr/share/elasticsearch/data:Z
ports:
- 9200:9200
- 9300:9300
environment:
node.name: elasticsearch
ES_JAVA_OPTS: -Xms512m -Xmx512m
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
discovery.type: single-node
restart: unless-stopped
logstash:
container_name: logstash_container
build:
context: logstash
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z
- ./logstash/pipeline:/usr/share/logstash/pipeline:ro,Z
ports:
- 5044:5044
- 50000:50000/tcp
- 50000:50000/udp
- 9600:9600
environment:
LS_JAVA_OPTS: -Xms256m -Xmx256m
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
depends_on:
- elasticsearch
restart: unless-stopped
kibana:
container_name: kibana_container
build:
context: kibana
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro,Z
ports:
- 5601:5601
environment:
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
depends_on:
- elasticsearch
restart: unless-stopped
volumes:
elasticsearch:
## kibana 접속
위 flow를 따라가면 아이디 비번은 다음과 같을 것이다.
id : elastic
pw : changeme
여기서 Observability의 log를 확인해서 로그들을 시각적으로 확인한다.
또한 elastic search를 활용하여서 빠른 검색과 logstash를 통해 로그를 분류하고, kibana를 통해 시각화 할 수 있다.
# 결과

# 참고 (cicd에서 spring - logstash 연결)
서버에서 docker network를 통해 내부로 연결을 했다면 다른 팀원분들은 무수히 많은 에러 로그를 볼 것이다.
왜냐하면 lostash가 안 설치된 분들은 에러가 나기 때문이다.
이를 위해 서버에 올라간 환경에만 연결이 되도록 jenkins에서 git clone을 받고, 필요한 코드를 추가하는 방식으로 구현했다.
jenkins pipeline에 아래와 같이 설정하면 된다.
stage('Infra adaptor Logstash') {
steps {
script {
// 1. build.gradle 파일 수정
def gradleFilePath = "Owing-Infrastructure/build.gradle"
def gradleFileContent = readFile(gradleFilePath)
// 의존성 추가
def gradleLines = gradleFileContent.split('\n')
gradleLines[1] = gradleLines[1] + "\nimplementation 'net.logstash.logback:logstash-logback-encoder:8.0'"
writeFile(file: gradleFilePath, text: gradleLines.join('\n'))
// 2. logback-spring.xml 파일 배치
withCredentials([file(credentialsId: 'logbakXML', variable: 'LOGBACK_SECRET')]) {
// 지정된 경로로 파일 복사
sh """
cp $LOGBACK_SECRET Owing-Infrastructure/src/main/resources/logback-spring.xml
"""
}
}
}
}
# 출처
'Infra > 네트워크' 카테고리의 다른 글
[Infra] 시스템 메트릭 모니터링 구축 (with. spring) (0) | 2024.11.22 |
---|---|
[Infra] 포워드 프록시와 리버스 프록시 차이점 (6) | 2024.10.19 |