单台服务器

安装 JAVA

ELK 堆栈需要 Java 运行环境

1
2
sudo apt update
sudo apt install openjdk-11-jdk -y

安装ELK安装所需的基本工具

1
sudo apt install wget apt-transport-https curl gnupg2

添加 Elasticsearch 存储库

在官方 Ubuntu 存储库中找不到 ELK 堆栈组件,因此必须添加 Elastic 提供的外部存储库

从存储库下载并添加 GPG 密钥

1
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

使用以下命令将存储库添加到系统源列表中

1
2
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
sudo apt update

所有其他 ELK 组件必须来自同一分支

安装 Elasticsearch

1
sudo apt install elasticsearch

如果觉得下载很慢,可以手动下载 .deb 包并进行安装:

1
2
wget https://mirrors.aliyun.com/elasticstack/7.x/apt/pool/main/e/elasticsearch/elasticsearch-7.17.23-amd64.deb
sudo dpkg -i elasticsearch-7.17.23-amd64.deb

默认会为 Elasticsearch 服务创建一个新的 systemd 服务,但不会启动

1
2
3
sudo systemctl start elasticsearch
sudo systemctl enable elasticsearch
sudo systemctl status elasticsearch

Elasticsearch 默认监听 TCP 端口 9200 上的本地地址

咳咳,可能无法成功启动服务,大概率是内存不足(Elasticsearch 服务因内存不足而被 OOM(Out of Memory)杀手终止。这通常是因为 Elasticsearch 的默认内存需求较高,超出了系统可用内存) —— Elasticsearch 默认内存为1G

可以使用以下命令查看系统内存

1
free -h

安装 Kibana

1
sudo apt install kibana

systemd 服务

1
2
3
sudo systemctl start kibana
sudo systemctl enable kibana
sudo systemctl status kibana

配置 nginx 反向代理

1
2
touch /etc/nginx/conf.d/Kibana.conf
vim /etc/nginx/conf.d/cms.conf
1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name your_domain;
location / {
proxy_pass http://localhost:5601;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

安装 Logstash

1
sudo apt install logstash

在 Logstash 配置文件(例如 /etc/logstash/conf.d/logstash.conf

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
input {
tcp {
port => 5044
codec => json_lines
}
}

filter {
ruby {
code => "event.set('timestamp', event.get('@timestamp').time.localtime + 8*60*60)"
}
ruby {
code => "event.set('@timestamp',event.get('timestamp'))"
}
mutate {
remove_field => ["timestamp"]
}
}

output {
elasticsearch {
hosts => ["localhost:9200"]
index => "logstash-%{[server_name]}-%{+YYYY.MM.dd}"
}
}

systemd 服务

1
2
3
sudo systemctl start logstash
sudo systemctl enable logstash
sudo systemctl status logstash

发送日志到 Logstash

在你的程序中编写代码,监听日志,然后发送到Logstash

Docker

为了容器间的通信,需要先用 docker 创建一个网络

1
docker network create --subnet=172.10.0.0/16 elk

安装 ElasticSearch

1. 拉取镜像

1
2
3
4
5
6
# 搜索镜像
docker search elasticsearch
# 拉取 7.17.23 版本镜像
docker pull elasticsearch:7.17.23
# 查看所有镜像
docker images

有可能无法拉取镜像,下面是我遇到的问题和解决方法

配置 Docker 国内镜像源

如果不存在/etc/docker/daemon.json这个配置文件,可以直接使用下面的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建目录
sudo mkdir -p /etc/docker
# 写入镜像配置
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn"
]
}
EOF
# 重启docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
# 查看是否已经添加(可以看到"Registry Mirrors"地址列表)
docker info

2.拷贝配置文件

1
2
# 运行 elasticsearch
docker run -d --name es --net elk -P -e "discovery.type=single-node" elasticsearch:7.17.23
  • **docker run**:这是 Docker 用来创建和启动容器的基本命令
  • **-d**:这个选项表示以”分离模式”(detached mode)运行容器,即在后台运行容器。这让你可以在启动容器后继续使用终端
  • **--name es**:这个选项为容器指定一个名字。这样你可以用这个名字来引用容器,例如停止或删除容器
  • **--net elk**:这个选项将容器连接到名为 elk 的 Docker 网络
  • **-P**:这个选项将容器内的所有暴露的端口映射到主机上的随机端口
  • **-e "discovery.type=single-node"**:这个选项用来设置环境变量。设置了 Elasticsearch 的配置参数 discovery.typesingle-node,这使 Elasticsearch 在单节点模式下运行。这样 Elasticsearch 会跳过集群发现步骤
  • **elasticsearch:7.17.23**:这是要运行的 Docker 镜像的名称和标签。在这个例子中,指定了 elasticsearch 镜像的 7.17.23 标签。Docker 会从本地镜像缓存或从 Docker Hub 拉取这个镜像(如果本地没有的话)
1
2
3
# 进入容器查看配置文件路径
docker exec -it es /bin/bash
cd config
  • **docker exec**:这个命令用于在已经运行的 Docker 容器中执行命令。它允许你进入一个正在运行的容器并执行命令,查看文件系统或调试问题

  • **-it**:使得你可以像在本地终端一样与容器交互

    • **-i**:保持标准输入打开,这样你可以和容器内的进程交互
    • **-t**:分配一个伪终端,使得交互变得更像是在一个真实的终端中
  • **es**:这是你想要进入的容器的名字

  • **/bin/bash**:这是要在容器内执行的命令。在这个例子中,/bin/bash 会启动一个 Bash shell,这让你进入容器的命令行界面,从而可以在容器内运行命令、检查文件、调整配置等

1
2
3
4
5
6
7
8
9
10
11
# 退出容器
exit
# 创建目录
sudo mkdir -p /usr/local/elk/elasticsearch/
# 将容器内的配置文件拷贝到 /usr/local/elk/elasticsearch/ 中
docker cp es:/usr/share/elasticsearch/config/elasticsearch.yml /usr/local/elk/elasticsearch/
# 修改文件权限
chmod 666 elasticsearch.yml
# 在elasticsearch 目录下再创建data目录,同时修改权限
sudo mkdir -p /usr/local/elk/elasticsearch/data
chmod -R 777 /usr/local/elk/elasticsearch/data

3.重新运行容器并挂载

1
2
3
4
5
6
7
8
9
10
11
# 先删除旧的容器
docker rm -f es
# 运行新的容器
docker run -d --name es \
--net elk \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
--privileged=true \
-v $PWD/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v $PWD/elasticsearch/data/:/usr/share/elasticsearch/data \
elasticsearch:7.17.23
  • -p 9200:9200 -p 9300:9300

    • -p 9200:9200: 将容器的 9200 端口映射到主机的 9200 端口,这通常是 Elasticsearch 的 HTTP 访问端口
    • -p 9300:9300: 将容器的 9300 端口映射到主机的 9300 端口,这通常是 Elasticsearch 的集群通信端口
  • **--privileged=true**:以特权模式运行容器,容器将拥有较高的权限

  • -v $PWD/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml

    • -v: 挂载卷,将主机上的文件或目录映射到容器中
    • $PWD/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml: 将当前目录($PWD)下的 elasticsearch/elasticsearch.yml 文件挂载到容器内的 /usr/share/elasticsearch/config/elasticsearch.yml,用于覆盖容器内默认的 Elasticsearch 配置文件
  • **-v $PWD/elasticsearch/data/:/usr/share/elasticsearch/data**:将主机上的 elasticsearch/data/ 目录挂载到容器内的 /usr/share/elasticsearch/data,用于存储 Elasticsearch 的数据。持久化数据,即使容器被删除,数据仍然保存在主机上

  • **elasticsearch:7.17.23**:指定使用 elasticsearch:7.17.23 镜像来启动容器

4.查看容器

1
2
3
4
5
6
# 查看运行中的容器
docker ps
# 查看容器日志
docker logs es
ifconfig
curl -I http://ip地址:9200

安装 Kibana

1.拉取镜像

1
2
3
4
docker search kibana
docker pull kibana:7.17.23
# 启动 kibana 容器并连接同一网络
docker run -d --name kibana --net elk -P -e "ELASTICSEARCH_HOSTS=http://es:9200" -e "I18N_LOCALE=zh-CN" kibana:7.17.23
  • **-e "ELASTICSEARCH_HOSTS=http://es:9200"**: 表示连接刚才启动的 Elasticsearch 容器,因为在同一网络(elk)中,地址可直接填 容器名+端口,即 es:9200, 也可以填 http://ip:端口

2.拷贝配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建目录
sudo mkdir -p /usr/local/elk/kibana/
# 拷贝文件
docker cp kibana:/usr/share/kibana/config/kibana.yml /usr/local/elk/kibana/
chmod 666 /usr/local/elk/kibana/kibana.yml
vim /usr/local/elk/kibana/kibana.yml
-------------------------------------------------------------------------------------------------------------------
#
# ** THIS IS AN AUTO-GENERATED FILE **
#

# Default Kibana configuration for docker target
server.host: "0.0.0.0"
server.shutdownTimeout: "5s"
# 注意此ip为容器的ip地址,可以输入命令docker network inspect elk进行查看
elasticsearch.hosts: [ "http://ip:9200" ]
monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: zh-CN
-------------------------------------------------------------------------------------------------------------------

3.重新运行容器并挂载

1
2
3
4
5
6
7
8
9
#删除原来未挂载的容器
docker rm -f kibana
# 启动容器并挂载
docker run -d --name kibana \
-p 5601:5601 \
-v $PWD/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml \
--net elk \
--privileged=true \
kibana:7.17.23

安装 LogStash

1.拉取镜像

1
2
3
docker search logstash
docker pull logstash:7.17.23
docker run -d -P --name logstash --net elk logstash:7.17.23

2.拷贝配置文件

1
2
3
4
5
6
7
8
# 创建目录
sudo mkdir -p /usr/local/elk/logstash/
# 拷贝文件
docker cp logstash:/usr/share/logstash/config /usr/local/elk/logstash/
docker cp logstash:/usr/share/logstash/data /usr/local/elk/logstash/
docker cp logstash:/usr/share/logstash/pipeline /usr/local/elk/logstash/
# 文件夹赋权
chmod -R 777 /usr/local/elk/logstash/

3.重新运行容器并挂载

1
2
3
4
5
6
7
8
9
10
11
#删除原来未挂载的容器
docker rm -f logstash
# 启动容器并挂载
docker run -d --name logstash --net elk \
-p 5044:5044 \
-v $PWD/logstash/config:/usr/share/logstash/config \
-v $PWD/logstash/data:/usr/share/logstash/data \
-v $PWD/logstash/pipeline:/usr/share/logstash/pipeline \
logstash:7.17.23
vim /usr/local/elk/logstash/config/logstash.yml
修改es的ip地址即可

日志监控

第一种方法:安装 Filebeat(当你已经有log文件的时候)

1.拉取镜像

1
2
3
docker search filebeat
docker pull docker.elastic.co/beats/filebeat:8.10.0
docker run -d -P --name filebeat --net elk docker.elastic.co/beats/filebeat:8.10.0

2.拷贝配置文件

1
2
3
4
5
6
# 创建目录
sudo mkdir -p /usr/local/elk/filebeat/
# 拷贝文件
docker cp filebeat:/usr/share/filebeat/filebeat.yml /usr/local/elk/filebeat/
# 文件夹赋权
chmod -R 777 /usr/local/elk/filebeat/

3.重新运行容器并挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 删除原来未挂载的容器
docker rm -f filebeat
# 启动容器并挂载
docker run -d -P --name filebeat --net elk \
-v $PWD/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml \
docker.elastic.co/beats/filebeat:8.10.0
vim /usr/local/elk/filebeat/filebeat.yml
-------------------------------------------------------------------------------------------------------------------
filebeat.inputs:
- type: log
enabled: true
paths: 填写你的日志文件地址

processors:
# - add_cloud_metadata: ~
- add_docker_metadata: ~

output.logstash:
hosts: ['ip地址:5044']
# 可选: 如果 Logstash 启用了身份验证
# username: '${LOGSTASH_USERNAME:}'
# password: '${LOGSTASH_PASSWORD:}'
-------------------------------------------------------------------------------------------------------------------

4. 调整 Logstash 配置文件(logstash.conf)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
input {
beats {
port => 5044
}
}

filter {

}

output {
elasticsearch {
hosts => ["http://ip地址:9200"]
index => "logstash-%{[server_name]}-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}

第二种方法:编写程序,发送日志到 Logstash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
input {
tcp {
port => 5044
codec => json_lines
}
}

filter {

}

output {
elasticsearch {
hosts => ["http://ip地址:9200"]
index => "logstash-%{[server_name]}-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}