Ubuntu 环境下通过 Docker 快速搭建 ELK 日志系统环境

视频教程请移步 Ubuntu 环境下通过 Docker 快速搭建 ELK 日志系统环境_哔哩哔哩_bilibili

  1. 安装 Docker

# 允许apt通过HTTPS使用存储库来安装软件
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# 添加Docker官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 使用下面的命令去设置稳定版的存储库
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# 使用下面的命令去设置稳定版的存储库
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# 验证Docker
docker -v
  1. 安装 docker-compose

# 运行下面的命令来下载 Docker Compose 当前稳定版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 添加权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
  1. Docker 拉镜像加速

Docker 下载镜像慢,可以增加 /etc/docker/daemon.json 文件如下,然后 systemctl restart docker 生效后,继续 docker-compose up -d 的操作

{
    "registry-mirrors": [
        "http://f1361db2.m.daocloud.io",
        "https://registry.docker-cn.com",
        "http://hub-mirror.c.163.com",
        "https://kfwkfulq.mirror.aliyuncs.com"
    ]
}

  1. ELK 搭建

mkdir -p ~/projects/elk/{elasticsearch/data,logstash}
# yaml 文件,放在 projects/elk 文件夹下
version: '3'
services:
  elasticsearch:
    image: elasticsearch:7.7.0  #镜像
    container_name: elk_elasticsearch  #定义容器名称
    # restart: always  #开机启动,失败也会一直重启
    environment:
      - "cluster.name=elasticsearch" #设置集群名称为elasticsearch
      - "discovery.type=single-node" #以单一节点模式启动
      - "ES_JAVA_OPTS=-Xms512m -Xmx1024m" #设置使用jvm内存大小
    volumes:
      - /home/xiaobaiyang/projects/elk/elasticsearch/plugins:/usr/share/elasticsearch/plugins #插件文件挂载
      - /home/xiaobaiyang/projects/elk/elasticsearch/data:/usr/share/elasticsearch/data #数据文件挂载
    ports:
      - 9200:9200
  kibana:
    image: kibana:7.7.0
    container_name: elk_kibana
    # restart: always
    depends_on:
      - elasticsearch #kibana在elasticsearch启动之后再启动
    environment:
      - ELASTICSEARCH_URL=http://elasticsearch:9200 #设置访问elasticsearch的地址
    ports:
      - 5601:5601
  logstash:
    image: logstash:7.7.0
    container_name: elk_logstash
    # restart: always
    volumes:
      - /home/xiaobaiyang/projects/elk/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #挂载logstash的配置文件
    depends_on:
      - elasticsearch #kibana在elasticsearch启动之后再启动
    links:
      - elasticsearch:es #可以用es这个域名访问elasticsearch服务
    ports:
      - 4560:4560
# logstash.conf 文件,放在 projects/elk/logstash 文件夹下
input {
  tcp {
    mode => "server"
    host => "0.0.0.0"
    port => 4560
    codec => json_lines
  }
}
output {
  elasticsearch {
    hosts => "es:9200"
    index => "logstash-%{+YYYY.MM.dd}"
  }
}
  1. Django 接入 ELK

  2. 安装依赖库

使用 python-logstash 这个第三方依赖库。

pip install python-logstash
  1. 修改 Django 项目的设置

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        # 日志格式
        'standard': {
            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
                      '[%(levelname)s]- %(message)s'},
        'simple': {  # 简单格式
            'format': '%(levelname)s %(message)s'
        },
    },
    # 过滤
    'filters': {
    },
    # 定义具体处理日志的方式
    'handlers': {
        # 默认记录所有日志
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(log_path, 'all-{}.log'.format(time.strftime('%Y-%m-%d'))),
            'maxBytes': 1024 * 1024 * 5,  # 文件大小
            'backupCount': 5,  # 备份数
            'formatter': 'standard',  # 输出格式
            'encoding': 'utf-8',  # 设置默认编码,否则打印出来汉字乱码
        },
        'logstash': {
            'level': 'INFO',
            'class': 'logstash.TCPLogstashHandler',
            'host': 'localhost',
            'port': 4560,  # Default value: 5959
            'version': 1,  # Version of logstash event schema. Default value: 0 (for backward compatibility of the library)
            'message_type': 'django',  # '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.
        },
        # 输出错误日志
        'error': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(log_path, 'error-{}.log'.format(time.strftime('%Y-%m-%d'))),
            'maxBytes': 1024 * 1024 * 5,  # 文件大小
            'backupCount': 5,  # 备份数
            'formatter': 'standard',  # 输出格式
            'encoding': 'utf-8',  # 设置默认编码
        },
        # 控制台输出
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'standard'
        },
        # 输出info日志
        'info': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(log_path, 'info-{}.log'.format(time.strftime('%Y-%m-%d'))),
            'maxBytes': 1024 * 1024 * 5,
            'backupCount': 5,
            'formatter': 'standard',
            'encoding': 'utf-8',  # 设置默认编码
        },
    },
    # 配置用哪几种 handlers 来处理日志
    'loggers': {
        # root logger 默认调用
        '': {
            'handlers': ['logstash'],
            'level': 'INFO',
            'propagate': True
        },
        # 类型 为 django 处理所有类型的日志, 默认调用
        'django': {
            'handlers': ['default', 'console'],
            'level': 'INFO',
            'propagate': True
        },
        # log 调用时需要当作参数传入
        'log': {
            'handlers': ['error', 'info', 'console', 'default'],
            'level': 'INFO',
            'propagate': True
        },
    }
}
  1. ELK 的基本使用

  2. 创建索引

进入 ELK 后,点击左下角设置按钮,再点击 Index Patterns,最后点击右上角的 Create index pattern 按钮,即可创建索引了。

image
  1. 搜索日志

创建好索引后,接着点击左上角 discover 按钮,再选择我们创建的索引 logstash,然后添加一些过滤条件,即可搜索对应日志。

http://192.168.10.102:5601/goto/c1a3cde2acf09533f717b9c34c8c4aef

image
  1. Django 日志中添加 trace id

Django 日志中,添加 trace id,实现链路追踪,能方便我们快速排查问题,大大提升发现问题,解决问题的效率。参考 https://zzun.app/repo/JonasKs-django-guid-python-django-utilities 的操作,以下为添加trace id 所需的操作步骤。

  1. 安装依赖

pip install django-guid
  1. 设置 setting.py

DJANGO_GUID = {
    'GUID_HEADER_NAME': 'Correlation-ID',
    'VALIDATE_GUID': True,
    'RETURN_HEADER': True,
    'EXPOSE_HEADER': True,
    'INTEGRATIONS': [],
    'IGNORE_URLS': [],
    'UUID_LENGTH': 32,
}

# installed_app 里需要添加 django_guid 应用
INSTALLED_APPS = [
    ...
    'django_guid',
]

# 中间件里需要添加 guid 的中间件,最好放在最开头,这样尽可能多的日志里会加上 trace id
MIDDLEWARE = [
    'django_guid.middleware.guid_middleware',
    ...
 ]

 #
 LOGGING = {
    ...
    'formatters': {
        # 日志格式
        'standard': {
            'format': '[%(correlation_id)s][%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
                      '[%(levelname)s]- %(message)s'},
        'simple': {  # 简单格式
            'format': '%(levelname)s %(message)s'
        },
    },
    # 过滤
    'filters': {
        'correlation_id': {
            '()': 'django_guid.log_filters.CorrelationId'
        }
    },
    'handlers': {
        # 默认记录所有日志
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(log_path, 'all-{}.log'.format(time.strftime('%Y-%m-%d'))),
            'maxBytes': 1024 * 1024 * 5,  # 文件大小
            'backupCount': 5,  # 备份数
            'formatter': 'standard',  # 输出格式
            'encoding': 'utf-8',  # 设置默认编码,否则打印出来汉字乱码
            'filters': ['correlation_id'],
        },
        'logstash': {
            'level': 'INFO',
            'class': 'logstash.TCPLogstashHandler',
            'host': 'localhost',
            'port': 4560,  # Default value: 5959
            'version': 1,  # Version of logstash event schema. Default value: 0 (for backward compatibility of the library)
            'message_type': 'django',  # '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.
        },
    }
}
  1. 打印日志

import logging

logger = logging.getLogger('log')

class UserViewSet(viewsets.ModelViewSet):
    """
    允许用户查看或编辑的API路径。
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

    def list(self, request, *args, **kwargs):
        logger.info('welcome to django list')
        user.test_log()
        return super().list(request, *args, **kwargs)
import logging

logger = logging.getLogger('django')

def test_log():
    logger.warning('test log trace id print')
    try:
        x = 1 / 0
        logger.info(f'{x=}')
    except Exception as e:
        logger.exception(f'except:{str(e)}')
  1. 请求接口并查看日志

请求 Django 的接口,并找到 response header 中的 Correlation-ID。

image

打开 Kibana,搜索 Correlation-ID。如果找不到,则可能需要在 Kibana 上更新我们的日志索引。

image

在 Kibana 上更新我们的日志索引步骤:左下角设置按钮->Index Pattern->refresh filed list.

image
  1. Django 接入 ELK APM

两步走,先搭建 APM server,再根据情况,接入 APM agent。

http://192.168.10.102:5601/app/kibana#/home/tutorial/apm

  1. 搭建 APM server

# Download and unpack APM Server
curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-7.7.0-amd64.deb
sudo dpkg -i apm-server-7.7.0-amd64.deb
# Edit the configuration,default config file is /etc/apm-server/apm-server.yml 
output.elasticsearch:
    hosts: ["localhost:9200"]
    # 账号密码不需要也可以
    # username: <username> 
    # password: <password>
# 开启防火墙
sudo ufw allow 8200
# 后台运行 apm server,运行时可能会出现错误 Exiting: error loading config file: config file ("/etc/apm-server/apm-server.yml") can only be writable by the owner but the permissions are "-rwxrwxrwx" (to fix the permissions use: 'chmod go-w /etc/apm-server/apm-server.yml')
sudo apm-server &
# 检查 APM server 状态
image
  1. Django 接入 APM agent

# Install the APM agent
pip install elastic-apm
# Configure the agent
# Add the agent to the installed apps
INSTALLED_APPS = (
  'elasticapm.contrib.django',
  # ...
)

ELASTIC_APM = {
  # Set required service name. Allowed characters:
  # a-z, A-Z, 0-9, -, _, and space
  'SERVICE_NAME': '',

  # Use if APM Server requires a token
  'SECRET_TOKEN': '',

  # Set custom APM Server URL (default: http://localhost:8200)
  'SERVER_URL': '',
}

# To send performance metrics, add our tracing middleware:
MIDDLEWARE = (
  'elasticapm.contrib.django.middleware.TracingMiddleware',
  #...
)
# 
  1. 参考资料

ELK 日志系统介绍

安装 Docker 和 Docker Compose (Ubuntu)

docker-compose安装ELK

访问Vmware中的服务不爱debug的BugMaker的博客-CSDN博客访问vmware服务

Python 修改 pip 源为国内源 - 137point5 - 博客园

www.codementor.io

将 Django 应用的日志输出到 ELK 中

Elasticsearch:如何在 Django 中使用 Elasticsearch_Elastic 中国社区官方博客的博客-CSDN博客_django使用elasticsearch

Inject an ID into every log message from a Django request. ASGI compatible, integrates with Sentry,

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容