部署 ELK 日志系统

适用范围与安全说明:本文原始案例基于 CentOS 7 和早期 Elastic Stack,保留用于理解旧环境。CentOS 7 已于 2024 年 6 月 30 日停止维护,新建生产环境应选择仍受支持的 Linux 发行版,并使用 Elastic 官方镜像或软件仓库。生产部署不得关闭主机防火墙、不得禁用 SELinux、不得跳过 TLS 校验,也不得把固定密码写入文章、命令行或版本库。

生产环境先做这些

  1. 明确版本矩阵,锁定 Elasticsearch、Kibana、Logstash 和 Beats 的相同主版本,不使用浮动的 latest。
  2. 仅开放确有需要的端口:Kibana 5601 面向管理网,Elasticsearch 9200 面向受信客户端,集群传输端口 9300 仅允许节点间访问。
  3. 启用身份验证、最小权限角色和 HTTP/传输层 TLS。客户端只分发 CA 公共证书,绝不能分发 CA 私钥。
  4. 密码、API Key 和服务令牌放入 Elastic Keystore、Docker Secret 或受限权限的环境文件,并制定轮换和吊销流程。
  5. 下载镜像、脚本或配置后先核对来源、版本和摘要;不要把未经审查的远程脚本直接通过管道交给 shell。
  6. 上线前验证快照仓库、索引生命周期策略、磁盘水位、恢复演练、告警和容量预估。

1.ELK概述

ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 是一个日志搜集、分析的整体解决方案。

1.1.为什么要使用ELK

日志分析是运维工程师解决系统故障,发现问题的主要手段。日志主要包括系统日志、程序日志、安全日志。通过对日志分析,了解服务器软硬件信息、检查配置过程中的错误以及错误发生的原因。

往往单台机器的日志,使用grep、awk等工具就能基本实现简单分析,但是当日志被分散的储存在不同的设备上,或者管理上百台服务器,依次登录每台机器查阅日志就会很繁琐且效率低下。而使用开源的 syslog 虽然可以将所有服务器上的日志集中化管理,但对于要求更高的查询、排序和统计等要求和庞大的机器数量,仍然使用grep、awk和wc等Linux命令难免有点力不从心。

一般大型系统是一个分布式部署的架构,不同的服务模块部署在不同的服务器上,问题出现时,大部分情况需要根据问题暴露的关键信息,定位到具体的服务器和服务模块,构建一套集中式日志系统,可以提高定位问题的效率。

1.2.ELK架构图

1.3.ELK工作原理

在所有需要收集日志的服务器上部署Logstash,或者先将日志进行集中化管理在日志服务器上,再在日志服务器上部署Logstash。

  • Logstash 收集日志,将日志格式化并输出到 ElasticSearch 中
  • ElasticSearch 对格式化后的数据进行索引和存储
  • Kibana 从 ES 中查询数据生成图表,并进行前端数据的展示

注:Filebeat是一种轻量级的开源日志文件数据搜集器,它能快速收集数据,并发送给 logstash 进行解析,或是直接发给Elasticsearch存储,性能上相比运行于JvM上的logstash优势明显,是对它的替代。常应用于EFLK架构当中。

2.安装部署

2.1.前提条件

  • 硬件:至少使用2核CPU、16G内存、60G磁盘,推荐8核CPU、64G内存、500G磁盘
  • 软件:原案例使用 CentOS 7.9 x64,仅供旧环境复现;新部署应改用仍受支持的系统。示例 IP 为 192.168.4.222,请替换为实验网地址。

2.2.安装服务端

  • 1.安装Docker CE
curl -sL 'http://iso.sqlfans.cn/docker/install_docker_2401.sh' | bash
sudo docker --version
  • 2.安装docker-compose
curl -sL 'http://iso.sqlfans.cn/docker/install_docker_compose_2181.sh' | bash
sudo docker-compose --version
  • 3.调整防火墙规则(内网环境可关闭防火墙)
# 不要清空 iptables、关闭 firewalld 或禁用 SELinux。
# 请依据节点角色,只允许可信网段访问 5601/9200/9300 等必需端口。
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<TRUSTED_CIDR>" port port="5601" protocol="tcp" accept'
firewall-cmd --reload
  • 4.配置vm.max_map_count
sed -i 's/^vm.max_map_count.*/vm.max_map_count=655360/g' /etc/sysctl.conf
cat /etc/sysctl.conf | grep "^vm.max_map_count" > /dev/null || sudo bash -c "echo 'vm.max_map_count=655360' >> /etc/sysctl.conf"
sudo /sbin/sysctl -p /etc/sysctl.conf
  • 5.配置dns并安装基础软件
sed -i 's/^nameserver.*/nameserver 223.5.5.5/g' /etc/resolv.conf
cat /etc/resolv.conf | grep "^nameserver" > /dev/null || echo "nameserver 223.5.5.5" > /etc/resolv.conf
yum install -y -q curl wget ntp ntpdate lrzsz telnet zip unzip net-tools
  • 6.修改时区并同步时间
timedatectl set-timezone Asia/Shanghai
/usr/sbin/ntpdate -u ntp.aliyun.com
  • 7.编辑yml配置文件
sudo mkdir -p /data/docker/elk/{elasticsearch/{config/certs,data,plugins},kibana}
# 按容器实际 UID/GID 授权,避免 777;以下 UID 仅为示例,先核对镜像说明。
sudo chown -R 1000:0 /data/docker/elk/elasticsearch/data
sudo chmod 750 /data/docker/elk/elasticsearch/data
sudo curl -sL http://iso.sqlfans.cn/docker/yml/docker-elk-single-es.yml -o /data/docker/elk/docker-elk.yml
sudo curl -sL http://iso.sqlfans.cn/docker/yml/elk-env.yml -o /data/docker/elk/.env
sudo curl -sL http://iso.sqlfans.cn/docker/yml/elk-kibana.yml -o /data/docker/elk/kibana/kibana.yml
sudo cat /data/docker/elk/.env | egrep "(VERSION|PASSWORD|MEM_LIMIT)"
  • 8.下载yml文件中配置的镜像并启动
docker-compose -f /data/docker/elk/docker-elk.yml up -d
netstat -lnpt | grep "0.0.0.0" | egrep "(5601|9200|9300)"
docker ps
  • 9.浏览器访问(防火墙开放5601、9200)
# elk地址:http://192.168.4.222:5601
# es地址:https://192.168.4.222:9200
# 首次登录凭据应在部署时安全生成并立即保存到密码库,不在文档中固定。

2.3.配置客户端

  • 服务端:将es证书从容器内拷贝出来
sudo docker cp elk-es-1:/usr/share/elasticsearch/config/certs/ca/ca.crt /data/docker/elk/elasticsearch/config/certs/
ll /data/docker/elk/elasticsearch/config/certs/
  • 服务端:只把 CA 公共证书 ca.crt 分发给 Filebeat。CA 私钥必须留在受控签发环境中,不得放入文件服务器。
http://iso.sqlfans.cn/docker/yml/elk-ca.crt
  • 客户端:下载es证书到本地
sudo mkdir -p /etc/filebeat/certs
sudo curl -sL http://iso.sqlfans.cn/docker/yml/elk-ca.crt -o /etc/filebeat/certs/ca.crt
# 客户端只需要 CA 公共证书,不得复制或下载 CA 私钥。
  • 客户端:配置filebeat收集本地日志并输出给es
#.下载安装文件
sudo curl -L http://iso.sqlfans.cn/linux/filebeat-8.2.2-x86_64.rpm -o /opt/filebeat-8.2.2-x86_64.rpm
sudo yum localinstall -y /opt/filebeat-8.2.2-x86_64.rpm

#.修改filebeat配置
sudo mkdir -p /etc/filebeat/certs
sudo curl -sL http://iso.sqlfans.cn/docker/yml/elk-filebeat.yml -o /etc/filebeat/filebeat.yml
sudo cat /etc/filebeat/filebeat.yml | egrep "(host:|hosts:|password:|index:)"

#.启动filebeat服务
sudo filebeat test config /etc/filebeat/filebeat.yml
sudo filebeat modules enable system
sudo sed -i "s/enabled: false/enabled: true/" /etc/filebeat/modules.d/system.yml
sudo filebeat setup
sudo systemctl restart filebeat
sudo systemctl status filebeat
sudo filebeat version
  • 服务端:确认es索引
curl --cacert /etc/filebeat/certs/ca.crt -u elastic https://192.168.4.222:9200/_cat/indices?v

3.使用指导

3.1.初次登陆

3.2.创建数据视图

  • 1.进入主页,打开 Management

  • 2.创建数据视图,假设filebeat推送的es索引为 sam-gateway-YYYYMMDD,可将数据视图命名为 sam-gateway-*,则会自动匹配相关的es索引

  • 3.返回 Discover,从下拉框中选择某个数据视图,就可以查看相关的日志记录

  • 4.打开某个数据视图的日志,还可以根据多个字段对日志进行筛选,比如:只看 host.ip 是 10.30.4.192 的日志

3.3.权限设置

  • 1.创建 spcae 管理空间,用来分离不用的权限

  • 2.创建 role 角色

  • 3.创建 user 用户

  • 4.定时更新spcae,用户可以看到新的dashboard。同时更新roles index权限,用户可以看到新的index

4.使用规范

4.1.基本规范

所有接入elk的服务日志都应该遵循下述原则:

  • 非必要不采集,避免日志过大而占用过多的es存储空间
  • es日志只保留15天,超过15天则自动清理
  • 日志存放统一路径:/data/logs,再根据应用创建子目录
  • 日志切分和过期处理标准:单个日志文件不超过100M、存放时间7天
  • 日志格式统一采用 JSON,便于 ELK 解析处理,比如
2022-08-10 16:15:09,155 INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping {"orderId": 1, "userId":30, "payed":1, "exception":"failed to ....."}

4.2.服务索引命名规范

使用ES存储日志的时候,可以按照索引名切分后再存储,切分方式有:

  • 按业务切分,比如 xxx-gateway 代表 xxx系统网关服务
  • 按日期切分,日志量小就可以按月、年来做切分,量大就按天来做切分

通常会结合上面两种方式对索引名做切割,比如 xxx-gateway-20200122 代表xxx系统网关服务2020年1月22日的日志

4.3.日志采集来源

日志类型 日志来源 备注
访问日志 Apache、Nginx、Tomcat
业务日志 程序写入的日志文件 推荐开发同事采集异常日志用于分析
系统日志 /var/log/*、rsyslog
网络日志 防火墙、交换机、路由器 可以不采集

4.4.日志采集模板

根据“非必要不采集”的原则,请开发同事参考如下模板,填写需要采集的日志清单:

业务系统 ip地址 服务名称 服务日志路径 建议索引名称 备注
xxx系统 192.168.x.x gateway服务 /data/logs/gateway/application.log xxx-gateway 这是一个样例

4.5.filebeat客户端配置模板

  • 范例1:假设 elk 服务端为 192.168.4.222:5601,es账密为 elastic/xxx,以下则是 filebeat 客户端配置模板:
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - "/data/logs/gateway/application.log"
filebeat.config.modules:
  path: /etc/filebeat/modules.d/*.yml
  reload.enabled: false
setup.template.enabled: false
setup.template.overwrite: true
setup.ilm.enabled: false
setup.template.settings:
  index.number_of_shards: 1
setup.kibana:
  host: "192.168.4.222:5601"
output.elasticsearch:
  hosts: ["192.168.4.222:9200"]
  protocol: "https"
  username: "elastic"
password: "${ELASTIC_PASSWORD}"
  ssl.certificate_authorities: "/etc/filebeat/certs/ca.crt"
  indices:
    - index: "xxx-gateway-%{+yyyyMMdd}"
processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_cloud_metadata: ~
  • 范例2:单机多日志监控并写入不同es索引
#================ input =====================
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - "/var/log/*.log"
  tags: ["syslog"]
  fields:
    index: "syslog"
  multiline.pattern: '^\s'
  multiline.negate: true
  multiline.match: after
- type: log
  enabled: true
  paths:
    - /usr/local/nginx/logs/error.log
  tags: ["nginx"]
  fields:
    index: "nginx"
  multiline.pattern: '^\s'
  multiline.negate: true
  multiline.match: after
#================ output =====================
output.elasticsearch:
# hosts: ["192.168.0.21:9200","192.168.0.22:9200"]
  hosts: ["192.168.4.222:9200"]
  protocol: "https"
  username: "elastic"
  password: "xxx"
  ssl.certificate_authorities: "/etc/filebeat/certs/ca.crt"
  indices:
    - index: "syslog-log-%{+yyyyMMdd}"
      when.contains:
        fields:
          index: "syslog"
    - index: "nginx-log-%{+yyyyMMdd}"
      when.contains:
        fields:
          index: "nginx"
#============== Elasticsearch template setting ==========
filebeat.config.modules:
  path: /etc/filebeat/modules.d/*.yml
  reload.enabled: false
setup.template.enabled: false
setup.template.overwrite: true
setup.ilm.enabled: false
setup.template.settings:
  index.number_of_shards: 1
setup.kibana:
  host: "192.168.4.222:5601"
#================== processors config ===================
processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_cloud_metadata: ~

5.服务器维护

5.1.ES索引定期清理

当elk运行一段时间之后,ES中会保存大量的日志,需要定时清理。下面将创建一个定时清理14天以前es索引的任务。

  • 将如下脚本保存为:/scripts/crontab/es_clear_daily.sh
#!/bin/bash

iport=192.168.4.222:9200
user=es_index_maintainer
ca_file=/etc/elasticsearch/certs/ca.crt
: "${ES_PASSWORD:?请通过受控环境变量或密钥服务提供 ES_PASSWORD}"
dte=`date -d "14 days ago" +%Y%m%d`

for idx in `curl --fail --silent --show-error --cacert "$ca_file" -u "$user:$ES_PASSWORD" "https://$iport/_cat/indices?v" | awk '{print $3}' | grep "$dte"`;
do 
  curl --fail --show-error --cacert "$ca_file" -u "$user:$ES_PASSWORD" -X DELETE "https://$iport/$idx";
done
  • 添加计划任务
echo "9 2 * * * /scripts/crontab/es_clear_daily.sh > /dev/null 2>&1" >> /var/spool/cron/`whoami`
Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-18 13:28:40

results matching ""

    No results matching ""