JustDoEat
Django + DOCKER를 이용하여 ELK를 연동해보자(기초세팅) 1편 본문
이 글은 필요에 의해 정말 급하게 공부 한 내용이라 전문성도 없고 두서도 없습니다, 혹시 이 글을 발견하신분들은
" 뉴비가 맛본척만 했네" 라고 참고만 해주시면 감사하겠습니다.
+테스트용이라 보안이나 여러가지 관련된 설정 또한 많이 부족합니다.
위 블로그를 참고 후 설정하다가 공부 한 내용을 위주로 적었습니다.
대략적으로 따라서 해보면 어떤식으로 동작하는지 이해하기 쉬울거 같습니다.
https://github.com/deviantony/docker-elk
위 레포를 클론 한 후 프로젝트에 적용해주면 되겠습니다.
🔋 ELK란?
ELK는 Elasticsearch, Logstash, 그리고 Kibana로 구성되어 있고. 각 구성 요소는 로그 데이터 수집, 저장, 검색, 시각화에 특화된 기능을 제공하는데, Logstash가 중간다리로써 데이터를 elasticsearch로 보냄, 그 데이터를 Elasticsearch가 저장(로그DB역할)을하고, Kibana가 시각화를 해주는 대쉬보드 역할을 해주는데 이러한 과정들에서 사용되는 기술스택을 ELK스택이라고 한다.
filebeat:
logstash로 가기전에, filebeat가 log파일이나 text파일을 수집 후 logstash로 보내주는 역할을 함.
logstash:
중간 다리 역할로 filebeat에서 온 데이터를 필터를 통해 가공 후 elasticsearch로 보내줌.
elasticsearch:
쉽게 생각하면 nosql형태 DB라고 생각하면 좋다, 물론 db처럼 트렌젝션등의 기능은 없고 검색엔진에 특화 되어서 여기로 들어온 데이터를 분석하는데 탁월한 친구임.
kivana:
elasticsearch에 저장된 데이터를 보기 좋게 대쉬보드에 띄어주는 역할을 하는 친구임.
filebeat - logstash - elasticsearch - kibana 순서로 설명을 이거가도록 하겠습니다.
Doker, Doker-Compose에 대한 설명은 가장 마지막에 적어놓겠습니다.
🍑 filebeat
filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/*.log
#파일비트에 들어오는 로그들의 path는 filebeat 컨테이너 상 /var/log/nginx/*.log 라는 경로에 있는 파일들이다.
output.logstash:
hosts: ["logstash:5044"]
#출력으로써는 파일비트로 들어온 로그들을 logstash로 전송을 해준다는소리
setup.kibana:
host: "http://kibana:5601"
username: "elastic"
password: "changeme"
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/*.log
✅ filebeat로 input이 들어오는 경로는 도커컨테이너 상 경로 /var/log/nginx 에 있는 모든로그파일 /*.log 이라는 소리
output.logstash:
hosts: ["logstash:5044"]
✅ output은 기 설명 했던것처럼 logstash라는 파이프 라인으로 가야한다.
+ 추가설명
hosts: ["logstash:5044"]
docker-compose.yml
#생략
logstash:
container_name: logstash
build:
context: logstash
#생략
ports:
- 5044:5044
docker-compose.yml 파일에 일부를 보자.
logstash 라는 컨테이너에 5044포트로 output이 간다는 이야기다.
주의사항으로는 도커 컴포즈 설정을 할때 같은 네트워크 안에 있어야 이런방식이 가능하다.
🍑 logstash
logstash.yml
---
## Default Logstash configuration from Logstash base image.
## https://github.com/elastic/logstash/blob/main/docker/data/logstash/config/logstash-full.yml
#
http.host: 0.0.0.0
node.name: logstash
pipline / logstash.conf
input {
beats {
port => 5044
host => "0.0.0.0"
}
}
filter {
.
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "weblogs-%{+YYYY.MM.dd}"
# document_type => "nginx_logs"
user => "elastic"
password => "changeme"
}
stdout { codec => rubydebug }
}
input은 filebeat로 받는다는 이야기 이고.
🍑 ElasticSerarch
elasticsearch.yml
---
## Default Elasticsearch configuration from Elasticsearch base image.
## https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/config/elasticsearch.yml
#
cluster.name: docker-cluster
network.host: 0.0.0.0
## X-Pack settings
## see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-settings.html
#
xpack.license.self_generated.type: basic
# elasticsearch에서 보안이 활성화 되어있을 경우 kibana는 HTTPS를 통해 elasticsearch에 연결 되어야 함.
# 현재 true로 할 경우 kibana에서 "kibana server is not ready yet."이라고 출력함.
xpack.security.enabled: false
xpack.license.self_generated.type: trial
처음 에는 trial로 되어있는데 이 부분을 basic으로 바꿔줘야 한다.
trial은 시험판 라이선스는 Elastic에서 제공하는 무료 평가판 라이선스로, 제한된 기간 동안 Elastic Stack의 모든 기능을 무제한으로 사용할 수 있습니다. 시험판 기간이 만료되면, 해당 라이선스는 자동으로 제거되고 Elastic Stack의 일부 기능이 비활성화될 수 있습니다. xpack.license.self_generated.type 설정을 변경하면 라이선스 유형을 변경할 수 있습니다. 예를 들어, 상업적인 용도로 사용할 경우에는 시험판 라이선스 대신 별도의 유료 라이선스를 구매하여 설정할 수 있습니다.
xpack.security.enabled: True
이 부분도 True로 되어있는데 현제는 간단한 연동을 할 예정이므로 false로 바꾸어 주었다.
🍑 kivana
server.name: kibana
server.host: 0.0.0.0 # 모든 네트워크 인터페이스에서 요청 수락
# Elasticsearch Connection Settings
elasticsearch.hosts: [ http://elasticsearch:9200 ] # Elasticsearch 클러스터 엔드포인트 설정
monitoring.ui.container.elasticsearch.enabled: true # Kibana Monitoring에서 Elasticsearch 모니터링 활성화
monitoring.ui.container.logstash.enabled: true # Kibana Monitoring에서 Logstash 모니터링 활성화
# SSL Verification (for Testing/Development)
elasticsearch.ssl.verificationMode: none # SSL 인증서의 유효성 검사 모드 설정 (none: 검사 안 함) 테스트 용이라 none으로 비꿈
Docker
ARG ELASTIC_VERSION
FROM docker.elastic.co/beats/filebeat:${ELASTIC_VERSION}
ARG ELASTIC_VERSION
# https://www.docker.elastic.co/
FROM docker.elastic.co/logstash/logstash:${ELASTIC_VERSION}
# Add your logstash plugins setup here
# Example: RUN logstash-plugin install logstash-filter-json
ARG ELASTIC_VERSION
# https://www.docker.elastic.co/
FROM docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_VERSION}
# Add your elasticsearch plugins setup here
# Example: RUN elasticsearch-plugin install analysis-icu
ARG ELASTIC_VERSION
# https://www.docker.elastic.co/
FROM docker.elastic.co/kibana/kibana:${ELASTIC_VERSION}
# Add your kibana plugins setup here
# Example: RUN kibana-plugin install <name|url>
각각 Docker 파일들을 보면 공통점이 있습니다. 결과만 말씀드리면,
ARG ELASTIC_VERSION
✅ ELASTIC_VERSION 이라는 환경변수를 사용한다는 뜻.
FROM docker.elastic.co/logstash/logstash:${ELASTIC_VERSION}
✅ 위 경로로 가서 이미지를 기지고 온다는 뜻.
Docker-Compose
version: '3.7'
services:
setup:
profiles:
- setup
build:
context: ./elk/setup
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
init: true
volumes:
- ./elk/setup/entrypoint.sh:/entrypoint.sh:ro,Z
- ./elk/setup/lib.sh:/lib.sh:ro,Z
- ./elk/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:-}
networks:
- elk
depends_on:
- elasticsearch
- kibana
- logstash
- filebeat
elasticsearch:
container_name: elasticsearch
build:
context: ./elk/elasticsearch
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./elk/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
# Bootstrap password.
# Used to initialize the keystore during the initial startup of
# Elasticsearch. Ignored on subsequent runs.
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
# Use single node discovery in order to disable production mode and avoid bootstrap checks.
# see: https://www.elastic.co/guide/en/elasticsearch/reference/current/bootstrap-checks.html
discovery.type: single-node
networks:
- elk
restart: unless-stopped
logstash:
container_name: logstash
build:
context: ./elk/logstash
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./elk/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z
- ./elk/logstash/pipeline:/usr/share/logstash/pipeline:ro,Z
- ./haruProject/logs/:/logs/
ports:
- 5044:5044
- 50000:50000/tcp
- 50000:50000/udp
- 9600:9600
environment:
LS_JAVA_OPTS: -Xms256m -Xmx256m
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
restart: unless-stopped
kibana:
container_name: kibana
build:
context: ./elk/kibana
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./elk/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro,Z
- ./elk/kibana/dashboard/:/usr/share/kibana/data/
ports:
- 5601:5601
environment:
KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
restart: unless-stopped
filebeat:
container_name: filebeat
build:
context: ./elk/filebeat
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
# Run as 'root' instead of 'filebeat' (uid 1000) to allow reading
# 'docker.sock' and the host's filesystem.
user: root
command:
# Log to stderr.
- -e
# Disable config file permissions checks. Allows mounting
# 'config/filebeat.yml' even if it's not owned by root.
# see: https://www.elastic.co/guide/en/beats/libbeat/current/config-file-permissions.html
- --strict.perms=false
volumes:
- ./elk/filebeat/config/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro,Z
#- ./nginx/logs:/var/log/nginx
environment:
FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
networks:
elk:
driver: bridge
volumes:
elasticsearch:
오류
Error fetching categories2
Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.
✅ Kibana 설정 파일인 kibana.yml에 암호화 키를 설정해야함. 설정 파일에서 xpack.encryptedSavedObjects.encryptionKey 항목을 찾은 후
.
xpack.encryptedSavedObjects.encryptionKey: 32글자 이상 입력
✅ 이러한 조치를 취한 후 Kibana를 다시 시작하면 문제가 해결될 것입니다. 암호화 키가 설정되면 Encrypted Saved Objects 플러그인이 정상적으로 작동할 수 있습니다
+ 이부분은 보안 설정부분을 trial -> basic으로 하면 설정을 안해도 되더라
logstash가 nginx의 로그를 읽어오지 못하는 오류
-도커의 Backend 볼륨, Nginx 볼륨 연동 누락
docker-compose.yml(docker-elk폴더가 아닌 원래 프로젝트 파일)
nginx:
build:
context: nginx
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
# - "443:443"
volumes:
- build_folder:/var/www/frontend
- ./nginx/logs:/var/log/nginx #이걸 추가야야함
#엔진엑스 컨테이너에 경로 보면 생성이 되어있을거임
depends_on:
- frontend
expose:
- '80'
# - '443'
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
networks:
- haru
- ./nginx/logs:/var/log/nginx #이걸 추가야야함
#엔진엑스 컨테이너에 경로 보면 생성이 되어있을거임
✅ Nginx컨테이너에 보면 엔진엑스의 로그를 저장하는 부분이 있다, 이 부분을 볼륨으로 연동을 시켜야, 도커로 nginx가 작동하면서 쌓인로그가 로컬에 연동이 되어서 그 부분을 Filebeat가 마운트를 해서 로그를 가지고 와야함.
docker-compose.yml(elk스택에 있는 컴포즈파일중 filebeat 부분)
filebeat: #설명에 관련없는 부분 전부 삭제
volumes:
- ./nginx/logs:/var/log/nginx
✅ 그리고 이 로그가 쌓인 로컬 폴더경로를 Filebeat가 볼륨으로 마운트를 시켜주고 그 경로를 Filebeat의 input경로로 지정해주면 됩니다.
엔진엑스.conf——————————————
upstream haru {
server localhost:8000;
}
# 서버 블록 시작
server {
listen 80;
server_name localhost;
charset utf-8;
# Allow only for register SSL (Certbot)
# location /.well-known/acme-challenge/ {
# allow all;
# root /var/www/certbot;
# }
# Access 로그를 /var/log/nginx/access.log 파일에 남기도록 설정
access_log /var/log/nginx/access.log; #이부분 추가
#access_log 는 지시어이다, 도커 컨테이너 내부 경로에 로그를 남기라는말
location ~* (service-worker\.js)$ {
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
expires off;
proxy_no_cache 1;
}
location /api/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
proxy_pass http://haru;
}
location /ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_pass http://haru;
}
location / {
# include /etc/nginx/mime.types;
root /var/www/frontend;
# index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /metrics {
stub_status on; # stub_status 활성화
allow all; # allow 접근을 허용할 주소 설정
# deny 접근을 허용하지 않을 주소 설정
}
}
# upstream 지시어 설정
# Access 로그를 /var/log/nginx/access.log 파일에 남기도록 설정
access_log /var/log/nginx/access.log; #이부분 추가
#access_log 는 지시어이다, 도커 컨테이너 내부 경로에 로그를 남기라는말