/docker-elk-tutorial

docker-elk-tutorial + django + logging

Primary LanguagePythonMIT LicenseMIT

docker-elk-tutorial

docker-elk-tutorial📝

簡介

docker-elk ❓ 這是什麼❓ 他可以吃嗎😕

重點在 ELK ,他是由三個東西所組成的。

Elasticsearch ( E )

img

Logstash ( L )

img

Kibana ( K )

img

基本上,整個工作流程是這樣

img

步驟一

Logstash 蒐集從 docker or 其他地方的 log 資訊,這個步驟主要是因為我們可以透過 logstash.conf 過濾

以及解析我們需要的資訊。

步驟二

Logstash 將處理完後的 log 資訊轉發到 Elasticsearch 進行 index。

步驟三

最後使用者可以透過 Kibana 分析以及視覺化所要的資料。

以上就是整個工作的流程,那他有什麼用呢 😕

像是分散式系統好了,之前介紹的 docker swawm,每個容器的 log都進去一個一個看一定會累死,

所以這時候就可以統一把 log 送到 docker-elk 中,方便統一管理以及分析。

使用者的 log 非常重要,如果可以從 log 中分析出使用者愛好以及習慣,就可以推薦他類似的東西或

進行改善,當然,有一點很重要,就是這些 log 必須 處理 過,你可能會和我說可以用 AI( AI 正夯 😑 )

但這不是這次的重點:relaxed:

由於這篇文章我會採用 Docker 建立 docker-elk,所以建議對 Docker 要有一定的認識,如果你不了解

Docker ,可參考我之前的 Docker 教學文章

透過這篇文章,你將會學會

docker ELK 環境建立

我們直接使用 docker-elk 這邊的 docker-compose.yml 即可,但因為我擔心版本會

更新( 導致怪問題 ),所以我放一份到我自己的目錄下,建議閱讀一下 docker-elk

中的 README.md,先到 docker-elk 目錄底下

cd docker-elk

直接執行以下指令

docker-compose up

第一次會比較慢,因為要 pull image 而且還要初始化 😴

這時候可以起來**一下拉拉筋 ☺️

也可以用 docker ps 確認 docker-elk 都有正常運行

img

docker-compose.yml 如果沒有特別修改,默認的 port 可參考下方

5000: Logstash TCP input
9200: Elasticsearch HTTP
9300: Elasticsearch TCP transport
5601: Kibana

以上是預設的,這邊我多加上一個 UDP 的 port

12201: Logstash UDP input

那要如何加,首先,在 docker-elk/docker-compose.yml 中加上 12201:12201/udp

  logstash:
    build:
      context: logstash/
    volumes:
      - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro
      - ./logstash/pipeline:/usr/share/logstash/pipeline:ro
    ports:
      - "5000:5000"
      - "12201:12201/udp"
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    networks:
      - elk
    depends_on:
      - elasticsearch

接著在 docker-elk/logstash/pipeline/logstash.conf 底下加上 udp

input {
    tcp {
        port => 5000
    }
    udp {
        port => 12201
    }
}

## Add your filters / logstash plugins configuration here

output {
    elasticsearch {
        hosts => "elasticsearch:9200"
    }
}

logstash.conf 可以設定的真的非常多,像是 filters ,大家可以自行去摸索,這邊先不介紹:smirk:

確認啟動成功後,我們可以先來看看 Elasticsearch,瀏覽 http://localhost:9200/

img

接著再來看看 Kibana( 有時候你會發現無法瀏覽,這是因為還在初始化 )

等待初始化完畢後,可以瀏覽 http://localhost:5601/,你應該會看到

img

我們需要先設定 index pattern,MAC 或 Linux 用戶直接使用以下指令

curl -XPOST -D- "http://localhost:5601/api/saved_objects/index-pattern" \
    -H "Content-Type: application/json" \
    -H "kbn-version: 6.1.0" \
    -d "{'attributes':{'title':'logstash-*','timeFieldName':'@timestamp'}}"

如果你是 Windows 用戶,請用其他方法,雖然 Windows 也有 curl,但我裝上去執行指令,

他都會報錯說 josn格式錯誤,所以我直接改用 Postman

img

如果一切順利,你應該會看到 response

img

接著重新整理 http://localhost:5601/,你應該會看到 index pattern 建立成功

img

接著我們可以嘗試送送看 log , 如果你是 MAC 或 Linux 用戶,你可以使用以下指令

nc localhost 5000 < README.md

上面這段指令其實只是將 README.md 往 logstash ( http://localhost:5000/ ) 送資料,

可以透過 Kibana 觀看結果,會發現有一堆 README.md 的文字

img

如果你是 Windows 用戶,請跳過這段 😆

直接用 python 來測試吧:smirk:

透過 python 送 log 到 ELK

剛剛簡單的介紹 ELK,現在讓我們透過 python 送 log 到 ELK 吧 😆

建議大家可以先了解一下 python 中的 logging

也可以參考這個簡單的範例 logging_tutorial.py

要使用 python 發送 log 到 ELK,請先執行下列指令

python-logstash

pip install python-logstash

接著執行以下程式碼 python-logging/demo_logging.py

import logging
import logstash
import sys

host = 'localhost'

test_logger = logging.getLogger('python-logstash-logger')
test_logger.setLevel(logging.INFO)

# UDP
# test_logger.addHandler(logstash.LogstashHandler(host, 12201, version=1))

# TCP
test_logger.addHandler(logstash.TCPLogstashHandler(host, 5000, version=1))

test_logger.error('python-logstash: test logstash error message.')
test_logger.info('python-logstash: test logstash info message.')
test_logger.warning('python-logstash: test logstash warning message.')

# add extra field to logstash message
extra = {
    'test_string': 'python version: ' + repr(sys.version_info),
    'test_boolean': True,
    'test_dict': {'a': 1, 'b': 'c'},
    'test_float': 1.23,
    'test_integer': 123,
    'test_list': [1, 2, '3'],
}
test_logger.info('python-logstash: test extra fields', extra=extra)
print('done,please see kibana')

接著可以到 Kibana 觀看

img

log 訊息的確是我們剛剛送出去的

img

如果你要測試 UDP 的部份,就把 TCP 註解,UDP 打開( 取消註解 ),

這樣以後我們就可以將我們需要記錄的 log 資料通通都送到 ELK 中管理 👍

logging for Django + ELK

剛剛介紹了如何透過 python 送 log 到 ELK 中,現在要教大家如何在 Django 中設定 logging 😏

如果不了解什麼是 Django,可參考我之前寫的 Django 基本教學 - 從無到有 Django-Beginners-Guide 📝

一樣請記得安裝 python-logstash 😊

pip install python-logstash

我們就依照 這篇 的範例繼續介紹,

先將 django-tutorial/django-tutorial/settings.py 加入下方程式碼

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'logstash': {
            'level': 'WARNING',
            'class': 'logstash.TCPLogstashHandler',
            'host': 'localhost',
            'port': 5000,  # Default value: 5000
            'version': 1,
            'message_type': 'django_logstash',  # 'type' field in logstash message. Default value: 'logstash'.
            'fqdn': False,  # Fully qualified domain name. Default value: false.
            'tags': ['django.request'],  # list of tags. Default: None.
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': True,
        },
        'django.request': {
            'handlers': ['logstash'],
            'level': 'WARNING',
            'propagate': True,
        },
    }
}

詳細的 django logging 可參考官網 https://docs.djangoproject.com/en/2.0/topics/logging/

這邊要稍微提一下 django.request

django.request
Log messages related to the handling of requests.
5XX responses are raised as ERROR messages;
4XX responses are raised as WARNING messages.

接著到 django-tutorial/musics/views.py中修改程式碼

from django.shortcuts import render

from musics.models import Music
from django.http import Http404

# Create your views here.
def hello_view(request):
    musics = Music.objects.all()
    # raise Exception('error !!!!')
    # raise Http404("sorry 404")
    return render(request, 'hello_django.html', {
        'data': "Hello Django ",
        'musics': musics,
})

以上註解的兩個地方,可以自行玩玩看,然後到 Kibana 中觀看,

如果不太理解,可參考影片的說明 Youtube Tutorial PART 4 - logging for Django + ELK

raise Exception('error !!!!') 這行等於是 5XX responses,也就是 ERROR messages,

raise Http404("sorry 404") 這行等於是 ˋXX responses,也就是 WARNING messages。

docker logging + ELK

既然都講到這裡了,一定要來說一下如何將 docker 的 log 送到 ELK 中,

先來個 tcp 的簡單範例

docker run --log-driver=syslog --log-opt syslog-address=tcp://0.0.0.0:5000 --log-opt syslog-facility=daemon alpine echo hello world tcp

img

到 Kibana 觀看

img

再來個 udp 的簡單範例

docker run --log-driver=gelf --log-opt gelf-address=udp://0.0.0.0:12201 alpine echo hello world udp

img

這邊我覺得奇怪的是,如果用 gelf 送出去的 log 都會變成亂碼,

如果有人知道原因再請解答:sweat_smile:

img

docker logging 詳細可參考 https://docs.docker.com/engine/admin/logging/overview/

那如果我希望寫在 docker-compose 中呢?

請看 docker-logging/docker-compose.yml

version: '3.3'
services:

    db:
      # container_name: 'postgres'
      image: postgres
      environment:
        POSTGRES_PASSWORD: password123
      ports:
        - "5432:5432"
        # (HOST:CONTAINER)
      volumes:
        - pgdata:/var/lib/postgresql/data/

    web:
      # build: ./api
      # command: python manage.py runserver 0.0.0.0:8000
      image: twtrubiks/my_django
      restart: always
      volumes:
        - api_data:/docker_api
        # (HOST:CONTAINER)
      ports:
        - "8000:8000"
        # (HOST:CONTAINER)
      depends_on:
        - db

      logging:
        driver: syslog
        options:
            syslog-address: tcp://0.0.0.0:5000
            tag: web-container-tcp

      # logging:
      #   driver: gelf
      #   options:
      #     gelf-address: udp://0.0.0.0:12201
      #     tag: web-container-udp

volumes:
    api_data:
    pgdata:

以上這個範例是從 Docker 基本教學 - 從無到有 Docker-Beginners-Guide修改過來的,

一樣執行 docker-compose up

img

接著到 Kibana 中可以看到 log 資訊

img

後記:

這篇文章主要是帶大家對 ELK 有一些基本的觀念,因為 ELK 可以玩的東西真的非常的多,

坑很大,像是前面所說的 logstash.conf 中可以設定的參數,像是 filters 之類的.......

又或是 Kibana 如何呈現精美的圖表,甚至將 docker-elk 佈署到 Swarm 中,都可以玩玩

看,所以大家有興趣可以再自行深入研究:smile:

我本來是想要透過 Django 結合 Haystack 做個全文檢索的範例,但因為 Haystack 對於

ElasticSearch 的版本只支援到 2.X ( ElasticSearch 都出到 6.X 了 ),最後就沒有將這範例

寫出來了:sweat_smile:

elasticsearch-py 這個 library 也可以看看,我用 6.x 版本測試,還是有一點問題,問題

如果解決再分享給各位:laughing:

執行環境

  • Python 3.6.2

Reference

Donation

文章都是我自己研究內化後原創,如果有幫助到您,也想鼓勵我的話,歡迎請我喝一杯咖啡:laughing:

alt tag

贊助者付款

License

MIT license