使用腾讯云容器服务搭建 ELK 日志系统

概述

应用日志的收集,在docker未出现前,常用做法是将日志写到主机的某个文件,当需要查看日志时先登录到主机然后去查看相关的日志文件,主机上的日志只要不特意删除会一直存在;随着docker和容器编排技术的出现,容器的销毁和重新创建被看成是一种常态,如果用原来的方式将应用日志写到容器的文件系统里,那么当容器销毁时日志就会丢失,这种情况下,一种有效的解决方法是引入集中式的日志管理系统,将容器的日志通过agent发送给日志系统进行统一存储。

目前主流的分布式日志系统有ELK,flume,fluentd,splunk等,本文利用腾讯云容器服务搭建ELK系统收集nginx的访问日志 ,搭建过程中共搭建如下4个服务,每个服务的功能如下:

  1. ElasticSearch服务:该服务提供日志集中存储和查询
  2. Kibana服务:以web的形式提供日志的可视化展现和查询界面
  3. Kibana登录鉴权服务:Kibana如果直接放到公网上,因为kibana本身没有鉴权机制,如果被端口扫描工具扫出来,很容易出现他人查看操作日志的行为,为避免该情况,在kibana前面加个nginx服务,利用nginx的basic认证来做鉴权。
  4. nginx应用服务:创建该服务的目的是为了验证是否可以将应用日志采集到ElasticSearch里。该服务用nginx的访问日志做日志源,浏览器每访问一次nginx服务,就会生成一条access日志,和该服务在一起的logstash容器会将新产生的日志发到ElasticSearch里。

在开始搭建日志系统之前,了解容器日志的输出方式和ELK的相关配置是非常必要的,因此下文先简单介绍这两个方面的内容,然后再进行具体的搭建步骤说明,最后对搭建过程中碰到的问题进行总结。

下面的搭建方法采用的方式是一个应用容器绑定一个采集日志容器的做法,如果一台主机上有很多服务的日志需要采集,建议先提前规划好日志目录,用一台主机放一个日志采集容器的方法。

容器日志输出方式

容器日志常见输出形式主要有以下两种:

  • 标准输出,当docker 的log driver使用默认设置时,用docker logs 命令看到的日志输出采用的就是这种方式。如果要收集标准输出的日志,常用方式是设置docker 的log driver,目前docker 支持的log driver 如下表所示,但是kubernetes目前的pod 定义中还不包括log driver的字段,一种解决方式是修改docker daemon的log driver默认配置。

日志驱动名称

描述

none

不输出任何内容

json-file

日志以json的格式保存成文件,这是默认的docker日志输出驱动

syslog

将log日志输出到syslog

journald

将日志输出到journald

gelf

将日志输出到支持GaryLog Extended log Fromat(GELF)格式的日志采集系统如Graylog和Logstash

fluentd

将日志输出到fluentd

awslogs

将日志输出到AWS cloudwatch logs

splunk

将日志输出到Splunk

etwlogs

将日志输出到Windows的事件系统,这个驱动只有对windows下的docker生效

gcplogs

将日志输出到GCP的日志系统中

  • 日志文件输出,像nginx、apache,tomcat等应用都是将日志写到文件。这种形式的日志输出常用的收集方式有两种:
    1. 每个应用容器单独再配一个日志采集容器如logstash或filebeat等,在k8s中应用容器和日志采集容器可以做成一个pod,然后他们之间共享一个volume。这种方式的缺点是应用容器越多,日志采集容器也会变多,会增加系统的资源消耗。
    2. 在主机上放一个日志采集容器,将某个主机目录映射到容器内,同时将该主机目录映射到每个应用容器的日志输出目录,这种方式的优点是每台主机上只有一个日志采集容器,缺点是要对每个应用的日志输出目录做本地磁盘映射,同时要提前规划好各个应用的日志文件名称和目录,避免出现不同应用生成相同的日志文件或日志目录。

ELK简介和配置简介

ELK是由ElasticSearch、logstash和kibana三个项目共同组成的日志系统,其中:

  • ElasticSearch(简称ES)是日志搜索引擎,java语言开发,提供日志存储、聚合、搜索和查询等功能,支持插件
  • logstash是日志采集模块,java语言开发,支持的日志输入源包括syslog、http、tcp、file等,日志输出端支持kafka、elasticsearch、file和mogodb等,有丰富的插件。
  • kibana是日志分析和展现模块,可以通过配置和ElasticSearch对接,支持自定义界面展示。

在ELK系统中采集端如果用logstash,logstash因为是java写的,对系统资源占用相对较多,因此ELK生态中出现了轻量级的采集端beat家族,目前beat家族的成员如下:

  • Filebeat:采集文件中的日志到Elasticsearch。
  • Metricbeat:采集主机的CPU、内存、文件系统、磁盘IO和网络IO等信息到ElasticSearch
  • Packetbeat:对网络包进行采集,将采集数据发到ElasticSearch
  • winlogbeat:采集windows系统的event logs到Elasticsearch
  • Heartbat:对服务进行健康检查,将检查结果发给Elasticsearch

Elasticsearch配置

elaticsearch的配置文件采用yaml文件格式

配置项名称

含义

cluster.name

ES集群名称

node.name

ES节点名称

node.master

是否允许该节点成为master

node.data

是否允许该节点成为数据节点

path.logs

存储ES日志的目录

path.data

存储ES数据的目录

transport.host

bind的主机地址

discovery.zen.ping.unicast.hosts

集群中主机之间相互发现时使用该字段,指定集群内的所有主机IP,格式如discovery.zen.ping.unicast.hosts: ["host1", "host2"]

discovery.zen.minimum_master_nodes

成为master的时候,集群中至少需要多少个节点

logstash配置

logstash的配置文件包含三部分: 1、input部分,指定数据源,可以同时指定多个数据源,可以使syslog,标准输出,kafka等

2、filter部分,数据处理部分,可以对输入的数据做格式解析,提取新字段等。

3、output部分, 指定数据输出到哪里,可以同时指定多个输出源,可以是标准输出,kafka,redis和elasticsearch等。

kibana配置

kibana的配置文件也是采用yaml格式

配置项名称

含义

server.port

web的服务端口,默认为5601

elasticsearch.url

指定elasticsearch的url

server.ssl.enabled

是否启用https

server.ssl.certificate

ssl证书

logging.dest

日志输出的地址

logging.silent

控制是否输出日志

使用腾讯云容器服务搭建ELK

下面的搭建步骤基于腾讯云容器服务来搭建,容器服务集群中包括两台机器,配置是2核4G的ubuntu16.04系统。 搭建步骤如下:

  1. 创建 elasticseach服务,该服务包含一个ES容器
  2. 创建kibana服务,该服务包含一个kibana容器,kibana和Elasticsearch 之间以服务的方式连接。
  3. 搭建kibana的鉴权服务,该服务使用nginx容器,放在kibana前面,避免kibaban在公网上被随机登录使用。
  4. 创建nginx应用服务,该服务包括两个容器,一个nginx还有一个是logstash,logstash和nginx容器之间共享数据目录/var/log/nginx,logstash采集nginx的访问日志文件并将新生成的日志发给ElasticSearch。

搭建过程中使用的镜像是dockerhub上的offical的elasticsearch、kibana和logstash的镜像,版本为5.4

在搭建ELK之前,参考Elasticsearch的安装文档,需要对容器主机做相关设置:

  • 使用free命令确保主机至少有3G的可用内存,因为elastic search的镜像中的java配置参数是2G.
  • 在每台容器主机上执行sysctl -w vm.max_map_count=262144。ES默认使用 hybrid mmapfs / niofs 目录来存储索引。 默认操作系统对mmap计数的限制太低,可能引发内存不足的异常。

创建elasticsearch服务

启动elastcisearch的docker run命令如下:

docker run -d --name elas -p 9200:9200 -v "$PWD/esdata":/usr/share/elasticsearch/data elasticsearch -Etransport.host=0.0.0.0 -Ediscovery.zen.minimum_master_nodes=1

对应腾讯容器服务控制台创建elasticsearch的参数配置如下:

配置项名称

配置值

服务名称

elasticsearch

CPU限制

1核

内存限制

3072M

镜像

elasticsearch

镜像版本

5.4

实例个数

1

运行命令

/docker-entrypoint.sh

运行参数

-Etransport.host=0.0.0.0 -Ediscovery.zen.minimum_master_nodes=1

网络参数

网络方式选仅在集群内访问,协议选TCP,容器端口9200,服务端口9200

数据卷

选择本地磁盘,选择一个主机目录,取名为esdata

挂载点

选择数据卷esdata,映射到容器目录为/usr/share/elasticsearch/data

另外为了避免容器还在运行状态但是es进程异常导致服务不可用,可以考虑给elasticsearch服务配置健康检查参数。

创建kibana服务

启动kibana的docker run 命令如下:

docker run --name some-kibana --link elas:elasticsearch -p 5601:5601 -d kibana

对应腾讯容器服务控制台创建该服务的参数如下:

配置项名称

配置值

服务名称

kibana

核数

1核

内存

512M

实例个数

1

镜像

kibana

镜像版本

5.4

网络方式

提供集群内访问方式,不在公网上直接暴露5601的端口

创建kibana认证服务

第一步,在主机上用htpasswd生成包含用户名和密码的文件,具体的使用方式如下:

htpasswd /etc/nginx/.htpasswd administrator

在两台主机上将生成的帐号密码文件.htpasswd放到该目录放到/home/ubuntu/conf目录下

第二步,在两台主机的/home/ubuntu/conf目录下创建nginx的配置文件内容如下:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;
    server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        auth_basic "kibana ui";
        auth_basic_user_file /conf/.htpasswd;
        autoindex on;
        proxy_pass   http://kibana:5601;
        proxy_set_header X-Real-IP $remote_addr;

    }
  }
}

第三步,创建nginx认证服务,配置参数如下:

配置项名称

配置值

服务名称

nginx-basicauth

镜像

nginx

数据卷1

使用本地硬盘,volume名称用nginxconf,对应的主机目录 /home/ubuntu/conf/nginx.conf

数据卷2

使用本地磁盘,volume名称用passwd,对应的主机目录/home/ubuntu/conf/.htpasswd

网络方式

提供公网访问,容器端口用80,服务端口用9098

挂载点1

使用volume nginxconf,容器内目录/etc/nginx/nginx.conf,放nginx的配置文件

挂载点2

使用volume passwd,容器内目录/conf/.htpasswd,放basic auth的用户密码文件

第四步,在外网访问kibana服务,输入正确的用户名和密码后,可以看到kibana的界面,表示这一步配置成功。

输入正确的用户名和密码后,如果可以看到kibana的如下界面,表示ELK搭建成功:

创建nginx应用服务

第一步,先在两台主机上放好logstash的配置文件,配置文件的内容如下,配置文件放到主机的/home/ubuntu/conf/logstash.conf,需要映射到logstash容器的目录为/conf/logstash.conf。该配置文件同时抓取access.log和error.log两个日志文件到elasticsearch。

   input {
     file {
     path => ["/var/log/nginx/access.log"]
     type => "nginx_access_log"
     start_position => "beginning"
    }
     file {
     path => ["/var/log/nginx/error.log"]
     type => "nginx_error_log"
     start_position => "beginning"
    }
   }
   output {
     elasticsearch { hosts => ["elasticsearch:9200"] }
   }

第二步,创建两个数据卷

数据卷名称

对应的本机目录

用途

log

不填主机上临时分配

nginx在该目录下产生日志,logstash读取该目录的日志

conf

/home/ubuntu/conf

存放nginx的启动配置文件

第三步, 创建logstash容器

配置项名称

配置值

实例个数

1

镜像

logstash

镜像版本

5.4

核数

1

内存

1650M

运行命令

/docker-entrypoint.sh

运行参数

-f /conf/logstash.conf,注意在界面上填的时候,-f 和/conf/logstash.conf要放两行

挂载点1

挂载卷 log,容器目录/var/log/nginx,存放nginx生成的日志文件

挂载点2

挂载卷conf,容器目录/conf,存放logstash的配置文件

第四步, 创建nginx容器

配置项名称

配置值

实例个数

1

镜像

nginx

内存

128M

核数

0.2

挂载点1

挂载卷 log,容器目录/var/log/nginx,存放nginx生成的日志文件

第五步,将nginx的端口80映射到外部8088端口

第六步:等服务创建完成,通过网页访问nginx服务,检查kibana界面上是否可以看到nginx的访问日志,正常的访问日志如下:

搭建过程问题总结

在使用腾讯云容器服务搭建ELK系统的过程中碰到如下问题:

  1. 容器主机上用docker run运行ElasticSearch没有跑起来,原因是elasticSearch对内存要求较高,申请的主机如果只有1G的内存,容器会自动退出(原因为配置的javaoption都是2G的内存,配置文件在/etc/elasticsearch目录),建议使用4G以上的主机;另外需要对主机执行sysctl -w vm.max_map_count=262144。运行ES之前需要做的系统配置在https://www.elastic.co/guide/en/elasticsearch/reference/current/system-config.html
  2. 对于docker run命令可以正常运行的elastic search,相同的参数使用容器服务运行失败。原因是容器服务默认做了内存限制,大小为128M,因为镜像中的默认配置是2G,先通过free看可用内存是否有2G,如果没有的2G的话就用 echo 3 > /proc/sys/vm/drop_caches 释放一部分内存出来,如果该参数设置为刚刚好2G还是会报错killed,建议用3G。
  3. logstash用默认设置128M启动不了,原因是镜像中配置的jvm option选项最小堆栈是256M,最大为1g;通过将logstash的内存调到1G。
  4. 数据采集端logstash如果采集的是主机某个目录的日志,碰上这种情况需要容器服务支持daemonset的功能,指定对应的采集pod在某些label的主机上运行,还有如果可以支持自定义配置文件的定义和下发,让容器可以引用到下发的配置文件,就不用预先在所有的主机上预先放置配置文件了。这两个需求点待容器服务推出daemonset和配置管理功能后就能很好地解决。
  5. 如果需要重新搭建一套elk环境,通过目前界面上的操作比较繁琐,希望能够支持从已经部署完的服务中导出yaml配置文件,支持从yaml文件导入创建服务。这个需求点,目前容器服务团队已经在做应用模版的开发工作,推出应用模版后可以解决该问题。
  6. 本文档的部署方式只用一个elaticsearch容器,当elasticsearch容器所在的主机异常时,如果elasticsearch在另外一台机器上启动了,原先的数据就看不到了,针对这种情况,就需要容器服务支持网络存储如nfs volume等。olume等。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏鬼谷君

使用Nginx转发TCP/UDP数据

1533
来自专栏编程

如何建立一个Node.js的应用生产在Ubuntu 14.04

Node.js是一个开源的Javascript运行时环境,可以轻松构建服务器端和网络应用程序。该平台运行在Linux,OS X,FreeBSD和Windows上...

2080
来自专栏我和未来有约会

在创建的Silverlight Control中使用图片

在创建的Silverlight Control中使用图片  在做控件的Template的时,有可能需要用到位图。但是直接把图片放到ControlTempla...

2614
来自专栏Java工程师日常干货

docker化你的java应用(下)

在《docker化你的java应用(上)》中,我们已经初步接触了docker的核心概念与思想,本篇博客将对docker进行实践,会介绍一些docker常用的命令...

831
来自专栏贺贺的前端工程师之路

第一次发布自己的npm包

在做表单的时候,会遇到很多的表单项的验证工作,几乎很多验证都是重复的,有一个比较好的lodash库来做了这些工作,但是里面有些方法和实际的业务工作有些不符。比如...

732
来自专栏phodal

如何以“正确的姿势”阅读开源软件代码

之前想过写这篇文章,但是没有想到一个好的内容、好的突破点。在《GitHub 漫游指南》指南里,我们提到过《如何在GitHub“寻找灵感(fork)”》,但是并不...

16810
来自专栏地方网络工作室的专栏

打造前端 Deepin Linux 工作环境——配置静态服务器

打造前端 Deepin Linux 工作环境——配置静态服务器 我们前面虽然已经安装了一个 xampp 的集成服务器环境,但是这个东西实在是太重了。一般情况下,...

2028
来自专栏AndroidTv

【Android】你应该知道的调试神器--adb

最近跟着一个前辈在做TV应用,因为不能通过usb连接调试,接触到了adb,突然间觉得自己似乎发现了另外一个世界,借助adb shell命令对应用进行调试,简直方...

3988
来自专栏前端大白专栏

使用gulp实现自动刷新浏览器

1775
来自专栏java思维导图

思维导图学linux

写在前面 网上收集一些有关linux的思维导图,希望对你们有用哈。 linux命令大全 ? linux内核 ? ? ? ? ? 说明 这篇文章只有高清图,没有...

3486

扫码关注云+社区