IILeeのBlog

IILeeのBlog

Docker 搭建 ELK 集群

454
2021-04-25
Docker 搭建 ELK 集群

##前言
本篇文章主要介绍在两台机器上使用 Docker 搭建 ELK。

正文

环境

  • 三台CentOS 7.7 系统
  • Docker version 20.10.6
  • docker-compose version 1.29.1

系统设置

vim 编辑 /etc/security/limits.conf,在末尾加上:

* soft nofile 65536
* hard nofile 65536
* soft nproc 4096
* hard nproc 4096

vim 编辑 /etc/sysctl.conf,在末尾加上:

vm.max_map_count = 655360

执行 sysctl -p 命令是配置生效。

Elasticsearch 搭建

注意:如果用非 Docker 搭建,是不能用 root 用户去启动的。

由于我是用虚拟机搭建的,我的机器只能开两台,所以只有一个主节点和一个数据节点;在生产环境中最少要3台,防止脑裂问题。

注意:如果开启了防火墙,需要执行以下命令开放 9200 和 9300 端口号。

firewall-cmd --zone=public --add-port=9200/tcp --permanent
firewall-cmd --zone=public --add-port=9300/tcp --permanent
service firewalld reload

主节点

首先设置主节点的配置文件 elasticsearch.yml,如下:

cluster.name: es-cluster
node.name: es-master
node.master: true
node.data: false
network.host: 0.0.0.0
network.publish_host: 192.168.0.231
http.port: 9200
transport.tcp.port: 9300
discovery.seed_hosts:
  - 192.168.0.231
  - 192.168.0.232
  - 192.168.0.233
cluster.initial_master_nodes:
  - es-master
http.cors.enabled: true
http.cors.allow-origin: "*"

然后编写主节点的 docker-compose.yml,如下:

version: "3"
services:
  es-master:
    container_name: es-master
    hostname: es-master
    image: elasticsearch:7.10.1
    privileged: true
    ports:
      - 9200:9200
      - 9300:9300
    volumes:
      - ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./data:/usr/share/elasticsearch/data
      - ./logs:/usr/share/elasticsearch/logs
    environment:
      - "ES_JAVA_OPTS=-Xms2g -Xmx2g"
    ulimits:
      memlock:
        soft: -1
        hard: -1

如果出现下图所示的错误,可以使用 chmod 777 logschmod 777 data 来修改文件夹的权限,即可正常启动。

image.png

接着执行以下命令启动容器

docker-compose up -d

数据节点

首先设置数据节点的配置文件 elasticsearch.yml,如下:

cluster.name: es-cluster
node.name: es-data
node.master: true
node.data: true
network.host: 0.0.0.0
network.publish_host: 192.168.0.232
http.port: 9200
transport.tcp.port: 9300
discovery.seed_hosts:
  - 192.168.0.231
  - 192.168.0.232
  - 192.168.0.233
cluster.initial_master_nodes:
  - es-master
http.cors.enabled: true
http.cors.allow-origin: "*"

注意,这里只列出一个节点的配置,另一个节点配置只需修改为network.publish_host: 192.168.0.233即可。

然后编写数据节点的 docker-compose.yml,如下:

version: "3"
services:
  es-master:
    container_name: es-data
    hostname: es-data
    image: elasticsearch:7.10.1
    privileged: true
    ports:
      - 9200:9200
      - 9300:9300
    volumes:
      - ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./data:/usr/share/elasticsearch/data
      - ./logs:/usr/share/elasticsearch/logs
    environment:
      - "ES_JAVA_OPTS=-Xms2g -Xmx2g"
    ulimits:
      memlock:
        soft: -1
        hard: -1

接着像上面主节点一样启动就行了,然后访问主节点的
http://192.168.0.233:9200/_cat/nodes API 地址,如下图所示就代表 Elasticsearch 集群搭建成功了。

image.png

Kibana 搭建

因为主节点负责集群范围内的轻量级操作,例如创建或删除索引,跟踪哪些节点是集群的一部分以及确定将哪些碎片分配给哪些节点;所以将 Kibana 跟主节点放在一台机器上。

注意:如果开启了防火墙,需要执行以下命令开放 5601 端口号。

firewall-cmd --zone=public --add-port=5601/tcp --permanent

首先是 Kibana 的配置文件 Kibana.yml,如下:

server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://192.168.0.231:9200","http://192.168.0.232:9200","http://192.168.0.233:9200"]
i18n.locale: "zh-CN"

然后是 docker-compose.yml 文件的编写,如下:

version: "3"
services:
  kibana:
    container_name: kibana
    hostname: kibana
    image: leisurexi/kibana:7.1.0
    ports:
      - 5601:5601
    volumes:
      - ./kibana.yml:/usr/share/kibana/config/kibana.yml

接着像 Elasticsearch 几点一样启动就可以了。

我们访问 Kibana 节点的 5601 端口就可以看到界面了,接下来执行 GET _cluster/health 查看 ES 集群的健康状况,来验证 Kibana 是否可以正常工作。

image.png

如上图一样就代表你已经 kibana 已经搭建成功了。

logstash 搭建

logstash 在 任一一台 ES 的数据节点上搭建。

注意:如果开启了防火墙,需要执行以下命令开放 4560 和 5044 端口号。

firewall-cmd --zone=public --add-port=4560/tcp --permanent
firewall-cmd --zone=public --add-port=5044/tcp --permanent

首先是 logstash 的全局配置文件 logstash.yml,如下:

xpack.monitoring.enabled: true
xpack.monitoring.elasticsearch.hosts: ["http://192.168.0.231:9200","http://192.168.0.232:9200","http://192.168.0.233:9200"]
xpack.management.enabled: false

然后是自定义的 logstash 的配置文件 logstash.conf,如下:

input {
  tcp {
    mode => "server"
    host => "0.0.0.0"
    port => 4560
    codec => json_lines
  }
}
output {
  elasticsearch {
    hosts => ["http://192.168.0.231:9200","http://192.168.0.232:9200","http://192.168.0.233:9200"]
    index => "log-%{+YYYY.MM.dd}"
  }
}

上面文件的大概意思就是监听 4560 端口,然后写入 ES,索引名称就是 log 前缀加上日期;每天都会创建一个新的索引。

然后是 docker-compose.yml,如下:

version: "3"
services:
  logstash:
    container_name: logstash
    hostname: logstash
    image: logstash:7.10.1
    command: logstash -f ./config/logstash.conf
    volumes:
      - ./logstash.conf:/usr/share/logstash/config/logstash.conf
      - ./logstash.yml:/usr/share/logstash/config/logstash.yml
    ports:
      - 4560:4560
      - 5044:5044

最后像上面启动 ES 一样,启动 logstash 即可。

定期删除索引

如果长时间运行,会有磁盘满的而无法写入 ES 的情况,所以得定时删除不怎么重要的索引数据;如下,可以通过定时脚本来实现。

我们先写个删除15天前索引的脚本 vim /mnt/elk/es-index-clear.sh,如下:

# /bin/bash
# es-index-clear
# 只保留15天内的日志索引
LAST_DATA=`date -d "-15 days" "+%Y.%m.%d"`
# 删除索引 ,主节点
curl -XDELETE 'http://192.168.0.231:9200/*-'${LAST_DATA}'*'

然后利用 crontab 去添加定时任务,首先执行 crontab -e,然后添加以下内容:

0 1 * * * /mnt/elk/es-index-clear.sh

该定时会在每天的凌晨1点执行,后面换成你自己脚本所在的绝对路径即可。

可以执行 tail -f /var/log/cron,查看定时任务的日志。

测试

我们新建一个 spring-boot 应用,添加 logstash 的依赖,如下:

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>5.3</version>
</dependency>

然后新建一个 logback.xml 放在 resources 目录下,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    <!--应用名称-->
    <property name="APP_NAME" value="log"/>

    <!--输出到logstash的appender-->
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <!--可以访问的logstash日志收集端口-->
        <destination>192.168.0.232:4560</destination>
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="LOGSTASH"/>
    </root>

</configuration>

接着编写一个定时任务,Java 代码如下:

@EnableScheduling
@Configuration
public class LogScheduler {

    private static Logger log = LoggerFactory.getLogger(LogScheduler.class);

    @Scheduled(cron = " 0/30 * * * * ? ")
    public void doTiming() {
        log.info("ELK测试日志");
    }

}

该定时任务每30秒输出一条日志。

最后我们查看 kibana 的界面就可以看到啦!

image.png

总结

本次只是简单的搭建了 ELK,如果要在生成环境上使用,还需要做很多修改;例如,ES 开启安全认证,端口不可直接暴露在公网上,索引最好使用模板创建等。

最后本篇文章的代码和 ELK 的配置文件,我都上传到 我的GIT仓库

注意:Git 上的 docker-compose.yml 我是和在一起写的,文章中是分开写的,为了更清晰一点。

参考地址 : Docker 搭建 ELK 集群步骤