JVM 的日志太多了,tail -f 累觉不爱,于是有搭建 ELK 堆栈的需求。

ELK 堆栈主要是 4 个组件:

  • Elasticsearch:用于存储日志
  • Kibana:用于搜索和可视化日志的Web界面
  • Logstash:用于处理传入的日志
  • Filebeat 代理:充当日志传送代理,利用伐木工具网络协议与 Logstash 进行通信

本次部署条件:ELK 部署在单机,操作系统为 CentOS 7。JVM 通过 Logstash 将日志写入 Elasticsearch,客户端通过 Kibana 实现可视化管理。ELK 组件均使用 7.3.0 版本。未使用 Filebeat 搜集 syslog,此项工作标记为 TODO。

开始。

1、准备工作

1.1、配置国内的 yum 源

增加一个 repo 文件:

vim /etc/yum.repos.d/elasticsearch.repo

添加清华镜像:

[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://mirrors.tuna.tsinghua.edu.cn/elasticstack/yum/elastic-7.x/
gpgcheck=0
enabled=1

强迫症患者来一波:

yum makecache

1.2、安装 Java 运行环境

这里我安装的是 OpenJDK(也可以是 Oracle Java),版本要求 1.8.0 及以上:

yum -y install java

确认 JDK 版本:

java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

若已安装 OpenJDK 且版本为 1.7,很有可能无法通过 yum 来升级。可先 yum remove java,再 yum -y install java。

2、安装与配置 ELK 组件

2.1、安装 ELK 组件

yum -y install elasticsearch kibana logstash

为 Elasticsearch 与 Logstash 创建数据存放与日志的目录:

mkdir -p /data/elasticsearch/{data,logs}
mkdir -p /data/logstash/{data,logs}
chown -R elasticsearch:elasticsearch /data/elasticsearch
chown -R logstash:logstash /data/logstash

2.2、配置 Elasticsearch

修改 Elasticsearch 配置文件:

vim /etc/elasticsearch/elasticsearch.yml

内容为:

cluster.name: test
node.name: node-1
path.data: /data/elasticsearch/data
path.logs: /data/elasticsearch/logs
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["127.0.0.1"]
cluster.initial_master_nodes: ["node-1"]

因为是单机部署,cluster.initial_master_nodes 中的节点名称要与 node.name 一致。其余都好理解。

启动 Elasticsearch:

service elasticsearch start

验证 Elasticsearch 是否成功启动:

ss -ntlup | grep -E "9200|9300"
tcp    LISTEN     0      32768    :::9200                 :::*                   users:(("java",pid=30466,fd=286))
tcp    LISTEN     0      32768    :::9300                 :::*                   users:(("java",pid=30466,fd=237))

2.3、配置 Kibana

修改 Kibana 配置文件:

vim /etc/kibana/kibana.yml

内容为:

server.port: 5601
server.host: "127.0.0.1"
elasticsearch.hosts: ["http://127.0.0.1:9200"]
kibana.index: ".kibana"
i18n.locale: "zh-CN"

这里值得注意的是,7.3.0 以前的版本中,elasticsearch.hosts 表现为 elasticsearch.url,需要注意甄别。

关于 Kibana 汉化:自 6.x 以来,官方自带汉化资源,7.x 的方法是通过修改配置文件 i18n.locale: "zh-CN" 即可。5.x 与 6.x 的汉化可参考这个项目

启动 Kibana:

systemctl start kibana

验证 Kibana 是否成功启动:

ss -ntlup | grep 5601
tcp    LISTEN     0      511       *:5601                  *:*                   users:(("node",pid=31095,fd=18))

2.4、配置 Logstash

修改 Logstash 配置文件:

vim /etc/logstash/logstash.yml

内容为:

path.data: /data/logstash/data
path.logs: /data/logstash/logs

创建一个索引的配置文件:

vim /etc/logstash/conf.d/my-project-1.conf

这里是针对 JVM 的配置:

input {
    tcp {
        port => 5044
        codec => json_lines
    }
}

output {
    elasticsearch {
        hosts  => ["127.0.0.1:9200"]
        index => "test-myproject-1-%{type}"
    }
    stdout {
        codec => rubydebug
    }
}

配置文件的创建根据项目需要以此类推。

启动 Logstash:

systemctl start logstash

若启动失败,可执行:

/usr/share/logstash/bin/system-install /etc/logstash/startup.options systemd

验证 Logstash 是否成功启动:

ss -ntlup | grep 5044
tcp    LISTEN     0      1024     :::5044                 :::*                   users:(("java",pid=8747,fd=134))

2.5、反向代理

我的环境中,“本机”没有公网 80 或 443 端口权限。因此通过 nginx 反代至 ELK 所在主机的 Kibana 端口,即本文的:5601。

3、收尾

到这里为止若无报错,ELK 环境就搭建完毕了。收个尾:

systemctl daemon-reload  # 重新加载所有配置文件
systemctl restart elasticsearch kibana logstash  # 启动 ELK
systemctl enable elasticsearch kibana logstash  # 将 ELK 加入开机启动
systemctl status elasticsearch kibana logstash  # 查看 ELK 启动状态

现在,我们的 Java 项目可以通过 5044 端口直接将日志输出到 Logstash。其它诸如 MySQL、系统日志等的配置,敬请期待。

对于不能 SSH 的场景的确够麻烦,rsync 又嫌麻烦,只能 FTP 了。

以下是自己马克用的。

#!/bin/bash
date=`date +%Y%m%d`
deldate=`date -d -{NUMBER}day +%Y%m%d`
ftp -inp<<!
open {HOST} {PORT}
user {FTP_USER} {FTP_PASSWD}
cd /
lcd /data/backup
mdelete *$deldate*
mput *$date*
close
bye
!

注意几点:

1、脚本中花括号内容替换为对应的变量;
2、cd 是远程的目录,lcd 是本地目录;
3、备份文件名需符合 date +%Y%m%d 这样的规则。

Oneinstack 有一个备份配置脚本:backup_setting.sh 及备份脚本:backup.sh。目前已经支持本地备份、远端主机备份及诸如阿里云、七牛云等各种云的备份。虽然同时支持多种方式进行备份,但同一种备份方式只能选一次,譬如不能同时向两个远端主机进行备份,且只能通过 ssh 方式。在比较看重异地灾备的情况下,多远端主机备份的需求不能满足;在不方便开启外网 ssh 的情况下,这个脚本也不能满足。

面对前述情况我做了一些调整:

1、Oneinstack 自带备份脚本只进行本地备份和各种云的备份。默认本地备份路径是 /data/backup,通过观察备份文件名的规律可得出:

ls -lah /data/backup/*20190101*

可匹配到当日备份成功的新文件。

2、远端备份机搭建 FTP 服务,一般 VPS 需要开启被动模式支持,防火墙配置好被动模式的端口段。

3、本地提前安装好 FTP 客户端:

yum -y install ftp

需要每向一台远端备份机上传,便增加一个脚本:

#!/bin/bash
ftp -n<<!
open REMOTE_HOST_IP REMOTE_PORT
user FTP_USER FTP_PASSWD
binary
hash
cd /
lcd /data/backup
prompt
mput *$(date "+%Y%m%d")*
close
bye
!

注意自行修改脚本中大写字母部分的配置,也可拎出来做变量配置。若有问题可在 ftp 后面加 -v 或 -d 参数,输出对端返回和打开 debug 模式,以进一步调试。

测试通过后就可以放 crontab 了,需要备份到几个地方就开几个脚本。再也不用担心神马地震、海啸、核武,美滋滋。

- EOF -

开篇第一句,感谢马爸爸。

以前在墙外 VPS 上,不需要修改 yum 源也飞快。后来用了猪厂的 yum 源,速度尚可。当有几十台服务器需要一起管理时,时间就显得特别珍贵了。因此,我找了这个物理位置最近的 yum 源。

留下命令自己马克:

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup \
&& wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

下面这个文件没有就不换了:

mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup \
&& wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo

最后:

yum clean all && yum makecache

要不要 update 你说了算:

yum -y update

嗯,真香。

近日,某导演发给我一个神秘的链接。不敢独享,遂发圈。因将敏感词替换成了“xxx”,结果被人误会是公然开车。打算助个力,建个镜像,以证清白。

昨日周末,用一台 GCP 的台湾 Windows 主机跑这个神秘项目的种子。经过一个下午的等待,这个神秘的高达 30G 的“file.tar”终于到手。

把存放数据的磁盘分配至另一台同机房的 CentOS 主机,fdisk -l 一下。嗯,NTFS,很酸爽。

这里用到一个叫做“NTFS-3G”的项目,下载最新的版本:

wget -c https://tuxera.com/opensource/ntfs-3g_ntfsprogs-2017.3.23.tgz

解压、编译,一气呵成。

tar xzf ntfs-3g_ntfsprogs-2017.3.23.tgz && cd ntfs-3g_ntfsprogs-2017.3.23 && ./configure && make && make install

尝试挂载:

mkdir -p /path_to_wikileaks && mount -t ntfs-3g /dev/vdb /path_to_wikileaks

报错,提示 /dev/vdb 是一整块磁盘。所以:

parted -l

得到正确挂载路径是 /dev/vdb2(是因为 NTFS 首分区保留的意思吗?),最终:

mount -t ntfs-3g /dev/vdb2 /path_to_wikileaks

搞定,/etc/fstab 略。