Quản lý log với EFK (Elasticsearch + Fluentd + Kibana) Stack
Nội dung
- Giới thiệu
- Cơ chế hoạt động
- Tại sao phải dùng EFK Stack?
- Những lợi ích khi sử dụng EFK Stack
- Triển khai trong dự án thực tế
- Kết luận
- Tài liệu thamn khảo
Giới thiệu
Với những hệ thống lớn việc quản lý log và phân loại log bằng việc xem file log của server để xác định thông tin của log, phân loại log là khá khó khăn. Cần thiết phải có một công cụ quản lý log một cách tốt hơn, sớm phát hiện những lỗi phát sinh của server hoặc kiểm tra các thông tin về log. Hiện nay cũng có khá nhiều công cụ để quản lý log khác nhau. Qua tìm hiểu thì bộ công cụ Fluentd, Elasticsearch, Kibana có nhiều ưu điểm như phần mềm mã nguồn mở hoàn toàn miễn phí, cung cấp dịch vụ quản lý log rất tốt và dễ sử dụng. Dưới đây tôi sẽ giới thiệu về bộ công cụ này.
Fluentd:
- "Fluentd" is an open-source tool to collect events and logs.
http://fluentd.org/ - Fluentd là một phần mềm trung gian tuyệt vời dựa trên Ruby dùng để đọc, xử lý và gửi log.
- Fluentd cũng có thể được mở rộng bằng cách viết plugin, hiện nay có nhiều plugin đã được develop và public.
http://fluentd.org/plugin/
Elasticsearch:
- sử dụng cơ sở dữ liệu NoSQL dựa trên nền tảng của Apache Lucene engine. Dùng để lưu trữ dữ liệu và cung cấp interface cho phép truy vấn đến cơ sở dữ liệu.
- Elasticsearch là một công cụ tìm kiếm mã nguồn mở được phát triển bởi công ty Elastic.
- Bạn có thể nhanh chóng trích xuất các tài liệu chứa các từ mong muốn từ một số lượng lớn document.
- Vì Elasticsearch không phải là cơ sở dữ liệu quan hệ, nên các câu lệnh SQL không thể được sử dụng.Thay vào đó nó hoạt động bằng cách sử dụng RESTful interface.
- Bạn có thể gặp khó khăn vì đã quen thuộc với cơ sở dữ liệu quan hệ như Oracle, MySQL vv. Tuy nhiên Elasticsearch API rất đơn giản, bạn không cần quá lo lắng nhé.
Kibana: Đây là giao diện sử dụng dành cho người dùng trên môi trường web. Kibana sẽ sử dụng Elashtichsearch để tìm kiếm các dữ liệu phù hợp với yêu cầu của người dùng.
Cơ chế hoạt động:
Cơ chế hoạt động của EFK Stack cũng khá đơn giản, các bạn xem hình sẽ hiểu:
- Đầu tiên, log sẽ được đưa đến Fluentd. (Ví dụ như log access server nginx/apache, log do develop setting trong source php/java vv. miễn là có ghi ra file log).
- Fluentd sẽ đọc những log này, thêm những thông tin như thời gian, IP, parse dữ liệu từ log (server nào, độ nghiêm trọng, nội dung log) ra, sau đó ghi xuống database là Elasticsearch.
- Khi muốn xem log, người dùng vào URL của Kibana. Kibana sẽ đọc thông tin log trong Elasticsearch, hiển thị lên giao diện cho người dùng query và xử lý.
- Log có nhiều loại (tag), do developer định nghĩa chẳng hạn access_log error_log, peformance_log, api_log. Khi Fluentd đọc log và phân loại từng loại log rồi gửi đến Elasticsearch, ở giao diện Kibana chúng ta chỉ cần add một số filter như access_log chẳng hạn và query.
Tại sao phải dùng EFK Stack?
Với các hệ thống hoặc ứng dụng nhỏ, ta không cần sử dụng EFK stack làm gì! Cứ dùng thư viện ghi log đi kèm với ngôn ngữ, sau đó ghi log ra file rồi đọc thôi!
Tuy nhiên, với những hệ thống lớn nhiều người dùng, có nhiều service phân tán (microservice), có nhiều server chạy cùng lúc… thì việc ghi log xuống file không còn hiệu quả nữa. Đơn giản 1 ví dụ quản lý log bằng cách ghi xuống file như thông thường nãy sinh vấn đề như sau:
Giả sử bạn có 10 con server web (có log nginx, apache, log fronted, backend, api, batch vv) chạy cùng lúc, bạn sẽ phải lục tung 10 con server này để đọc và tìm file log, cực quá phải không nào? Lúc này, người ta bắt đầu áp dụng centralized logging, tức ghi log tập trung vào 1 chỗ.
Việc tập trung 1 chổ và query bằng giao diện Kinaba giúp tìm log nhanh chóng ở bất kỳ server nào, loại log gì. Thật tuyệt vời đúng không.
Những lợi ích khi sử dụng EFK Stack
- Đọc log từ nhiều nguồn: Fluentd có thể đọc được log từ rất nhiều nguồn, từ log file cho đến log database cho đến UDP hay REST request.
- Dễ tích hợp: Dù bạn có dùng Nginx hay Apache, dùng MSSQL, MongoDB hay Redis, Fluentd đều có thể đọc hiểu và xử lý log của bạn nên việc tích hợp rất dễ dàng.
- Hoàn toàn free: Chỉ cần tải về, setup và dùng, không tốn một đồng nào cả. Công ty tạo ra EFK Stack kiếm tiền bằng các dịch vụ cloud hoặc các sản phẩm premium phụ thêm.
- Khả năng scale tốt: Fluentd và Elasticsearch chạy trên nhiều node nên hệ thống EFK cực kì dễ scale. Khi có thêm service, thêm người dùng, muốn log nhiều hơn, bạn chỉ việc thêm node cho Fluentd và Elasticsearch là xong.
- Search và filter mạnh mẽ: Elasticsearch cho phép lưu trữ thông tin kiểu NoSQL, hỗ trợ luôn Full-Text Search nên việc query rất dễ dàng và mạnh mẽ.
- Cộng đồng mạnh, tutorial nhiều: Nhiều công ty dùng nên dĩ nhiên là có nhiều tutorial để học và dùng EFK Stack rồi.
Triển khai trong thực tế
Về triển khai Elasticsearch Fluentd Kibana. Các bạn có thể cài tất cả cùng trên 1 máy. Việc cài đặt mình nghĩ không khó đối với anh em developer, trong bài viết này mình không trình bày cụ thể việc cài đặt như thế nào.
Hiện tại dự án mình dùng Ansible và Docker và mình xin chia sẽ cách triển khai trên môi trường test. Việc scale dùng ansible hay docker rất dễ dàng, nên mình chỉ trình bày cấu trúc đơn giản nhất.
- Về cơ bản mình có rất nhiều server chứa log, cần tập hợp hết các log này lại 1 server.
- Các server chứa log (Fluentd agent) chúng ta cài đặt Fluentd, sử dụng plugin forwarder: plugin đơn giản là cách cấu hình để gửi log đến server Tập hợp log(Fluentd aggregator)
- Tại server tập hợp log (Fluentd aggregator) chúng ta cài Fluentd với plugin Elasticsearch với mục đích là chuyển log đến cơ sở dữ liệu ES (Elasticsearch). chỉ nên dùng đúng 1 server tập hợp log.
- ES server có thể có nhiều hơn 1 server dùng để chứa dữ liệu log được gửi về từ nhiều Fluent forwarder server.
- Kibana có thể tách riêng thành 1 server riêng hoặc cài chung trên ES server, có thể dùng nhiều server cài Kibana (dùng Load Balanceing).
Ví dụ Fluentd forwarder config:
# vi /fluentd/etc/fluent.conf
<source>
@type tail
path /fluentd/log/nginx/access.log
tag nginx-lb.access
pos_file /fluentd/log/nginx-lb.access.log.pos
<parse>
time_format %d/%b/%Y:%H:%M:%S %z
expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")$/
@type regexp
</parse>
</source>
<source>
@type tail
path /fluentd/log/nginx/error.log
tag nginx-lb.error
pos_file /fluentd/log/nginx-lb.error.log.pos
<parse>
time_format %d/%b/%Y:%H:%M:%S %z
expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")$/
@type regexp
</parse>
</source>
<source>
@type tail
path /fluentd/log/nginx/ac_your_domain_80_log
tag nginx-lb.ac_your_domain_log
pos_file /fluentd/log/nginx-lb.ac_your_domain_80_log.log.pos
<parse>
time_format %d/%b/%Y:%H:%M:%S %z
expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")$/
@type regexp
</parse>
</source>
<source>
@type tail
path /fluentd/log/nginx/er_your_domain_80_log
tag nginx-lb.er_your_domain_80_log
pos_file /fluentd/log/nginx-lb.er_your_domain_80_log.log.pos
<parse>
time_format %d/%b/%Y:%H:%M:%S %z
expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")$/
@type regexp
</parse>
</source>
<match **>
@type forward
<server>
host 172.70.70.70
port 24224
</server>
<buffer>
flush_interval 1s
</buffer>
</match>
**Giải thích 1 tý **
<source>
@type tail
path /fluentd/log/nginx/access.log
tag nginx-lb.access
pos_file /fluentd/log/nginx-lb.access.log.pos
<parse>
time_format %d/%b/%Y:%H:%M:%S %z
expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")$/
@type regexp
</parse>
</source>
Ở đây mình dùng plugin parser_regexp, log được đọc từ file log sẽ được format lại theo định dạng được config: mục đích để cho dễ nhìn: Như ví dụ trên thì log nhìn thấy ở giao diện Kibana sẽ như sau:
<server>
host 172.70.70.70
port 24224
</server>
Server tâph hợp log (Fluentd aggregator) sẽ có IP là 172.70.70.70, access tới cổng 24224.
Ví dụ Fluentd aggregator config:
<source>
@type forward
</source>
<match nginx-lb.*>
@type copy
<store>
@type elasticsearch
host 172.80.80.80
port 9200
index_name ${tag}
type_name ${tag}
include_timestamp
<buffer>
flush_interval 1s
</buffer>
</store>
<store>
@type file
path /fluentd/log/project/nginx-lb/${tag}.%Y%m%d%H%M
append true
compress gz
<buffer tag,time>
@type file
path /fluentd/log/project/nginx-lb/buffer
timekey 1d
timekey_wait 1m
</buffer>
</store>
</match>
Những log nào có tag nginx-lb.* sẽ được gửi đến:
- Cơ sở dữ liệu ES (172.80.80.80 cổng 9200)
- Lưu file ở directory: /fluentd/log/project/nginx-lb/
Kết luận
Với việc sử dụng bộ 3 công cụ này, việc quản lý log trở nên dễ dàng và thuận tiện hơn rất nhiều, giảm thời gian điều tra log qua đó giúp vận hành hệ thống tốt hơn, hiệu quả hơn.
Ngoài Fluentd thì Logstash cũng có chức năng tương tự. các bạn có thể tự tìm hiểu thêm về công cụ này.
Bạn có thể tham khảo thêm một số hướng dẫn sử dụng Kibana chi tiết cho việc tìm kiếm, tạo biểu đồ, tạo báo cáo tại các link sau:
https://www.elastic.co/guide/en/beats/packetbeat/current/_kibana_query_and_filter.html
https://www.digitalocean.com/community/tutorials/how-to-use-kibana-dashboards-and-visualizations
Tài liệu tham khảo
- https://qiita.com/nskydiving/items/1c2dc4e0b9c98d164329
- http://pppurple.hatenablog.com/entry/2018/02/17/035403
- https://blog.deimos.fr/2014/08/15/deploy-a-logs-managememt-infrastructure-elasticsearchkibanfluentd-with-ansible/
- https://viblo.asia/p/quan-ly-log-voi-logstash-elasticsearch-kibana-BAQ3vVj1vbOr
- https://toidicodedao.com/2018/03/20/elk-stack-logging/#more-5151