docker-elk-tutorial📝
docker-elk ❓ 這是什麼❓ 他可以吃嗎😕
重點在 ELK ,他是由三個東西所組成的。
Elasticsearch ( E )
Logstash ( L )
Kibana ( K )
基本上,整個工作流程是這樣
步驟一
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 教學文章
透過這篇文章,你將會學會
-
logging for Django + ELK - Django 如何設定 logging 以及發送 logging 到 ELK 中
-
docker logging + ELK - 將 docker logs 發送到 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 都有正常運行
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/
接著再來看看 Kibana( 有時候你會發現無法瀏覽,這是因為還在初始化 )
等待初始化完畢後,可以瀏覽 http://localhost:5601/,你應該會看到
我們需要先設定 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
如果一切順利,你應該會看到 response
接著重新整理 http://localhost:5601/,你應該會看到 index pattern 建立成功
接著我們可以嘗試送送看 log , 如果你是 MAC 或 Linux 用戶,你可以使用以下指令
nc localhost 5000 < README.md
上面這段指令其實只是將 README.md 往 logstash ( http://localhost:5000/ ) 送資料,
可以透過 Kibana 觀看結果,會發現有一堆 README.md 的文字
如果你是 Windows 用戶,請跳過這段 😆
直接用 python 來測試吧:smirk:
剛剛簡單的介紹 ELK,現在讓我們透過 python 送 log 到 ELK 吧 😆
建議大家可以先了解一下 python 中的 logging,
也可以參考這個簡單的範例 logging_tutorial.py。
要使用 python 發送 log 到 ELK,請先執行下列指令
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 觀看
log 訊息的確是我們剛剛送出去的
如果你要測試 UDP 的部份,就把 TCP 註解,UDP 打開( 取消註解 ),
這樣以後我們就可以將我們需要記錄的 log 資料通通都送到 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 的 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
到 Kibana 觀看
再來個 udp 的簡單範例
docker run --log-driver=gelf --log-opt gelf-address=udp://0.0.0.0:12201 alpine echo hello world udp
這邊我覺得奇怪的是,如果用 gelf 送出去的 log 都會變成亂碼,
如果有人知道原因再請解答:sweat_smile:
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
,
接著到 Kibana 中可以看到 log 資訊
這篇文章主要是帶大家對 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
文章都是我自己研究內化後原創,如果有幫助到您,也想鼓勵我的話,歡迎請我喝一杯咖啡:laughing:
MIT license