在Docker环境下部署 Elasticsearch 数据库(从零到一搭建ELK日志)

背景

最近在玩 ELK 日志平台,它是 Elastic 公司推出的一整套日志收集、分析和展示的解决方案。只有学习了,操作了才能算真正的学会使用了,虽然看起来简单,但是里面的流程步骤还是很多的,将步骤和遇到的问题记录和总结下,今天主要分享下在Docker环境下部署 Elasticsearch 数据库。

什么是Elasticsearch?

ElasticStack简称为ES, 是一个分布式、高扩展、高实时的搜索与数据分析引擎,是整个ELK架构的核心。

它能很方便的使大量数据具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸缩性,能使数据在生产环境变得更有价值。

Elasticsearch 的实现原理主要分为以下几个步骤,首先用户将数据提交到Elasticsearch 数据库中,再通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据,当用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户。

主要优点

  • 处理方式灵活: elasticsearch是实时全文索引,具有强大的搜索功能;
  • 配置相对简单: elasticsearch全部使用JSON接口,logstash使用模块配置,kibana的配置文件部分更简单;
  • 检索性能高效: 基于优秀的设计,虽然每次查询都是实时,但是也可以达到百亿级数据的查询秒级响应;
  • 集群线性扩展: elasticsearch和logstash都可以灵活线性扩展。

常用场景

  • 全文搜索

Elasticsearch提供了全文搜索的功能,适用于电商商品搜索、App搜索、企业内部信息搜索、IT系统搜索等。

  • 日志分析

Elasticsearch能够借助Beats、Logstash等快速对接各种常见的数据源,并通过集成的Kibana高效地完成日志的可视化分析,让日志产生价值。

  • 运维监控

使用Elasticsearch结合Beats、Logstash或ElasticFlow将所有日志实时集中并构建索引,然后通过集成的Kibana灵活地运用数据构建可视化运维看板

  • 安全分析

通过日志解决公司内部繁杂的安全审计工作,可通过Elasticsearch分析、检索海量历史日志,高效地完成安全审计工作

部署ES数据库

1.获取es镜像

1
sudo docker pull elasticsearch:7.7.1

2. 创造挂载目录

1
2
3
sudo mkdir -p /data/elk/es/config
sudo mkdir -p /data/elk/es/data
sudo mkdir -p /data/elk/es/logs

3.赋予权限

1
sudo chown -R 1000:1000 /data/elk/es

4.进入config创建配置文件

1
2
cd /data/elk/es/config
sudo vim elasticsearch.yml

编辑 elasticsearch.yml 文件:

1
2
3
cluster.name: "my-es"
network.host: 0.0.0.0
http.port: 9200

5.启动服务

1
sudo docker run -it  -d -p 9200:9200 -p 9300:9300 --name es -e ES_JAVA_OPTS="-Xms84m -Xmx512m" -e "discovery.type=single-node" --restart=always -v /data/elk/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /data/elk/es/data:/usr/share/elasticsearch/data -v /data/elk/es/logs:/usr/share/elasticsearch/logs elasticsearch:7.7.1

这里我们需要特别注意的是,做好容器内的文件与第二步创建的挂载目录进行文件夹的映射。

6.验证服务

1
curl 127.0.0.1:9200

看到这个,就表示我们已经安装成功了!

Python的列表,字典,元组,集合的区别和各自使用方法

背景

我在学习Python的时候,经常把 几个数据类型搞混,下面就对 list,tuple,set,dict总结区别:

1.列表list []

列表是处理一组有序的数据结构,可以读写,添加和删除,或者搜索列表里的元素。因为可以添加和删除,所以称为可变的数据类型,即这种类型是可以被改变的,并且列表可以嵌套。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
res = [1,2,'yihang']
#增加元素:extend和append
res.append(1)
res.extend('6')
#删除元素:del,pop,切片,remove
del res[1]
res.pop(1)#删除该位置上的元素,没有指定则是最后一个元素
res = res[:2]+res[3:]#切片
res.remove(2)#删除指定值的元素
#更改元素
res[1] = 100 #
#查元素
print(res[0])
print(res[1])

注意:如果想添加的一个元素是一个列表,那么append是将这个这个列表作为一个元素添加进来,而extend是将列中的元素一个一个添加进去

More...

算法练习:BM2 链表内指定区间反转

问题描述

将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度O(n),空间复杂度O(1)。例如:给出的链表为 1→2→3→4→5→NULL, m=2,n=4,返回 1→4→3→2→5→NULL.

数据范围: 链表长度 0<size≤10000,0<mnsize,链表中每个节点的值满足 val∣≤10000

要求:时间复杂度 O(n) ,空间复杂度 O(n)

进阶:时间复杂度O(n),空间复杂度O(1)

示例1

1
2
3
4
5
6
7
输入:

{1,2,3,4,5},2,4

返回值:

{1,4,3,2,5}

示例2

1
2
3
4
5
6
7
输入:

{5},1,1

返回值:

{5}
More...

Window上用包管理应用安装软件 — Chocolatey

前言

在经历了多次重装系统、重新安装各种常用软件后,我突然萌生了一个想法,难道 Window 就没有一个像 Linux 一样可以使用一行命令安装软件的包管理器吗?

答案是:有的。

这里主要是介绍 Chocolatey,对其他包管理器感兴趣的可以自行查看。

安装使用

安装 Chocolatey 前,你需要对检查一下自身系统是否达到所需的要求。

  • Windows 7+ / Windows Server 2003+
  • PowerShell v2+
  • .NET Framework 4+

如果已经满足要求,就可以打开命令行 copy 下面的命令执行。

1
2
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "(iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))) >$null 2>&1" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin

如果没报红字错误,应该是安装成功了。

1
2
choco -v
# 0.10.11

接下来你可以打开下方的链接,查看一下可以安装的软件列表。

chocolatey.org/docs

比如,安装 Git

1
choco install git

安装 Node

1
2
choco install nodejs.install

也可以加上-y,安装时就不需要等待确认了

1
2

choco install firefox -y

基本用法

  1. 安装 choco install baretail
  2. 升级 choco upgrade baretail
  3. 卸载 choco uninstall baretail
  4. 搜索 choco search something
  5. 列出已安装 choco list -lo

关于更多用法可点击以下链接查看:
chocolatey.org/docs

修改默认安装目录

但是,Chocolatey 安装的软件默认存放在 C 盘,对于我这种不太喜欢把软件装到 C 盘的人来说是不能忍的。

虽然 Chocolatey 自己提供了一个修改默认安装目录的命令,但是需要注册(收费),对于资金充裕的同学我还是建议使用这种方法。

这里我提供另外一个思路,既然他存到默认安装目录,那我们把这个默认安装目录改一下就好了。

比如我要默认存放到E盘,打开注册表,把 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion 下的:

  1. ProgramFilesDir的值改为:E:\Program Files
  2. ProgramFilesDir (x86)的值改为:E:\Program Files (x86)

参考链接:https://juejin.cn/post/6844903782854164487

查看和清理Linux日志文件

1、查看目录大小

du,下面命令显示当前文件夹下各个文件及文件夹大小(汇总)

1
sudo du -sh -- *

2、清理指定大小的日志文件:

1
sudo journalctl --vacuum-size=100M

这将保留最新的 100MB 日志数据。

3、清理指定时间范围之前的日志:

1
sudo journalctl --vacuum-time=10d

docker安装MySQL主从复制

以下是步骤:

1.拉取MySQL的镜像

1
sudo docker pull mysql:8.0.25

2.新建MySQL主服务器的容器实例,端口为3307

1
2
3
4
5
6
7
sudo docker run -p 3501:3306 --name mysql-master \
-v /mnt/n1/data/mysql-master/log:/var/log/mysql \
-v /mnt/n1/data/mysql-master/data:/var/lib/mysql \
-v /mnt/n1/data/mysql-master/conf:/etc/mysql \
-v /mnt/n1/data/mysql-master/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:8.0.25

命令解读:
docker run :创建并运行一个容器
–name : 给容器起一个名字,比如叫做 mysql-master
-p :将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
-d:后台运行容器
-e:环境变量,如密码什么的
-v:挂载一个数据卷到某个容器内目录,上面分别配置了日志、数据、配置的数据卷

More...

Windows命令-域内信息收集

判断是否存在域

ipconfig

查看网关 IP 地址、DNS 的 IP 地址、域名、本机是否和 DNS 服务器处于同一网段。

1
2
3
4
5
6
7
8
9
10
11
12
ipconfig /all
C:\Users\daniel10> ipconfig /all

Windows IP 配置
主 DNS 后缀 . . . . . . . . . . : teamssix.com
DNS 后缀搜索列表 . . . . . . . . : teamssix.com

以太网适配器 Ethernet0:
IPv4 地址 . . . . . . . . . . .. : 192.168.7.110
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.7.1
DNS 服务器 . . . . . . . . . . . : 192.168.7.7

接着使用 nslookup 解析域名的 IP 地址,查看是否与 DNS 服务器为同一 IP

1
2
3
4
5
6
nslookup teamssix.com
C:\Users\daniel10> nslookup teamssix.com
服务器: UnKnown
Address: 192.168.7.7
名称: teamssix.com
Address: 192.168.7.7

系统详细信息

1
2
3
systeminfo
C:\Users\daniel10> systeminfo | findstr 域
域: teamssix.com

当前登录域与域用户

1
2
3
4
5
net config workstation
C:\Users\daniel10> net config workstation | findstr 域
工作站域 TEAMSSIX
工作站域 DNS 名称 teamssix.com
登录域 TEAMSSIX

判断主域

1
2
3
4
net time /domain
C:\Users\daniel10> net time /domain
\\dc.teamssix.com 的当前时间是 2021/2/13 20:49:56
命令成功完成。

一次Docker应用排查过程

背景

重新发布了一个应用,发现无法访问,把排查过程记录一下。

检查docker程序和开放端口

运行下面语句:

1
sudo docker ps

发现docker都在运行。

运行下面语句:

1
sudo netstat -tunpl

检查开放端口,端口开放正常。

检查frp的状态

运行下面语句:

1
sudo systemctl status frp

由于是通过frp穿透内网的,要看一下是否是frp问题,查看日志,没有报错。

检查内网网页状态

访问内网ip,报错:502 Bad Gateway

运行一下语句,查看docker日志:

1
sudo docker logs ee86b3ee2451

其中 ee86b3ee2451 为容器ID

运行下面语句,查看实时docker日志:

1
sudo docker logs -f ee86b3ee2451

进入Docker查看

如果还是有问题,运行下面语句,查看docker内部情况

1
sudo docker exec -it ee86b3ee2451 bash

总结

经过一番折腾,发现还是docker本身的问题,restart一下就好了,运行以下语句:

1
sudo systemctl restart docker

Django 的日志机制-4

进阶

其实,如果只是为了排错方便,记录一些日志,自定义类基本可以满足要求。但如果要记录访问系统的所有请求日志,那就无能为力了,因为不可能手动在每个接口代码加日志,也没必要。

这个时候,很自然就能想到 Django 中间件了。

Django 中间件

定义中间件类,包括 Filters 代码和 middleware 代码,在本地app文件夹中创建目录:middlewares,目录下创建文件 LogMiddleware.py :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from django.utils.deprecation import MiddlewareMixin
import threading
import logging
import json
import socket

local = threading.local()

class RequestLogFilter(logging.Filter):
"""
日志过滤器
"""

def filter(self, record):
record.sip = getattr(local, 'sip', 'none')
record.dip = getattr(local, 'dip', 'none')
record.body = getattr(local, 'body', 'none')
record.path = getattr(local, 'path', 'none')
record.method = getattr(local, 'method', 'none')
record.username = getattr(local, 'username', 'none')
record.status_code = getattr(local, 'status_code', 'none')
record.reason_phrase = getattr(local, 'reason_phrase', 'none')

return True

class RequestLogMiddleware(MiddlewareMixin):
"""
将request的信息记录在当前的请求线程上。
"""

def __init__(self, get_response=None):
self.get_response = get_response
self.apiLogger = logging.getLogger('web.log')

def __call__(self, request):

try:
body = json.loads(request.body)
except Exception:
body = dict()

if request.method == 'GET':
body.update(dict(request.GET))
else:
body.update(dict(request.POST))

local.body = body
local.path = request.path
local.method = request.method
local.username = request.user
local.sip = request.META.get('REMOTE_ADDR', '')
local.dip = socket.gethostbyname(socket.gethostname())

response = self.get_response(request)
local.status_code = response.status_code
local.reason_phrase = response.reason_phrase
self.apiLogger.info('system-auto')

return response
More...

请我喝杯咖啡吧~

支付宝
微信