JustDoEat

Django + DOCKER를 이용하여 ELK를 연동해보자(기초세팅) 1편 본문

카테고리 없음

Django + DOCKER를 이용하여 ELK를 연동해보자(기초세팅) 1편

kingmusung 2024. 1. 24. 04:20

이 글은 필요에 의해 정말 급하게 공부 한 내용이라 전문성도 없고 두서도 없습니다, 혹시 이 글을 발견하신분들은

" 뉴비가 맛본척만  했네" 라고 참고만 해주시면 감사하겠습니다. 

+테스트용이라 보안이나 여러가지 관련된 설정 또한 많이 부족합니다.

 

https://xodns.tistory.com/115

 

docker-compose로 ELK 8 버전 사용해보기 1부

https://www.elastic.co/kr/downloads/elasticsearch Download Elasticsearch Download Elasticsearch or the complete Elastic Stack (formerly ELK stack) for free and start searching and analyzing in minutes with Elastic. www.elastic.co https://www.elastic.co/kr/

xodns.tistory.com

위 블로그를 참고 후 설정하다가 공부 한 내용을 위주로 적었습니다.

대략적으로 따라서 해보면 어떤식으로 동작하는지 이해하기 쉬울거 같습니다.

 

 

 

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. - GitHub - deviantony/docker-elk: The Elastic stack (ELK) powered by Docker and Compose.

github.com

위 레포를 클론 한 후 프로젝트에 적용해주면 되겠습니다.


🔋 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 파일에 일부를 보자.

localhost://5044 이런식으로 호스트를 안쓰고, logstash:5044로 쓰는 이유는

 

도커는 자체로 DNS기능을 가지고 있어서 같은 네트워크 안에있는 컨테이너 끼리, 컨테이너 이름으로 소통이 가능함.

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로 받는다는 이야기 이고.

filter는 데이터를 elasticsearch로 보내기전에 단어 그대로 필터링을 해주는데. elasticsearch가 이해 할 수 있는 언어로 필터링을 해주는 역할이다.

 

output에 hosts 부분은 elasticsearch:9200, http:/elasticsearch:9200 두가지가 있는데  둘다 같은 의미이다.

 

(혹여나 연결에 실패했다는 오류가 뜬다면 둘중 하나씩 번갈아가면서 해보시길.. 제가 그랬습니다.. 네..) 

 

참고로 index는 키바나 접속 후 stackmanagement->indexmanagement 에 접속하면 생기는 인덱스 이름이다.

🍑 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 는 지시어이다, 도커 컨테이너 내부 경로에 로그를 남기라는말