Skip to content

Technical

Hướng dẫn cài đặt ELK stack

ELK stack là bộ ba đi liền với nhau trong việc central log và visualization. Bài viết này hướng dẫn cài đặt ELK stack đơn giản

Sử dụng docker

  • Project structure
.
├── docker-compose.yml
├── .env
├── elasticsearch
│   ├── config
│   │   ├── elasticsearch.yml
│   │   └── log4j2.properties
│   └── Dockerfile
├── filebeat
│   ├── config
│   │   └── filebeat.yml
│   ├── Dockerfile
│   └── ingress
│       └── test.log
├── kibana
│   ├── config
│   │   └── kibana.yml
│   └── Dockerfile
└── logstash
    ├── config
    │   └── logstash.yml
    ├── Dockerfile
    └── pipeline
        └── logstash.conf

Trong ví dụ này, filebeat sẽ đọc các thay đổi từ test.log, transform chúng theo rule được quy định tại filebeat.yml, gửi tới logstash. Logstash sẽ transform một lần nữa (nếu có) và gửi chúng tới elasticsearch. Cuối cùng, kibana sẽ đọc data từ elasticsearch và tạo các chart.

docker-compose.yml
version: '2.29.1'
services:
  kibana:
    build:
      context: ./kibana
    container_name:  mykiba
    volumes:
      - ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro,Z
    ports:
      - 5601:5601
    environment:
      KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
    networks:
      - elk
    depends_on:
      - elasticsearch
    restart: unless-stopped

  elasticsearch:
    build:
      context: ./elasticsearch
    container_name: myes
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,Z
      - ./elasticsearch/config/log4j2.properties:/usr/share/elasticsearch/config/log4j2.properties:ro,Z
      - elasticsearch:/usr/share/elasticsearch/data:Z
    ports:
      - 9200:9200
      - 9300:9300
    environment:
      node.name: elasticsearch
      ES_JAVA_OPTS: -Xms512m -Xmx512m
      ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
      discovery.type: single-node
    networks:
      - elk
    restart: unless-stopped

  logstash:
    build:
      context: ./logstash
    container_name: mylogs
    volumes:
      - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z
      - ./logstash/pipeline:/usr/share/logstash/pipeline:ro,Z
    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
    restart: unless-stopped
    depends_on:
      - elasticsearch

  filebeat:
    container_name: mybeat
    hostname: filebeat
    build:
      context: ./filebeat
    user: root
    command:
      - -e
      - --strict.perms=false
    volumes:
      - ./filebeat/config/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro,Z
      - ./filebeat/ingress:/var/log/logify/
    environment:
      FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
      BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
    networks:
      - elk

networks:
  elk:
    driver: bridge

volumes:
  elasticsearch:

Cài đặt các biến

.env
1
2
3
4
5
FILEBEAT_INTERNAL_PASSWORD='your_file_beat_pass'
BEATS_SYSTEM_PASSWORD='your_file_beat_pass'
LOGSTASH_INTERNAL_PASSWORD='your_file_beat_pass'
ELASTIC_PASSWORD='your_file_beat_pass'
KIBANA_SYSTEM_PASSWORD='your_file_beat_pass'

Filebeat

Filebeat là yếu tố đầu tiên ta cần quan tâm. Do nó là yếu tố đầu tiên làm việc với log file. Sử dụng các rule transform cần thiết để parse log theo nhu cầu. Trước khi chuyển log sang logstash, nên in chung chúng ra màn hình trước để quan sát các thay đổi.

Dockerfile
FROM docker.elastic.co/beats/filebeat:8.14.3
filebeat.yml
logging.level: error

filebeat.inputs:
- type: log
  paths:
    - /var/log/logify/test.log
  scan_frequency: 5s

processors:
  - dissect:
      tokenizer: "%{event_time} %{+event_time} %{log_level} %{component}: allowed=%{allowed}\tugi=%{user}@%{realm} (auth:%{auth})\tip=/%{source_ip}\tcmd=%{command}\tsrc=%{source_path}\tdst=%{dst}\tperm=%{owner}:%{group}:%{permission}\tproto=%{proto}\tcallerContext=%{caller_context}"
      field: "message"
      target_prefix: "data"
      trim_values: "all"
      trim_chars: " \t"
      ignore_failure: true

  - drop_fields:
      fields: ["log.flags"]
  - drop_fields:
      fields: ["message","agent","ecs","input","parse"]


# This output for print on console 
output.console:
  pretty: true

# Comment above and uncomment bellow to output to logstash
# output.logstash:
#   hosts: ["logstash:5044"]

Logstash

Sau khi đã parse log thành công như ý muốn, ta chuyển nó đến logstash để transform một lần nữa (nếu có). Từ logstash, ta không chỉ có thể chuyển data tới elasticsearch mà còn nhiều ứng dụng khác như Kafka...

Dockerfile
FROM docker.elastic.co/logstash/logstash:8.14.3
logstash.yml
1
2
3
http.host: 0.0.0.0

node.name: logstash
logstash.conf
input {
    beats {
        port => 5044
    }

    tcp {
        port => 50000
    }
}

filter {
    mutate {
        rename => { "data" => "message" }
    }
}

output {
    elasticsearch {
        index => "filebeat"
        hosts => "elasticsearch:9200"
        user => "logstash_internal"
        password => "${LOGSTASH_INTERNAL_PASSWORD}"
    }
}

Elasticsearch

Elasticsearch là trái tim của mô hình, cần start nó lên trước khi start các ứng dụng khác.

Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:8.14.3
elasticsearch.yml
1
2
3
4
5
---
cluster.name: docker-cluster
network.host: 0.0.0.0
xpack.license.self_generated.type: basic
xpack.security.enabled: false

Kibana

Dockerfile
FROM docker.elastic.co/kibana/kibana:8.14.3
kibana.yml
---
server.name: kibana
server.host: 0.0.0.0
elasticsearch.hosts: [ http://elasticsearch:9200 ]

monitoring.ui.container.elasticsearch.enabled: true
monitoring.ui.container.logstash.enabled: true

elasticsearch.username: kibana_system
elasticsearch.password: ${KIBANA_SYSTEM_PASSWORD}

Tới đây, ta chỉ cần run docker compose up --build để chạy tất cả các container. Khi thành công, các bạn truy cập http://localhost:5601 để vào giao diện kibana và cấu hình các dashboard cần thiết.

Build openssl from source

  • Install prerequisite
    dnf install -y perl
    
  • Clone source code
    wget https://github.com/openssl/openssl/releases/download/openssl-3.2.1/openssl-3.2.1.tar.gz
    
  • Giải nén source
    tar -xvf openssl-3.2.1.tar.gz
    
  • Build openssl
    ./Configure --prefix=/root/sources/openssl-3.2.1
    make
    make install
    

Build python from source

Build python có sử dụng openssl, vì vậy cần build openssl trước

  • Clone source file
    wget https://www.python.org/ftp/python/3.12.3/Python-3.12.3.tgz
    
  • Configure
    ./configure --enable-optimizations --prefix=/usr/local/python3.12 --with-openssl=/root/sources/openssl-3.2.1
    
  • Build executable
    make
    make test
    sudo make install
    
  • Export variable
    export PATH=/usr/local/python3.12/bin:$PATH
    
  • Kiểm tra executable
    python3.12 --version
    

Build Mysql from Source

Instal dependencies

  • Trước khi build source, cần cài đặt Prerequisites Packages

    yum groupinstall "Development Tools"
    yum install cmake openssl-devel ncurses-devel rpcgen
    yum install gcc-toolset-12-gcc gcc-toolset-12-gcc-c++ gcc-toolset-12-binutils gcc-toolset-12-annobin-annocheck gcc-toolset-12-annobin-plugin-gcc
    dnf install zlib zstd
    dnf --enablerepo=crb install libtirpc-devel
    

  • Build thư viện boost. Mysql version 8.4.0 dưới đây đã có tích hợp boost trong source, nếu bạn dùng version này thì không cần build boost nữa.

    wget https://archives.boost.io/release/1.77.0/source/boost_1_77_0.tar.gz
    tar -xvf boost_1_77_0.tar.gz
    cd boost_1_77_0
    ./bootstrap.sh
    ./b2 headers
    

Build mysql

  • Tải và build mysql theo hướng dẫn sau.
    wget https://github.com/mysql/mysql-server/archive/refs/tags/mysql-8.4.0.tar.gz
    tar -xvf mysql-8.4.0.tar.gz
    cd mysql-server-mysql-8.4.0/
    mkdir bld && cd bld
    cmake ..
    make
    make install DESTDIR="/opt/mysql"
    

Hướng dẫn đóng góp vào dự án public trên github

Trong quá trình sử dụng các open source trên github, có thể bạn gặp vấn đề và sau đó tìm được cách sửa lỗi. Bạn muốn đóng góp nó vào repository để sửa lỗi này cho tất cả mọi người. Hoặc dự án của bạn bao gồm nhiều người và repository cần để public để có thể sử dụng một số tính năng của github như protect branch, đây là hướng dẫn dành cho bạn.

Đầu tiên, đối với các dự án open source lớn, hầu như đều có một hướng dẫn để contribute vào repository (thông thường nằm ở thư mục mẹ và là file CONTRIBUTING.md). Hãy đọc kỹ nó. Thông thường nó bao gồm các unitest, các bước để review một thay đổi, hoặc quy chuẩn chung như đặt tên biến, đặt tên branch... mà bạn phải tuân theo.

Sau khi đã đọc kỹ, bắt đầu code thôi.

1. Fork và clone project

  • Tại repository, chọn fork

    fork-project - Chọn repository để fork (nếu không có hướng dẫn gì, hãy chọn master hoặc main), sau đó chọn Create fork

    create-fork - Sau khi fork được repository, clone repository về

    clone-forked

2. Thực hiện thay đổi và push

  • Sau khi clone project về, tiến hành checkout sang branch mới. Tên branch cần thể hiện sơ qua mục đích của thay đổi, hoặc tác dụng của nó

    git checkout -b add-proxy-for-build
    
    switch-branch

  • Thay đổi các dòng trong code

  • Push các thay đổi lên branch vừa tạo

    push-code

3. Tạo pull request để thay đổi repository gốc

  • Tại repository gốc (không phải repo bạn vừa fork về), tiến hành tạo pull request

    pull-request new-pull-request

  • Chọn compare across fork, sau đó chọn fork repo và branch của mình. Cuối cùng chọn Create pull request

    compare-across-fork - Tại giao diện pull request, giải thích rõ bạn làm gì, tại sao contribute này lại cần thiết. Điều này rất quan trọng để maintainers hiểu bạn thay đổi cái gì và từ đó có cơ sở để approve.

    description_pull_request

  • Cuối cùng, chờ thôi. Các pull request sẽ phải có người review và approve. Trong quá trình đó, một số repository có bot để build tự động. Nếu build thất bại, request của bạn cần được chỉnh sửa hoặc sẽ bị reject. Một số maintainers có thể sẽ đặt câu hỏi thêm để hiểu rõ chinh xác thay đổi của bạn là gì. Nhớ check thông báo để trả lời nhé

    waiting-for-approve