Triển khai ELK trên Docker để thu thập và phân tích nhật ký container

Tổng quan về kiến trúc

Trong môi trường container hóa, việc quản lý nhật ký tập trung trở nên quan trọng. Hệ thống ELK (Elasticsearch, Logstash, Kibana) được triển khai dưới dạng container cung cấp giải pháp thu thập, lưu trữ và phân tích nhật ký hiệu quả. Bài viết này trình bày cách triển khai đầy đủ từ khâu thu thập nhật ký container, tự động tạo chỉ mục, đến giám sát cảnh báo và quản lý vòng đời dữ liệu.

Triển khai các thành phần ELK dưới dạng container

Khởi tạo Elasticsearch

Container Elasticsearch được cấu hình với các thông số quan trọng:

docker container run -d \
    --privileged \
    -p 127.0.0.1:9200:9200 \
    -p 9300:9300 \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name es-node \
    --restart unless-stopped \
    -e "discovery.type=single-node" \
    -v /storage/es-data:/usr/share/elasticsearch/data \
    docker.elastic.co/elasticsearch/elasticsearch:6.6.2

chown -R 1000:1000 /storage/es-data

Các tham số chính:

  • Port 9200 cho API HTTP, port 9300 cho giao tiếp cluster
  • Giới hạn kích thước file log: tối đa 10MB/file, giữ lại 3 file
  • Chế độ khởi động lại tự động
  • Chế độ single-node cho triển khai đơn giản
  • Mount volume lưu trữ dữ liệu ra host

Cấu hình và chạy Logstash

Tạo file cấu hình pipeline cho Logstash:

mkdir -p /storage/logstash-config
cat > /storage/logstash-config/pipeline.conf << "CONFIG_END"
input {
  beats {
    host => "0.0.0.0"
    port => "5044"
  }
}
filter {
  grok {
    match => { 
      "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:content}" 
    }
  }
  mutate {
    remove_field => ["@version", "host"]
  }
}
output {
  elasticsearch {
    hosts => [ "es-node:9200" ]
    index => "logs-%{container_id}-%{+YYYY.MM.dd}"
  }
}
CONFIG_END

Khởi chạy container Logstash:

docker container run -d \
    -p 5044:5044 \
    --name log-processor \
    --link es-node \
    --restart unless-stopped \
    -v /storage/logstash-config/pipeline.conf:/usr/share/logstash/pipeline/logstash.conf \
    docker.elastic.co/logstash/logstash:6.6.2

Triển khai Kibana với plugin

cat > /storage/kibana-config.yml << "YAML_END"
server.name: kibana
server.host: "0.0.0.0"
elasticsearch.hosts: http://es-node:9200
monitoring.ui.container.elasticsearch.enabled: true
YAML_END

docker container run -d \
    -p 5601:5601 \
    --name kibana-ui \
    --link es-node \
    --restart unless-stopped \
    -v /storage/kibana-config.yml:/usr/share/kibana/config/kibana.yml \
    docker.elastic.co/kibana/kibana:6.6.2

Thu thập nhật ký container với Filebeat

Cấu hình Filebeat nâng cao

# /storage/filebeat-config.yml
filebeat.inputs:
- type: log
  paths:
    - '/var/lib/docker/containers/*/*.log'
  
  # Xử lý JSON output từ Docker
  json.keys_under_root: true
  json.add_error_key: true
  json.message_key: log
  
  # Xử lý multi-line log
  multiline.pattern: ^\d{4}
  multiline.negate: true
  multiline.match: after
  
  # Lọc log
  exclude_lines: ['DEBUG']
  include_lines: ['ERROR', 'WARN', 'INFO']

processors:
  - add_docker_metadata:
      host: "unix:///var/run/docker.sock"
  
  - rename:
      fields:
        - from: "docker.container.name"
          to: "container_name"
        - from: "docker.container.id"
          to: "container_id"
        - from: "json.log"
          to: "raw_message"
  
  - drop_fields:
      fields: ["ecs", "agent", "input"]

output.logstash:
  hosts: ["host.docker.internal:5044"]

Khởi động Filebeat collector

docker container run -d \
    --name log-collector \
    --privileged \
    --restart unless-stopped \
    -v /storage/filebeat-config.yml:/usr/share/filebeat/filebeat.yml:ro \
    -v /var/lib/docker/containers:/var/lib/docker/containers:ro \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    docker.elastic.co/beats/filebeat:6.6.2

Thiết lập cảnh báo với ElastAlert

Triển khai ElastAlert Server

# Clone và chuẩn bị cấu hình
git clone https://github.com/bitsensor/elastalert.git
cd elastalert

# Điều chỉnh cấu hình kết nối Elasticsearch
sed -i 's/localhost:9200/es-node:9200/g' config/elastalert.yaml

# Khởi chạy container
docker container run -d \
    -p 3030:3030 \
    --name alert-engine \
    --link es-node \
    -v $(pwd)/config/elastalert.yaml:/opt/elastalert/config.yaml \
    -v $(pwd)/alert-rules:/opt/elastalert/rules \
    bitsensor/elastalert:latest

Cấu hình quy tắc cảnh báo mẫu

# alert-rules/error-threshold.yaml
name: "High Error Rate Alert"
type: frequency
index: logs-*
num_events: 10
timeframe:
  minutes:这四个数字

filter:
- query:
    query_string:
      query: "level:ERROR"

alert:
- "slack"

slack_webhook_url: "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
slack_username: "ELK Monitor"
slack_channel: "#alerts"

alert_subject: "High Error Rate Detected in {container_name}"
alert_text: |
  Container: {container_name}
  Error Count: {num_hits}
  Time Range: {timeframe}

Tự động dọn dẹp chỉ mục cũ

Script xóa chỉ mục theo thời gian

#!/bin/bash
# /scripts/cleanup-old-indices.sh

ES_HOST="127.0.0.1"
ES_PORT="9200"
RETENTION_DAYS=7
LOG_FILE="/var/log/index-cleanup.log"

# Lấy danh sách tất cả indices
INDICES=$(curl -s "${ES_HOST}:${ES_PORT}/_cat/indices?h=index" | grep -E 'logs-.+-[0-9]{4}\.[0-9]{2}\.[0-9]{2}$')

CURRENT_TS=$(date +%s)
RETENTION_SECONDS=$((RETENTION_DAYS * 24 * 3600))

for INDEX in $INDICES; do
    # Trích xuất ngày từ tên index
    INDEX_DATE=$(echo $INDEX | grep -o '[0-9]\{4\}\.[0-9]\{2\}\.[0-9]\{2\}$')
    
    if [ -n "$INDEX_DATE" ]; then
        # Chuyển đổi định dạng ngày
        INDEX_TS=$(date -d "${INDEX_DATE//./-}" +%s 2>/dev/null)
        
        if [ $? -eq 0 ]; then
            AGE=$((CURRENT_TS - INDEX_TS))
            
            if [ $AGE -gt $RETENTION_SECONDS ]; then
                echo "$(date): Deleting index $INDEX (age: $((AGE/86400)) days)" >> $LOG_FILE
                curl -XDELETE "${ES_HOST}:${ES_PORT}/${INDEX}" >> $LOG_FILE 2>&1
            fi
        fi
    fi
done

Thiết lập cron job tự động

# Thêm vào crontab
0 2 * * * /scripts/cleanup-old-indices.sh

Kiểm tra và giám sát

Sau khi triển khai hoàn tất:

  1. Truy cập Kibana tại http://localhost:5601
  2. Tạo index pattern: logs-*
  3. Kiểm tra log trong Discover tab
  4. Xác minh kết nối ElastAlert trong plugin
  5. Kiểm tra cảnh báo qua kênh đã cấu hình

Thẻ: Elasticsearch Logstash kibana Filebeat docker

Đăng vào ngày 12 tháng 8 lúc 21:26