日志

日志

使用开源工具fluentd-pilot收集容器日志

Rancher 发表了文章 • 1 个评论 • 2321 次浏览 • 2017-12-20 11:49 • 来自相关话题

来自用户的最佳实践分享,如何用阿里开源的Docker日志收集工具fluentd-pilot收集机器上所有Docker应用日志。 fluentd-pilot简介 fluentd-pilot是阿里开源的docke ...查看全部
来自用户的最佳实践分享,如何用阿里开源的Docker日志收集工具fluentd-pilot收集机器上所有Docker应用日志。

fluentd-pilot简介

fluentd-pilot是阿里开源的docker日志收集工具,Github项目地址 。你可以在每台机器上部署一个fluentd-pilot实例,就可以收集机器上所有Docker应用日志。

fluentd-pilot 具有如下特性:

  • 一个单独的 fluentd 进程收集机器上所有容器的日志。不需要为每个容器启动一个 fluentd 进程。
  • 支持文件日志和 stdout。docker log dirver 亦或 logspout 只能处理 stdout,fluentd-pilot 不仅支持收集 stdout 日志,还可以收集文件日志。
  • 声明式配置。当您的容器有日志要收集,只要通过 label 声明要收集的日志文件的路径,无需改动其他任何配置,fluentd-pilot 就会自动收集新容器的日志。
  • 支持多种日志存储方式。无论是强大的阿里云日志服务,还是比较流行的 elasticsearch 组合,甚至是 graylog,fluentd-pilot 都能把日志投递到正确的地点。
rancher使用fluentd-pilot收集日志我们既然要用fluentd-pilot,就得先把它启动起来。还要有一个日志系统,日志要集中收集,必然要有一个中间服务去收集和存储,所以要先把这种东西准备好。Rancher中我们要如何做?如图,首先我们选择Rancher的应用商店中的Elasticsearch和Kibana。版本没有要求,下面使用Elasticsearch2.X和Kibana4。其次在RancherAgent主机上面部署一个fluentd-pilot容器,然后在容器里面启动的时候,我们要声明容器的日志信息,fluentd-pilot会自动感知所有容器的配置。每次启动容器或者删除容器的时候,它能够看得到,当看到容器有新容器产生之后,它就会自动给新容器按照你的配置生成对应的配置文件,然后去采集,最后采集回来的日志同样也会根据配置发送到后端存储里面去,这里面后端主要指的elasticsearch或者是SLS这样的系统,接下来你可以在这个系统上面用一些工具来查询等等。可根据实际情况,在每台Agent定义主机标签,通过主机标签在每台RancherAgent主机上跑一个pilot容器。用这个命令来部署,其实现在它是一个标准的Docker镜像,内部支持一些后端存储,可以通过环境变量来指定日志放到哪儿去,这样的配置方式会把所有的收集到的日志全部都发送到elasticsearch里面去,当然两个挂载是需要的,因为它连接Docker,要感知到Docker里面所有容器的变化,它要通过这种方式来访问宿主机的一些信息。在Rancher环境下使用以下docker-compose.yml 应用---->添加应用,在可选docker-compose.yml中添加一下内容。
version: '2'services:  pilot:    image: registry.cn-hangzhou.aliyuncs.com/acs-sample/fluentd-pilot:0.1    environment:      ELASTICSEARCH_HOST: elasticsearch      ELASTICSEARCH_PORT: '9200'      FLUENTD_OUTPUT: elasticsearch    external_links:    - es-cluster/es-master:elasticsearch    volumes:    - /var/run/docker.sock:/var/run/docker.sock    - /:/host    labels:      aliyun.global: 'true'
配置好之后启动自己的应用(例子:tomcat),我们看应用上面要收集的日志,我该在上面做什么样的声明?关键的配置有两个,一是label catalina,声明的是要收集容器的日志为什么格式(标准格式等,也可以是文件。),所有的名字都可以;二是声明access,这也是个名字,都可以用你喜欢的名字。这样一个路径的地址,当你通过这样的配置来去启动fluentd-pilot容器之后,它就能够感觉到这样一个容器的启动事件,它会去看容器的配置是什么,要收集这个目录下面的文件日志,然后告诉fluentd-pilot去中心配置并且去采集,这里还需要一个卷,实际上跟Logs目录是一致的,在容器外面实际上没有一种通用的方式能够获取到容器里面的文件,所有我们主动把目录从宿主机上挂载进来,这样就可以在宿主机上看到目录下面所有的东西。当你通过部署之后,他会自己在elasticsearch创建索引,就可以在elasticsearch的kopf上面看到会生成两个东西,都是自动创建好的,不用管一些配置,你唯一要做的事是什么呢?就可以在kibana上创建日志index pattern了。然后到日志搜索界面,可以看到从哪过来的,这条日志的内容是什么,这些信息都已经很快的出现了。Lable说明启动tomcat的时候,我们声明了这样下面两个,告诉fluentd-pilot这个容器的日志位置。
aliyun.logs.tomcat1-access   /opt/apache-tomcat-8.0.14/logs/localhost_access_log.*.txt aliyun.logs.catalina   stdout
你还可以在应用容器上添加更多的标签aliyun.logs.$name = $path
  • 变量name是日志名称,具体指随便是什么,你高兴就好。只能包含0-9a-zA-Z_和-
  • 变量path是要收集的日志路径,必须具体到文件,不能只写目录。文件名部分可以使用通配符。/var/log/he.log和/var/log/*.log都是正确的值,但/var/log不行,不能只写到目录。stdout是一个特殊值,表示标准输出
aliyun.logs.$name.format,日志格式,目前支持
  • none 无格式纯文本
  • json: json格式,每行一个完整的json字符串
  • csv: csv格式
aliyun.logs.$name.tags: 上报日志的时候,额外增加的字段,格式为k1=v1,k2=v2,每个key-value之间使用逗号分隔,例如
  • aliyun.logs.access.tags="name=hello,stage=test",上报到存储的日志里就会出现name字段和stage字段
  • 如果使用elasticsearch作为日志存储,target这个tag具有特殊含义,表示elasticsearch里对应的index

#作者简介

翟坤,随行付支付有限公司资深运维工程师。
本文版权归作者所有,转载请后台留言。

关于应用日志持久化到本地的一个问题

voidint 回复了问题 • 2 人关注 • 1 个回复 • 1975 次浏览 • 2017-09-21 09:19 • 来自相关话题

DockOne微信分享(一二四):轻松筹监控系统实现方案

jiadas 发表了文章 • 1 个评论 • 9292 次浏览 • 2017-06-10 14:55 • 来自相关话题

【编者的话】监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况。虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化。这样既可以更灵活的满足自身 ...查看全部
【编者的话】监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况。虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化。这样既可以更灵活的满足自身业务的监控需求,也可以为以后自建机房提供技术积累。通过以下7个方面来建设监控系统。

【3 天烧脑式 Docker 训练营 | 上海站】随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛。本次培训我们理论结合实践,从Docker应该场景、持续部署与交付、如何提升测试效率、存储、网络、监控、安全等角度进行。

WechatIMG21.jpeg

# 1 . 日志打印
完善的日志是实现监控的基础,如何打印日志关系到之后的日志过滤、存储以及分析。除了选择合适的日志库,还要满足一些日志打印的要求:

  • 日志风格:以key-value的field形式输出结构化的日志。
  • 输出时机: error日志一定都需要打印,info日志结合业务需求适当打印,日志只需要在业务层关注,model和util等不需要打印。
  • 输出格式:线上以json的格式打印日志,方便解析日志。线下为了方便查看,可以用自定义的format打印日志,线上和线下的日志格式通过etcd来控制。
  • 输出内容: 每一条日志都要携带logid、method、host和level,并且根据不同业务场景,需要携带不同业务的标识field,例如projectType、platform、payType等。
  • 用context来传递不同goroutine之间的共享信息。

# 2 . 日志切分
日志切分是运维层面的东西,不应该由日志库来承担日志切分的事情,因为Linux在日志切分上有很成熟的工具,不需要自己写码去重复实现。

目前对日志切分的需求只有2个:按天切分和删除切出来的多余日志。logrotate就能很好的满足这些需求,logrotate是基于cron来运行的,其脚本是/etc/cron.daily/logrotate,默认放在/etc/cron.daily下,每天执行一次。

有的时候程序异常或者请求激增会导致日志量暴增,有可能在短时间内打满整个磁盘。可以在logrotate的配置文件里加上maxsize来限制日志文件的大小,并且将logrotate的执行频率调高至每小时甚至每分钟,及时切分并删除超过rotate数量的日志,来防止异常情况下磁盘被打满的情况发生。

样例配置如下所示:
// logrotate config of sample
// rotate every day, and keep for 3 days
/var/log/sample.log {
daily
rotate 3
maxsize 1G
missingok
sharedscripts
postrotate
# 在切分时向程序发送SIGHUP信号
killall -SIGHUP bin_sample
endscript
}

业务程序只需要负责监听SIGHUP信号,收到该信号时再重新打开日志文件。
# 3 . 日志采集
从监控系统的角度来说,日志收集有2种方式:主动采集和被动接收,两种方式各有利弊。
##主动采集
优点:日志收集和业务程序分开,互不影响。

缺点:日志收集需要依赖额外的采集服务,过滤和存储可能还需要额外配置。
##被动接收
优点:业务程序直接将日志发送至存储,灵活性强,存储内容可在业务代码里控制。

缺点:日志存储不稳定的话会影响业务程序的正常运行;反之,日志量大的话也会压垮日志存储。

但是在建设监控系统初期,日志存储还不是很稳定的情况下,还是用主动采集的方式比较稳妥,不影响服务稳定性为主。
WechatIMG24.jpeg

Collectd功能确实很强大,它的tail插件也能满足从文件收集日志,但是tail插件配置比较复杂而且说明文档相较于Filebeat来说不是很详细。

Collectd的其他插件可以采集的数据确实很多,而且也有插件支持将数据发送到Logstash和InfluxDB,但是多数插件的功能我们用不到,而且Elastic Stack中的Beats也能够很好的收集系统参数等数据,而且跟ELK能很好的兼容。

所以在分别试用了Filebeat和Collectd这2个采集服务后,综合上述分析决定采用Filebeat来负责从日志文件中采集日志。如下所示,Filebeat的配置简单易懂:
filebeat:
spool_size: 1024 # 最大可以攒够 1024 条数据一起发送出去
idle_timeout: "5s" # 否则每 5 秒钟也得发送一次
registry_file: "registry" # 文件读取位置记录文件,会放在当前工作目录下。
config_dir: "path/to/configs/contains/many/yaml" # 如果配置过长,可以通过目录加载方式拆分配置
prospectors: # 有相同配置参数的可以归类为一个 prospector
-
fields:
log_source: "sample" # 类似 logstash 的 add_fields,此处的"log_source"用来标识该日志来源于哪个项目
paths:
- /var/log/system.log # 指明读取文件的位置
- /var/log/wifi.log
include_lines: ["^ERR", "^WARN"] # 只发送包含这些字样的日志
exclude_lines: ["^OK"] # 不发送包含这些字样的日志
-
document_type: "apache" # 定义写入 ES 时的 _type 值
ignore_older: "24h" # 超过 24 小时没更新内容的文件不再监听。
scan_frequency: "10s" # 每 10 秒钟扫描一次目录,更新通配符匹配上的文件列表
tail_files: false # 是否从文件末尾开始读取
harvester_buffer_size: 16384 # 实际读取文件时,每次读取 16384 字节
backoff: "1s" # 每 1 秒检测一次文件是否有新的一行内容需要读取
paths:
- "/var/log/apache/*" # 可以使用通配符
exclude_files: ["/var/log/apache/error.log"]
-
input_type: "stdin" # 除了 "log",还有 "stdin"
multiline: # 多行合并
pattern: '^[[:space:]]'
negate: false
match: after
output:
logstash:
hosts: ["localhost:5044"] # The Logstash hosts

Filebeat 发送的日志,会包含以下字段:

* beat.hostname beat 运行的主机名
* beat.name shipper 配置段设置的 name,如果没设置,等于 beat.hostname
* @timestamp 读取到该行内容的时间
* type 通过 document_type 设定的内容
* input_type 来自 "log" 还是 "stdin"
* source 具体的文件名全路径
* offset 该行日志的起始偏移量
* message 日志内容
* fields 添加的其他固定字段都存在这个对象里面

# 4 . 日志过滤
logstash.png

Logstash 自2009年诞生经过多年发展,已经是很成熟并且流行的日志处理框架。Logstash使用管道方式进行日志的搜集处理和输出。有点类似*NIX系统的管道命令 input | filter | output,input 执行完了会执行 filter,然后执行 output。在 Logstash 中,包括了三个阶段:输入input → 处理filter(不是必须的)→ 输出output。每个阶段都由很多的插件配合工作,比如 file、elasticsearch、redis 等等。每个阶段也可以指定多种方式,比如输出既可以输出到elasticsearch中,也可以指定到stdout在控制台打印。

Codec 是 Logstash 从 1.3.0 版开始新引入的概念(Codec 来自 Coder/decoder两个单词的首字母缩写)。在此之前,Logstash 只支持纯文本形式输入,然后以过滤器处理它。但现在,我们可以在输入 期处理不同类型的数据,这全是因为有 Codec 设置。所以,这里需要纠正之前的一个概念。Logstash 不只是一个 input | filter | output 的数据流,而是一个 input | decode | filter | encode | output 的数据流!Codec 就是用来 decode、encode 事件的。Codec 的引入,使得 Logstash 可以更好更方便的与其他有自定义数据格式的运维产品共存,比如 graphite、fluent、netflow、collectd,以及使用msgpack、json、edn 等通用数据格式的其他产品等。

Logstash 提供了非常多的插件(Input plugins、Output plugins、Filter plugins、Codec plugins),可以根据需求自行组合。其中 Filter 插件 Grok 是 Logstash 最重要的插件。Grok 通过正则表达式匹配日志内容,并将日志结构化,所以理论上只要正则掌握的够娴熟,就能解析任何形式的日志,非常适合用来解析第三方服务产生的非结构化日志。但是如果是自己写的服务,就没必要将日志输出成非结构的,增加写正则的负担,所以在上述日志打印一节中才规定线上的日志输出成json形式,方便 Logstash 解析,Logstash 提供 json 的 Filter 插件。

Logstash 的配置文件默认放在 /etc/logstash/conf.d 目录下,如果需要采集多个项目的日志,每个项目的 Logstash 配置可能不一样,那就会在 conf.d 里存放多个配置文件,以每个项目命名方便管理。但是这样会带来一个问题,因为 Logstash 会将所有配置文件合并为一个,即一条日志通过input进入到Logstash后,会经过每个配置文件里的filter和output插件,造成对日志错误的处理和输出。解决方式是在Filebeat的fileds配置项里增加区分不同项目的field,如果日志路径就能区分不同项目的话也可以不用额外加field,用 Filebeat 自带的source字段就可以,然后在每个项目对应的 Logstash 配置文件里通过IF标识项目,项目各自的日志进各自的配置,互不干扰。

下列配置示例是对一个sample服务产生的json日志,通过Filebeat采集,用json的Filter插件进行解析,并将结果输出到标准输出。
input {
beats {
port => "5044"
}
}
// The filter part of this file is commented out to indicate that it is
// optional.
filter {
if [beat] and [source] =~ "sample" {
json {
source => "message"
}
ruby {
code => "event.set('time',(Time.parse(event.get('time')).to_f*1000000).to_i)"
}
}
}
output {
if [beat] and [source] =~ "sample" {
stdout { codec => rubydebug }
}
}

# 5 . 日志存储
InfluxDB vs. Elasticsearch

根据 DB-ENGINES 的排名,InfluxDB和Elasticsearch在各自专攻的领域都是NO.1,InfluxDB统治Time Series DBMS,Elasticsearch制霸Search engine,关于它们的原理和使用,各自都有非常详细的文档和资料,这里就不再赘述。

在时序数据方面,InfluxDB表现强劲,Elasticsearch在主要的指标上均远落于下风:

数据写入:同时起4个进程写入8百64万条数据,Elasticsearch平均为 115,422 条/秒,InfluxDB平均 926,389 条/秒,写入速度是Elasticsearch的8倍。这种写入速度的差距随着数据量的增大保持相对一致。
elastic-write-768x518.png

磁盘存储:存储相同的8百64万条数据,使用默认配置的Elasticsearch需要2.1G,使用针对时序数据配置的Elasticsearch需要517MB,而InfluxDB只需要127MB,压缩率分别是前两者的16倍和4倍。
elastic-compression.png

数据查询:在24h的数据集(8百64万条数据)里随机查询1个小时内的数据,按1分钟的时间间隔聚合,Elasticsearch和InfluxDB分别单进程执行1000次这种查询,算耗时的平均值。Elasticsearch耗时4.98ms(201次查询/秒),InfluxDB耗时1.26ms(794次查询/秒),查询速度是Elasticsearch的4倍。随着数据集的增大,查询速度之间的差距逐渐拉大,最大相差10倍之多。而且随着执行查询的进程数增加,InfluxDB的查询速度增幅显著,而且在不同数据集之间的查询速度基本一致,但是Elasticsearch增幅就不大,而且随着数据集的增大查询速度是递减的。
throughput.png

WechatIMG22.png

详细的比较说明参见:InfluxDB Markedly Outperforms Elasticsearch in Time-Series Data & Metrics Benchmark

Elasticsearch强在全文搜索,InfluxDB擅长时序数据,所以还是具体需求具体分析。如果需要保存日志并经常查询的,Elasticsearch比较合适;如果只依赖日志做状态展示,偶尔查询,InfluxDB比较合适。

轻松筹的业务各有特点,单一选择Elasticsearch或者InfluxDB都不能很好的查询日志和指标展示,所以有必要InfluxDB和Elasticsearch共存。在 Logstash 里配置2个输出,同一条日志输出2份,一份保留全部字段输出至 Elasticsearch;另一份过滤文本性的字段保留指标性的字段,然后输出至 InfluxDB。

InfluxDB如果作为Logstash的输出,有个坑需要注意,就是Logstash的InfluxDB插件支持的时间戳精度太粗,不能精确到纳秒,会导致同一个值的时间戳在插入InfluxDB的时候出现异常。因为InfluxDB用measurement名、tag集和时间戳来唯一标识一条记录。如果插入InfluxDB的一条记录与已经存在的一条记录measurement名、tag集和时间戳都相同,那么filed会是新老两条记录的集合,相同field的值会被新记录覆盖。 解决方式有2种,一种是增加一个tag来标识新记录。另一种是手动提升时间戳的精度,提升至微秒,理论上每天可以支持86,400,000,000条不重复的日志,可以很大程度避免时间戳的重叠,配置如下所示:
// 业务日志输出时时间戳格式化到微秒:2006-01-02T15:04:05.999999Z07:00

// Logstash的filter根据时间戳转换
filter {
ruby {
code => "event.set('time',(Time.parse(event.get('time')).to_f*1000000).to_i)"
}
}

# 6 . 数据展示
Grafana vs. Kibana
WechatIMG23.png

比较Kibana和Grafana,Kibana在图表展示上没有Grafana美观,而且Grafana的配置更加简单灵活。既然在日志存储中决定InfluxDB和Elasticsearch共存,展示上就也需要Kibana和Grafana共同协作,Kibana从Elasticsearch中检索日志,Grafana从InfluxDB和Elasticsearch中获取展示数据。下面2张图片展示了Grafana在轻松筹业务监控上的应用:
feed.png

sample2.png

# 7 . 异常报警
即使上述6个环节都建立了,如果没有报警一切都是没有意义的,因为不可能每时每刻都盯着曲线看,所以需要设置异常阈值,让监控系统定时检查,发现异常立即发送报警通知。

报警的服务有很多,但是数据展示的Grafana自带报警功能,功能也能满足我们的报警需求,而且配置简单,所以规则简单的报警可以采用Grafana的报警服务。不过Grafana的报警只支持部分数据库,分别是Graphite, Prometheus, InfluxDB 和 OpenTSDB,所以在Elasticsearch中的日志报警还需要Elastic Stack的X-Pack。
##Condition
image2017-4-20_15-10-32.png

如上图所示,可以设置报警检查的频率,报警条件是最近的5分钟内指定指标的平均值是否大于70,如果这个条件为True则触发报警。这种报警条件还比较单一,像错误数在十分钟内超过几次才报警,当前订单数与昨天同一时间的订单数比较跌了超过百分之几就报警,控制报警通知发送的频率,等等,Grafana就不能满足了,针对这种报警规则我们自己实现了一个报警引擎,用来满足这些比较复杂的报警规则。
##Notification
Grafana的报警通知只有在状态转换时才会触发,即报警状态的时候会发送告警通知,如果到恢复之前的一段时间里条件一直是满足报警条件的,Grafana不会一直发送通知,直到恢复的时候再发送一次恢复的通知。如果触发报警,Grafana支持4中通知方式:Email、Slack、Webhook 和 PagerDuty。其中Slack是国外的一种协作工具,类似钉钉,PagerDuty是一个收费的告警平台,所以可选的只剩下Email和Webhook了。下面简单的介绍如何配置Email和Webhook
##Email
Grafana的邮件配置很简单,可以利用QQ企业邮箱的smtp服务来发送报警邮件,邮件内容是配置的报警,配置比较简单:
[smtp]
enabled = true
host = smtp.exmail.qq.com:465
user = alert@qingsongchou.com
password = ********
from_address = alert@qingsongchou.com
from_user = Grafana

##Webhook
Webhook 就是在触发报警时,Grafana主动调用配置的http服务,以POST或者PUT方式传递json数据。这样就可以在我们自己开发的http服务里增加额外的通知方式,例如短信、微信甚至电话。
##Reception
配置了报警通知,不接收不去看也是白搭。一方面我们尽量实现多种通知途径,比如邮件、微信和短信。另一方面需要项目负责人接到报警及时响应,查看问题。
# Q&A
Q:针对Grafana不支持的报警,你们自己实现的报警引擎是直接在grafana的基础上修改的么,还是独立于Grafana呢?

A:我们用Go自己实现的一个报警引擎,独立于Grafana。



Q:Logstash 你们遇到过收集慢和丢日志的情况吗?现在你们Logstash收集日志到什么规模了?

A:我们目前的日质量大概每天2亿条,高峰时候每小时2000万条左右。Logstash运行的还可以,如果后期遇到手机慢,做简单的方式是扩机器,先解决问题,再想更好的优化策略。



Q:如果类似于Nginx、MySQL这种日志,类型增加需要解析每增加一个就要去改Logstash的grok吗?

A:针对常用的服务,grok已经提供了一些正则的pattern,例如你提到的Nginx、MySQL。目前是每增加一个就需要修改grok,后期可以实现一个UI来提高修改效率。



Q:这个lostash日志格式转换怎么学习?

A:Logstash有很完善的文档,感兴趣的话可以参考https://www.elastic.co/guide/en/logstash/current/index.html



Q:据说Logstash比较吃内存,fluentd作为EFK组合也经常出现,请问你们有没有做过选型呢?

A:当时选择了ELK,就没有做太多的选型了,Logstash吃内存的问题现在还不是太突出。



Q:日志的完整性怎么保证的?怎么知道没丢日志,或丢失了多少日志?

A:Filebeat和Logstash的输出插件都有一些重试的策略,但是也免不了日志丢失。日志的完整性确实和保证日志不丢也是我们目前在尝试解决的问题。



Q:请问监控系统需要考虑高可用吗?

A:肯定是要考虑高可用,当后期更多的业务依赖监控系统后,就要保证监控系统不挂,查询要快,实时监控,报警准确等。



轻松筹,一亿用户信赖的全民众筹平台!

以上内容根据2017年6月8日晚微信群分享内容整理。分享人施佳达,轻松筹GoLang高级工程师,北邮研究生,在分布式计算与舆情分析领域有深入研究,2015年滴滴出行公共平台负责滴滴出行Web APP后端研发,目前在轻松筹主要从事Feed系统架构设计以及重明鸟监控系统的建设。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

使用ELK处理Docker日志(一)

Dataman数人科技 发表了文章 • 0 个评论 • 19239 次浏览 • 2017-04-18 10:31 • 来自相关话题

【编者的话】Daniel Berman(Logz.io产品经理)为了纪念Docker四岁生日,撰写一系列文章,介绍如何使用ELK收集和处理Dockerized环境日志。小数今天给大家带来的第一部分将介绍如何安装各个组件以及不同日志收集方案的特点,下一部分将侧重 ...查看全部

【编者的话】Daniel Berman(Logz.io产品经理)为了纪念Docker四岁生日,撰写一系列文章,介绍如何使用ELK收集和处理Dockerized环境日志。小数今天给大家带来的第一部分将介绍如何安装各个组件以及不同日志收集方案的特点,下一部分将侧重于分析和可视化,近期发出,记得关注我们噢~
>
> PS:工程师们已奔赴奥斯汀DockerCON2017现场,更多最佳实践后天为您奉上!



【深圳站|3天烧脑式Kubernetes训练营】培训内容包括:Kubernetes概述和架构、部署和核心机制分析、进阶篇——Kubernetes调工作原理及源码分析等。


容器运行程序时产生的日志具有“无常,分布,隔离”等特点,因此在架构中收集Docker日志面临很大的挑战,有待尝试一种强有力的日志收集和处理方案来解决此类复杂问题。

ELK (Elasticsearch,Logstash和Kibana)是处理容器日志的一种方式,尽管设置ELK工作流并不容易(难度取决于环境规格),但最终可以使用Kibana的监控面板来展示Docker日志:

.

为了纪念Docker四岁生日,我们将撰写一系列文章,介绍如何使用ELK收集和处理Dockerized环境日志。第一部分将介绍如何安装各个组件以及不同日志收集方案的特点,并建立从容器中收集日志的工作流,下一部分将侧重于分析和可视化。

日志收集的流程

Dockerized环境中的典型ELK日志收集流程如下所示:


Logstash负责从各种Docker容器和主机中提取日志,这个流程的主要优点是可以更好地用过滤器来解析日志,Logstash将日志转发到Elasticsearch进行索引,Kibana分析和可视化数据。

当然这个流程可以有多种不同的实现方式, 例如可以使用不同的日志收集和转发组件, 如Fluentd或Filebeat 将日志发送到Elasticsearch,或者,添加一个由Kafka或Redis容器组成的中间层,作为Logstash和Elasticsearch之间的缓冲区。上图显示了日志从Docker到ELK的基本流程。

那么,如何设置这个流程呢?


组件安装


可以将ELK套件安装在一个容器里,也可以使用不同的容器来分别安装各个组件。



关于在Docker上部署ELK是否是生产环境的可行性解决方案(资源消耗和网络是主要问题)仍然存在很多争议,但在开发中这是一种非常方便高效的方案。


ELK的docker镜像推荐使用 docker-elk, 它支持丰富的运行参数(可使用这些参数组合不同的版本)和文档, 而且完全支持最新版本的 Elasticsearch, Logstash, 和 Kibana.


在安装组件之前需要确保以下端口没有被占用:5601 (Kibana), 9200 (Elasticsearch), and 5044 (Logstash).

同时需要确保内核参数 vm_max_map_count 至少设置为262144:
```
sudo sysctl -w vm.max_map_count=262144
```


运行如下命令:
```
git clone https://github.com/deviantony/docker-elk.git
cd docker-elk
docker-compose up
```

正常情况下, ELK套件的三个服务(Elasticsearch, Logstash, Kibana)会启动成功,默认持久化数据目录 /var/lib/elasticsearch (Elasticsearch 的数据存储目录)

sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

73aedc3939ad dockerelk_kibana "/bin/sh -c /usr/l..." 7 minutes ago Up 6 minutes 0.0.0.0:5601->5601/tcp dockerelk_kibana_1

b684045be3d6 dockerelk_logstash "logstash -f /usr/..." 7 minutes ago Up 6 minutes 0.0.0.0:5000->5000/tcp dockerelk_logstash_1

a5778b8e4e6a dockerelk_elasticsearch "/bin/bash bin/es-..." 7 minutes ago Up 7 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp dockerelk_elasticsearch_1




测试安装组件


可通过如下的方式来确保所有组件都能正常运行。

首先尝试访问Elasticsearch运行如下命令:
```
curl localhost:9200
```

输出结果:

```
{
"name" : "W3NuLnv",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "fauVIbHoSE2SlN_nDzxxdA",
"version" : {
"number" : "5.2.1",
"build_hash" : "db0d481",
"build_date" : "2017-02-09T22:05:32.386Z",
"build_snapshot" : false,
"lucene_version" : "6.4.1"
},
"tagline" : "You Know, for Search"
}
```

打开 Kibaba 页面通过http://[serverIP]:5601:



值得注意的是需要输入索引模式才能正常进行后续处理,这个稍后将会介绍。


发送Docker日志到ELK


安装组件比较简单,相比而言将Docker日志发送到ELK有点复杂,这取决于输出日志的方式。

如果没有额外指定,容器的stdout和stderr输出(也称为“docker logs”)输出到JSON文件。所以,如果是一个小型Docker环境,使用Filebeat来收集日志将是不错的选择。但如果使用其他日志记录驱动程序,则可能需要考虑其他方法。

以下是将日志导入ELK的三种不同的方法,切记,这并不能包含所有的方案。


# 使用Filebeat


Filebeat属于Elastic的Beats系列日志收集组件, Filebeat是用Go语言开发的,支持追踪特定文件和日志加密的中间组件,它可以配置将日志导出到Logstash或者直接导出到Elasticsearch.


如上所述,若使用默认的json文件记录驱动程序,Filebeat是一种相对简便的方式,可以输出日志到ELK.Filebeat部署在主机上,或将其作为容器与ELK容器一起运行(在这种情况下,需要添加到ELK容器的链接),这里有各种Filebeat Docker images可用,有些包括运行Filebeat并将其连接到Logstash的配置。

Filebeat配置将需要指定JSON日志文件的路径(位于:/ var / lib / docker / containers / ...)和目标的详细信息(通常是Logstash容器)。

下面是一个配置的例子
```
prospectors:
- paths:
- /var/log/containers/
document_type: syslog
output:
logstash:
enabled: true
hosts:
- elk:5044
```

# 使用日志驱动

Docker从1.12开始支持Logging Driver,允许将Docker日志路由到指定的第三方日志转发层,可将日志转发到AWS CloudWatch,Fluentd,GELF或NAT服务器。

使用logging drivers比较简单,它们需要为每个容器指定,并且将需要在日志的接收端进行其他配置。

在将日志发送到ELK的上下文中,使用syslog日志驱动可能是最简单的方法。


下面是一个指定Logging Driver的例子:
```
docker run \
--log-driver=syslog \
--log-opt syslog-address=tcp://:5000
\ --log-opt syslog-facility=daemon
\ alpine ash
```

如此这样运行每一个容器,结果是将Docker容器日志流输出到syslog实例,这些日志将转发到Logstash容器进行解析和数据增强,进入Elasticsearch。


# 使用Logspout

Logspout是Docker流行和轻量级的(15.2MB)日志路由器,它将附加到主机中的所有容器,并将Docker日志流输出到syslog服务器(除非定义了不同的输出目标)。
```
sudo docker run -d --name="logspout" --volume=/var/run/docker.sock:/var/run/docker.sock gliderlabs/logspout syslog+tls://:5000
```

使用Logstash module直接将日志路由到Logstash容器,但这需要其他配置和编译工作。


# Logz.io的日志采集器


本人在 In this blog post这篇文章中介绍了Logz.io的日志采集器,像Logspout一样,它附加在Docker主机中的所有容器上,但它不仅运送Docker日志,还包含Docker统计信息和Docker守护程序事件。
```
docker run -d --restart=always -v /var/run/docker.sock:/var/run/docker.sock logzio/logzio-docker -t
```

目前它是为Logz.io ELK 套件的用户设计的,我们正在努力将它开源项目。


数据持久化


配置Logstash来解析数据至关重要,因为这部分过程将添加上下文到容器的日志中,并能够更轻松地分析数据。

在Logstash配置文件中需要配置三个主要部分:输入,过滤和输出。 (若运行的是Logstash 5.x,则该文件位于:/ usr / share / logstash / pipeline)

输入取决于日志传送方式,使用Filebeat,则需要指定Beats输入插件。如果使用logspout或syslog日志记录驱动程序,则需要将syslog定义为输入。

过滤器部分包含用于分解日志消息的所有过滤器插件,依赖于正在记录的容器类型以及该特定容器生成的日志消息。

这部分的配置没有捷径,因为每个容器都输出不同类型的日志。有很多尝试和错误涉及,但是有一些在线工具可参考, 比如:Grok Debugger

导出部分将指定Logstash输出,例子中是Elasticsearch容器。

以下是通过syslog发送的Docker日志的基本Logstash配置示例。注意一系列过滤器的使用(grok,date,mutate和if条件):


input {
syslog {
port => 5000
type => "docker"
}
}

filter {
grok {
match => { "message" => "%{SYSLOG5424PRI}%{NONNEGINT:ver} +(?:%{TIMESTAMP_ISO8601:ts}|-) +(?:%{HOSTNAME:service}|-) +(?:%{NOTSPACE:containerName}|-) +(?:%{NOTSPACE:proc}|-) +(?:%{WORD:msgid}|-) +(?:%{SYSLOG5424SD:sd}|-|) +%{GREEDYDATA:msg}" }
}
syslog_pri { }
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
mutate {
remove_field => [ "message", "priority", "ts", "severity", "facility", "facility_label", "severity_label", "syslog5424_pri", "proc", "syslog_severity_code", "syslog_facility_code", "syslog_facility", "syslog_severity", "syslog_hostname", "syslog_message", "syslog_timestamp", "ver" ]
}
mutate {
remove_tag => [ "_grokparsefailure_sysloginput" ]
}
mutate {
gsub => [
"service", "[0123456789-]", ""
]
}
if [msg] =~ "^ *{" {
json {
source => "msg"
}
if "_jsonparsefailure" in [tags] {
drop {}
}
mutate {
remove_field => [ "msg" ]
}
}
}

output {
elasticsearch {
hosts => "elasticsearch:9200"
}
}



重新启动Logstash容器以应用新的配置。检查Elasticsearch索引,确保日志流能正常工作:

```
curl 'localhost:9200/_cat/indices?v'
```

具有Logstash模式的索引:


health status index               uuid                   pri rep docs.count docs.deleted store.size pri.store.size

yellow open logstash-2017.03.05 kgJ0P6jmQjOLNTSmnxsZWQ 5 1 3 0 10.1kb 10.1kb

yellow open .kibana 09NHQ-TnQQmRBnVE2Y93Kw 1 1 1 0 3.2kb 3.2kb



打开Kibana的页面


Kibana已经创建了'logstash- *' 索引是标识,按下“创建”按钮,可在Kibana中看到日志。


结语

Docker日志记录没有完美的方案,无论选择什么解决方案,使用日志记录驱动程序,Filebeat还是SaaS监控平台,每个方案都有优缺点。值得一提的是,Docker日志很有用,但它们只代表由Docker主机生成的数据的一个维度,检索容器统计信息和守护程序事件等还需要额外的日志记录层。

综上所述,Logz.io日志收集器提供了一个全面的日志解决方案,将三个数据流一起拉到ELK中。如需统计数据,建议尝试一下Dockerbeat.本系列的下一部分将重点介绍如何在Kibana中分析和可视化Docker日志。Docker 生日快乐!

Daniel Berman是Logz.io产品经理。擅长日志分析、大数据、云计算,热爱家庭,喜欢跑步,Liverpool FC和写颠覆性的技术内容。

原文链接:https://logz.io/blog/docker-logging/

Rancher体系下容器日志采集

Rancher 发表了文章 • 1 个评论 • 2529 次浏览 • 2017-04-12 10:52 • 来自相关话题

引言 一个完整的容器平台,容器日志都是很重要的一环。尤其在微服务架构大行其道状况下,程序的访问监控健康状态很多都依赖日志信息的收集,由于Docker的存在,让容器平台中的日志收集和传统方式很多不一样,日志的输出和采集点收集和以前大有不 ...查看全部
引言

一个完整的容器平台,容器日志都是很重要的一环。尤其在微服务架构大行其道状况下,程序的访问监控健康状态很多都依赖日志信息的收集,由于Docker的存在,让容器平台中的日志收集和传统方式很多不一样,日志的输出和采集点收集和以前大有不同。本文就探讨一下,Rancher平台内如何做容器日志收集。

当前现状

纵览当前容器日志收集的场景,无非就是两种方式:一是直接采集Docker标准输出,容器内的服务将日志信息写到标准输出,这样通过Docker的log driver可以发送到相应的收集程序中;二是延续传统的日志写入方式,容器内的服务将日志直接写到普通文件中,通过Docker volume将日志文件映射到Host上,日志采集程序就可以收集它。

第一种方式足够简单,直接配置相关的Log Driver就可以,但是这种方式也有些劣势:

1. 当主机的容器密度比较高的时候,对Docker Engine的压力比较大,毕竟容器标准输出都要通过Docker Engine来处理。
2. 尽管原则上,我们希望遵循一容器部署一个服务的原则,但是有时候特殊情况不可避免容器内有多个业务服务,这时候很难做到所有服务都向标准输出写日志,这就需要用到前面所说的第二种场景模式。
3. 虽然我们可以先选择很多种Log Driver,但是有些Log Driver会破坏Docker原生的体验,比如docker logs无法直接看到容器日志。

基于以上考虑,一个完整的日志方案必须要同时满足标准输出和日志卷两种模式才可以。当然完整的日志体系中,并不仅仅是采集,还需要有日志存储和UI展现。日志存储有很多种开源的实现,这个一般用户都会有自己钟情的选择,而UI展现更是各家有各家的需求,很难形成比较好的标准,一般都是通过定制化方式解决。所以此文主要展现的方案是日志采集方案,当然在存储和UI展现上会对接开源实现,没有特殊需求的情况下,也可以拥有一个完整的体验。



Rancher下的解决方案

如上面图中所示,日志存储和UI展现可以直接使用ElasticSearch & Kibana,日志采集方面如之前所分析,需要对接两种采集模式,所以这部分采用Fluentd & Logging Helper的组合,Fluentd是很通用的日志采集程序,拥有优异的性能,相对Logstash来说同等压力下,其内存消耗要少很多。Logging Helper是可以理解微Fluentd的助手,它可以识别容器内的日志卷文件,通知Fluentd进行采集。此外,由于要保证Dokcer和Rancher体验的完整性,在Docker Log Driver的选型上支持json-file和journald,其原因:一是json-file和journald相对来说比较常用;二是这两种驱动下,docker logs依然可以有内容输出,保证了体验的完整性。

下面开始说明,整个方案的部署过程。先用一张图来描述整体的部署结构,如下:



总共划分三个ENV,其中一个ENV部署ES & Kibana,另外两个ENV分别添加json-file驱动的主机和journald驱动的主机。详细部署过程如下:

创建三个ENV,使用Cattle引擎。设置Logging Catalog方便部署,在Admin–Settings页面中添加Catalog,地址为:https://github.com/niusmallnan/rancher-logging-catalog.git



进入ES-Kibana ENV中,部署ElasticSearch & Kibana,这两个应用在Community Catalog中均可以找到,部署非常简单,需要注意的是,建议选择Elasticsearch 2.x,Kibana中的Elasicsearch Source选择elasticseach-clients:



分配两台主机并安装Docker,其中Log Driver分别选择json-file和journald,并将主机添加到各自的ENV中。 在这两个ENV中添加External Link指向之前部署的Elasticsearch地址:



然后在Jsonfile & Journald ENV中添加Rancher Logging应用,打开对应的catalog,ES link指向刚才设定的External link, 其中Volume Pattern是日志卷的匹配模式,File Pattern是日志卷内的日志文件匹配模式:



以上部署完成之后,部署一些应用并产生一些访问日志,就可以在Kibana的界面中看到:



若要使用日志卷方式,则需要在service启动的时候配置volume,volume name需要匹配之前设定的Volume Pattern:



秉承一切开源的原则,相关实现可以查看一下链接:

1. https://github.com/niusmallnan/rancher-fluentd-package
2. https://github.com/niusmallnan/logging-helper
3. https://github.com/niusmallnan/rancher-logging-catalog

总结

通过Fluentd我们可以对接很多第三方日志存储体系,但是Fluentd自身并不能完成日志采集的所有场景,所以非常需要Logging Helper的帮助。通过Logging Helper可以定制出一些额外采集规则,比如可以过滤某些容器日志等等。当然真正大规模生产环境日志平台,其实是对整个运维体系的考验, 单纯靠开源程序的组合并不能真正解决问题。

原文来源:Rancher Labs

Docker监控及日志采集神器

Rancher 发表了文章 • 1 个评论 • 5034 次浏览 • 2017-01-24 09:27 • 来自相关话题

由Rancher社区维护的应用商店最近迎来了两个明星项目——SPM 和 Logsene,来自Sematext的监控与日志工具。如果你已经熟悉Logstash,Kibana,Prometheus,Grafana这些监控或日志解决方案,那么请认真阅读本文,它将向你 ...查看全部
由Rancher社区维护的应用商店最近迎来了两个明星项目——SPM 和 Logsene,来自Sematext的监控与日志工具。如果你已经熟悉Logstash,Kibana,Prometheus,Grafana这些监控或日志解决方案,那么请认真阅读本文,它将向你展示SPM和Logsene为Rancher用户带来了什么样的功能,和其它解决方案有着什么样的差异。

#接触Sematext Docker Agent

Sematext Docker Agent是一个时下Docker原生的监控及日志采集代理(Agent)程序。它在每一个Docker宿主机运行一个非常小的容器,用以为所有集群节点以及这些节点上的容器采集日志、系统指标与事件。Agent代理程序监听所有Rancher管理的节点,在部署Sematext Docker Agent后,所有的日志、Docker事件、各项指标都能被外部所访问。

这将变得很有价值,为什么呢?因为它意味着你不再需要耗费几个小时甚至好几天时间去弄明白究竟需要采集哪些数据或如何将它们图表化。还有,你不需要花资源来维护你自己的日志监控体系,你的Docker系统指标及事件都会输出给SPM 而日志将输出给Logsene(SPM是一个应用程序性能监控服务,它支持与诸多平台进行集成,这当然也包括Docker,而Logsene 是一个日志管理服务,一个托管于Rancher的ELK应用栈,它能很好的和Kibana和Grafana一并工作)




#DevOps工具对比

有一些Docker日志与指标处理的开源工具供我们选择,比如cAdvisor以及Logspout。遗憾的是,这些工具都不具备足够的综合能力。一种解决办法是集成一系列工具来达成目标,可是这样的后果是把体系带向“Franken-monitoring(指技术大杂烩,各个组件并不能按承诺的功能正常运行)”的方向,用户将因此而背负沉重的技术债,也没有人会愿意解决这种复杂的故障。

因此,另一种解决办法像Sematext Docker Agent这样的工具,则只是将cAdvisor和Logspout进行了结合,其功能尤其关注日志管理,比如格式检查,日志语法分析,数据改进(Geo-IP地址地理位置信息,元数据标签等)以及日志路由。

#通过Rancher Catalog配置Sematext Docker Agent

在Rancher平台设置Sematext Docker Agent,你只需要选择合适的catalog模板即可(在Rancher的社区Catalog条目下查找“Sematext” )。我们来快速的浏览一下Sematex提供了哪些功能?如何在Rancher平台对其进行设置?

Docker Compose及Kubernetes自动日志标签

所有的日志均被加上了元数据标签,这包含了对Docker/Rancher Compose项目及Kubernetes的支持:

针对Docker Container

- 容器ID
- 容器名
- 镜像名


针对Docker/Rancher Compose

- 服务名
- 项目名
- 容器数(如果你设置了Scale=N)

针对Kubernetes

请注意Kubernetes容器的日志和其它Docker容器的日志并没有什么很大的不同,然而Kubernetes用户需要访问已部署的pods的日志,因此,为日志搜索而抓取Kubernetes特有的信息变得非常有用,例如:

- 命名空间
- Pod名称
- 容器名称
- Kubernetes UID

诀窍:如需启用Kubernetes标签,请设置Kubernetes=1



#日志路由

对于较为庞大的部署,你也许需要针对不同租户或应用对日志进行索引,将其输出到不同的路径或Logsene应用处理(这样你也可以区分不同的用户对不同日志的访问权)。

我们使这个变得非常简单:为你的容器简单地添加一个Docker标签,或设置LOGSENE_TOKEN环境变量(LOGSENE_TOKEN=your app token),于是Sematext Docker Agent会将日志发送至正确的索引项!用这种方式你完全不需要一个中心配置文件来映射容器和索引项/令牌,于是日志路由变得非常灵活,动态与弹性化。

#集成的日志语法分析器

日志的处理基于Docker API以及一个叫做logagent-js的库,该项目被Sematext所开源。这个分析框架包含了日志格式检测和分析标准正式Docker容器所使用的不同日志格式的模式:

- Web服务器,例如Nginx、Apache httpd或其它使用常见Web服务器日志格式
- 搜索引擎,类似Elasticsearch和Solr
- 消息队列,类似Apache Kafaka及nsq.io
- 数据库,类似MongoDB, HBase, MySQL
- 检测JSON日志格式,通常被Node.js程序所使用,例如bunyan和winston日志框架

提示: 如果要创建自定义模式,请在Rancher Catalog模板里把它们添加到叫做LOGAGENT_PATTERNS的字段里。



#自动的容器日志Geo-IP增强项

从Docker容器之外获取到经过采集运送并分析后的日志已经节约了大量的时间,但是有一些应用日志需要从其它数据源获取额外的增强信息。一个常见的案例是增强Web Server的日志信息(或者说任意包含IP地址信息的日志),为日志中的IP地址提供其地理位置信息。

Sematext Docker Agent 支持Geo-IP enrichment of docker logs。它使用Maxmind Geo-IP轻量数据库,它能为你定期的提供更新信息,无需停止容器或为其挂载包含Geo-IP数据库的新卷,或任何其它手动操作。

诀窍: 如果需要开启Geo-IP增强功能,请设置环境变量GEOIP_ENABLED=true。



#过滤容器日志

在某些场景,我们只需要收集重要应用的日志而忽略掉那些较低优先级的或较为嘈杂的服务日志(例如那些频繁的清理工作)。这样我们可以使用白名单或黑名单(针对容器名或镜像名)来处理这些容器即可,其设置采用正则表达式匹配相应的元数据字段。




#如何使用Sematext Catalog项目

在Rancher的UI里,进入社区的Catalog项目列表,搜索关键字“sematext”、“monitoring”或“logs”即可。



点击“View Details”,在“Configuration Options”选项里输入SPM和Logsene App的tokens。你可以从这里进行注册并创建你的SPM和Logsene应用,然后即可获取这些访问令牌(tokens)。如果你的Rancher集群运行在防火墙(代理)之后, 你需要在HTTPS_PROXY或 HTTP_PROXY环境变量处填写proxy URL。如果你在这个集群里同时也运行了Kubernetes,请选择KUBERNETES=1。

如果你想收集所有的日志,不要填写任何容器或镜像名的过滤值,直接点击“Launch”即可。





#总结

我们希望这篇对Rancher平台中Sematext Docker Agent的介绍,能帮助你在开始对Docker进行监控与日志处理时,不用采用大杂烩的繁琐模式。该项目完整的配置参数可从Github获得参考。 我们相信新的Catalog模板已经能覆盖最常用的选项,如果你发现一些重要项目缺失,请将其提交至Rancher community catalog(提交issue或是pull request)。结合Rancher试用一下Sematext Docker Agent 吧,所有服务将被轻松接管,你将就此高枕无忧。Rancher Community Catalog让日志监控系统能瞬间设置并运行起来,一切都变得如此容易。


原文来源:Rancher Labs
> 原文作者:Stefan Thies
> 译者:彭攀(Alan Peng),Rancher中国社区技术专家委员会成员。现为睿云智合项目交付团队技术负责人。

DockOne微信分享( 一零二):基于容器的日志管理实践

Dataman数人科技 发表了文章 • 1 个评论 • 4378 次浏览 • 2017-01-06 16:15 • 来自相关话题

【编者的话】业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。 20 ...查看全部
【编者的话】业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。

2013年以来Docker迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控、日志、网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验。
# 基于ELK的日志管理系统架构
日志收集是大数据的基础,业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行分析处理;高可用性,高可靠性以及可扩展性是日志收集系统的必备要素。

ELK是目前较流行的日志一体化解决方案,提供日志收集、处理、存储、搜索、展示等功能。容器标准输出日志常用的查询方式是通过Docker命令 docker logs containerid来查看,容器内日志受容器隔离性影响不便于收集,因此当面对大型系统,用单一命令管理日志是不可行的,需要一个对于容器日志统一检索管理的方案。基于ELK实践了一套容器日志管理系统,架构如下:
1.png

# 日志采集
传统的日志采集有较成熟的解决方案,如Flume、Logstash等,但传统的采集方案不适用于容器日志。Docker本身提供了LogDriver功能,可以利用不同的driver把日志输出到不同地方,LogDriver具体有以下几种:

* None(将日志设置成不再输出)
* json-file(Docker默认的LogDriver,将日志以JSON文件的方式存储在本地)
* Syslog(标准输出日志可通过该方式传输)
* Journal
* SELF
* Fluent
* awslogs
* Splunk
* etwLogs
* gcplogs

对于这些LogDriver就不一一详细介绍了,大家有兴趣可以去Docker官网查看。可见Docker对日志提供了较为丰富的处理方式,供选择的还有优秀的开源项目Logspout等,然而这并不能满足所有的使用场景。

容器的标准输出日志可从以上驱动中选择,由于大多数用户选择标准化输出日志,故Docker没有提供采集功能,如果将日志内的文件挂载出来进行采集,多个实例同名日志则会无法区分,容器内文件日志处理、错误日志多行处理等问题时有发生,若想标准输出日志和容器内文件日志兼得,则需自己动手丰衣足食,以下为数人云日志采集系统实践。
##1. 标准输出日志
针对Marathon + Mesos环境开发了一套日志采集工具,Docker的标准输出日志json-file默认持久化在本地上,Mesos对于标准输出日志也存了一份在Sandbox下:
2.png

因此标准输出日志也可以通过Mesos文件的方式进行采集。
##2. 容器内文件日志
平台支持的文件存储是Overlay,避免了许多复杂环境的处理。关于Overlay盗用一张图:
3.jpg

容器的存储驱动运用写时复制(Copy On Write),Overlay主要分为lower和upper, 当需要修改一个文件时,使用CoW将文件从只读的Lower层复制到可写层Upper层进行修改,在Docker中,底部的只读层是image,可写层是Container,因此容器内日志在宿主机上通过Upper的文件系统可找到,例如在容器内的/var/log/test.log中写一个test字符,如图:
4.png

同理,无论是标注输出的日志还是容器内文件日志,都可以通过文件的方式进行处理,也可以同时把json-file关闭,以减轻Docker本身的压力。
##3. 自研日志采集工具
基于上述方式开发了一款日志采集工具,对日志进行统一收集管理,日志通过TCP把JSON格式化的日志输出到Logstash,包括应用ID,容器Name,容器ID,TaskID等,当然开发的过程中也遇到许多问题,如断点续传和错误日志多行处理等功能,这其中参考了Filebeat(Go语言开发)对于日志处理的方式,个人认为如果是对于传统文件日志处理,Filebeat是不错的选择,日志采集功能第一步支持:

* 容器标准输出日志采集
* 容器内文件日志采集,支持同时采集多个文件
* 断点续传 (如果Agent崩溃,从上次offset采集)
* 多行日志合并 (如:多行错误日志合并)
* 日志文件异常处理 (如:日志被rotate可以重新采集)
* TCP传输
* --add-env --add-label标签,可以通过指定命令把container的env或者label加到日志数据里,如(--add-env hostname=HOST --add-env test=ENV_NAME1 --add-label tlabel=label_name)
* Prometheus指标数据

日志处理需要提供快速的数据处理能力,在开发过程中遇到了性能问题,CPU占用非常高,针对该问题对程序作调优,使用Golang内置的包net/http/pprof,对Golang程序调优很好用,可将程序中每个函数占用CPU内存的比例通过生成SVG的方式直观的反映出来,如图:
5.jpg

Golang内置包encoding/json json的序列化、正则、反射、字节转字符串对于资源的消耗也比较高,可针对以上几方面以及程序本身进行调整。
# 日志存储后端架构
日志存储功能有Logstash、Heka、Fluentd等方案,Logstash基于R uby,支持功能丰富,但性能方面诟病较多;Heka基于Go,性能方面比Logstash好很多,不过Heka好像已经不维护了。综合考虑社区活跃度、迭代速度以及稳定性方面最终选择了Logstash,实际应用过程中比较重要的参数如下:

* --pipeline-workers (命令行参数)
* --pipeline-batch-size (命令行参数)
* LS_HEAP_SIZE=${LS_HEAP_SIZE} (根据自己的实际情况填写,可以写到环境变量活着命令行参数里面)
* workers => 8(根据自己实际情况,一般等于CPU数,配置文件参数)
* flush_size => 3000(根据自己的实际情况测试)

以上参数仅供参考,可根据实际环境进行调试。如果日志量较大,为了确保架构的稳定性,可以在中间加一层消息队列,比较常用的有Kafka、Redis等,相信大家对这方面应用比较多,不再赘述。

ES应该是索引存储的不二选择,整个架构的缓解包括ES通过Docker的方式部署,压测时用Marvel对ES的索引方式监控等,网上有很多调优资料,可自行实验。日志的展示是通过自己定制的,Kibana本身的功能比较强大的同时也略微有些学习成本,最终客户想要的是很简单的东西。

压测工具选择的是分布式压测工具Tsung,通过压测一个应用产生日志然后通过Log-Agent对日志进行采集,模拟真实环境日志采集。
# 日志告警
日志处理中,关键字报警是一个重要功能,对于监控报警主要用Prometheus + Alertmanager实现。应用运行过程中,根据日志关键字告警部的应用场景,从Logstash部分对日志做分流(具体方案可以看上面图的报警部分),自研grok_export对日志进行过滤分析生成Prometheus格式的数据,然后从Prometheus配置报警策略通过alertmanager报警。Log-Agent本身也支持Prometheus数据,Prometheus通过特定的规则查看日志的统计信息。

* Prometheus:
Prometheus是开源的监控告警系统,通过pull的方式采集时间序列,以及用http传输,数据存储在本地,支持丰富的查询语法和简单的Dashboard展示。

* Alertmanager:
Alertmanager作为Prometheus的组件,所有达到阀值的时间都通过Alertmanager报警,Alertmanager支持非常强大的告警功能,包括http、email通知,以及静默重复报警屏蔽等功能。

以上是数人云在实践容器日志系统过程中遇到的问题,更高层次的应用包括容器日志分析等,还有待继续挖掘和填坑,欢迎大家提出建议,一起交流。
#Q&A
Q:Overlay 是没有实现 inotify 接口的,是咋获取文件日志增量数据的?

A:通过循环读取文件的方式,记录文件offset。



Q:既然主要框架是 ELK,采集端不直接用 Filebeat 是因为 Filebeat 有局限性吗?

A:Filebeat没有满足我们产品基于Docker的需求,等于上面加了Docker的逻辑。



Q:自研的日志系统,打出来的每条日志格式都是规定好的吗?开发中每个人都要按这个规范来做吗?不管是什么级别的日志?

A:其实并没有,但是如果是内部使用,能规约好当然更好,可以更方便的处理,而且可以做更细粒度的分析。



Q:日志收集有做分析展示处理吗?用什么处理的。

A:对于日志内容的分析还没做,例如Nginx请求日志还是有分析意义的。



Q:采集方面有考虑直接使用系统的Syslog和Logrotate吗?

A:用过Syslog后来因为容器内的文件日志需求重新开发的。



以上内容根据2017年1月5日晚微信群分享内容整理。分享人郭已钦,数人云研发工程师。早期从事Java&JavaScript开发,爬虫大数据开发,之后开始写Go,参与开源容器管理工具Crane的研发与维护,目前在数人云做云平台研发工作。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

容器内应用日志收集方案

Rancher 发表了文章 • 1 个评论 • 2955 次浏览 • 2016-12-16 09:16 • 来自相关话题

原文来源:Rancher Labs 容器化应用日志收集挑战 应用日志的收集、分析和监控是日常运维工作重要的部分,妥善地处理应用日志收集往往是应用容器化重要的一个课题。 Docker ...查看全部
原文来源:Rancher Labs

容器化应用日志收集挑战

应用日志的收集、分析和监控是日常运维工作重要的部分,妥善地处理应用日志收集往往是应用容器化重要的一个课题。

Docker处理日志的方法是通过docker engine捕捉每一个容器进程的STDOUT和STDERR,通过为contrainer制定不同log driver 来实现容器日志的收集,缺省json-file log driver是将容器的STDOUT/STDERR 输出保存在磁盘上,然后用户就能使用docker logs 来进行查询。

在部署一个传统的应用的时候,应用程序记录日志的方式通常记录到文件里, 一般(但不一定)会记录到/var/log目录下。应用容器化后,不同于以往将所有日志放在主机系统的统一位置,日志分散在很多不同容器的相互隔离的环境中。

如何收集应用写在容器内日志记录,有以下挑战:

1) 资源消耗
如果在每个容器运行一个日志收集进程, 比如logstatsh/fluentd 这类的日志工具,在主机容器密度高的时候,logstatsh/fluentd这类日志采集工具会消耗大量的系统资源。上面这种方法是最简单直观的,也是最消耗资源的。

2) 应用侵入
一些传统应用,特别是legacy 系统,写日志机制往往是没法配置和更改的,包括应用日志的格式,存放地址等等。日志采集机制,要尽量避免要求修改应用。

3) 日志来源识别
采用统一应用日志收集方案,日志分散在很多不同容器的相互隔离的环境中,需要解决日志的来源识别问题。

日志来源识别的功能借助了rancher平台为container_name的命名的规则特性,可以做到即使一个容器在运行过程中被调度到另外一台主机,也可以识别日志来源。

容器化应用日志收集方案

下面是我们设计的一个低资源资源消耗、无应用侵入、可以清楚识别日志来源的统一日志收集方案,该方案已经在睿云智合的客户有成功实施案例。



在该方案中,会在每个host 部署一个wise2c-logger,wise2C会listen docker engine的event,当有新容器创建和销毁时,会去判断是否有和日志相关的local volume 被创建或者销毁了,根据lables,wise2c-logger 会动态配置logstatsh的input、filter 和output,实现应用日志的收集和分发。

1) 应用如何配置
应用容器化时候,需要在为应用容器挂载一个专门写有日志的volume,为了区别该volume 和容器其它数据volume,我们把该volume 定义在容器中,通过volume_from 指令share 给应用容器,下面是一个例子:demo应用的docker-compose file



web-data 容器使用一个local volume,mount到/var/log目录(也可以是其它目录),在web-data中定义了几个标签, io.wise2c.logtype说明这个容器中包含了日志目录,标签里面的值elasticsearch、kafka可以用于指明log的output或者过滤条件等。

那么我们现在来看下wiselogger大致的工作流程:



监听新的日志容器->获取日志容器的type和本地目录->生成新的logstash配置:

1)wise2c-looger 侦听docker events 事件, 检查是否有一个日志容器创建或者被销毁;

2)当日志容器被创建后(通过container label 判断), inspect 容器的volume 在主机的path;

3)重新配置wise2c-logger 内置的logstatsh 的配置文件,设置新的input, filter 和output 规则。



这里是把wise2c-logger在rancher平台上做成catalog需要的docker-compose.yml的截图,大家可以配合上面的流程描述一起看一下。

优化

目前我们还在对Wise2C-logger 作进一步的优化:

1)收集容器的STDOUT/STDERR日志
特别是对default 使用json-file driver的容器,通过扫描容器主机的json-file 目录,实现容器STDIN/STDERR日志的收集。

2)更多的内置日志收集方案
目前内置缺省使用logstatsh 作日志的收集,和过滤和一些简单的转码逻辑。未来wise2C-logger 可以支持一些更轻量级的日志收集方案,比如fluentd、filebeat等。

Q & A

Q:有没有做过性能测试?我这边模块的日志吞吐量比较大。比如在多少量级的日志输出量基础上,主要为logger模块预留多少系统资源,保证其正常稳定工作?
A:没有做过很强的压力,但是我们现在正常使用倒没碰上过性能上的瓶颈。我们现在没有对logger做资源限制,但是能占用300~400M内存,因为有logstash的原因。

Q:「生成日志容器」是指每个应用容器要对应一个日志容器?这样资源消耗不会更大吗?k8s那种日志采集性能消耗会比这样每个应用容器对应一个日志容器高么?
A:是指每个应用容器对应一个日志容器。虽然每个应用有一个日志容器,但是,日志容器是start once的,不会占用运行时资源。

Q:你说的start once是什么意思?我说占资源是大量日志来的时候,那么多日志容器要消耗大量io的吧,CPU使用率会上升,不会影响应用容器使用CPU么?
A:不会,日志容器只生成一下,不会持续运行。

Q:怎么去监听local volume?
A:可以监听文件目录,也可以定时请求docker daemon。

Q:直接用syslog driver,能做到对应用无侵入么?
A:启动容器的时候 注明使用Syslog driver的参数即可,这样几乎没有额外资源占用。

Q:这种方案是不是要保证应用容器日志要输出到/var/log下啊?
A:不是,可以随意定义,logstah可以抓syslog。

Q:syslog driver能收集容器内的日志文件么?容器内不同流向的日志能区分么?
A:容器内应用的本地日志syslog可以收集,分流同样可以完成,但是容器内的本地日志这个我个人觉得跟容器环境下的应用无本地化、无状态化相悖吧。

Q:最后你说到,重新配置logstash中配置文件,看上去感觉你又是通过wiselog这个容器去采集所有日志的?只不过是动态配置logstash里面参数。
A:是的,现在收集工作是logstash来完成的,单纯的文件收集,可选的方案还挺多的,也没有必要再造轮子了。

Q:那这个方案其实有个疑问,为什么不学k8s那种,直接固定那目录,通过正则表达式去采集日志文件,而要动态这么做?有什么好处吗?目前我感觉这两套方案几乎一样。
A:为了减少对应用的侵入。因为很多用户的现有系统不能再修改了,这样做也是为了减少用户现有程序的修改,为了最重要的“兼容现有”。

Q:除了kibana还有没别的可视化方案?
A:针对es来说,还没有别的更好的方案。

Q:如果是挂载log目录,logstash就可以去宿主机收集了,还需要别的插件做什么?
A:通过容器可以识别出来这个应用的业务上的逻辑,可以拿到service名称。

Q:有的应用输出的log名都是一样的,不会有冲突吗,比如我启动2个容器在一个宿主机上,都往xx.log里写入会有问题。
A:不会,给每一个应用容器配一个日志卷容器就可以解决这个问题。这个问题也是我们出方案时一个棘手的问题。所以这个方案的一个好处就是,每一个应用的都可以随意设置日志目录,不用考虑和别的应用冲突,也不会和同宿主机同一应用冲突。

Q:上次听别人说全部把日志扔到标准输出里,不知道靠谱不?
A:有人报过这种处理方式,日志量大时,docker daemon会崩溃。

如何在 Rancher 中统一管理容器日志

Rancher 发表了文章 • 1 个评论 • 2674 次浏览 • 2016-12-05 09:40 • 来自相关话题

原文来源:Rancher Labs 相信大家对于容器和 docker 这个概念并不陌生,很高兴的是 docker 为我们提供了多种log-driver。 我们在使用 docker ...查看全部
原文来源:Rancher Labs

相信大家对于容器和 docker 这个概念并不陌生,很高兴的是 docker 为我们提供了多种log-driver。



我们在使用 docker 处理日志的时候多数是采用 docker logs 命令,因为 docker 默认采用的 log-driver 是 json-file,所以 docker 会捕捉每一个容器进程 STDOUTS 和 STDERR,保存在磁盘文件.json.log 中供 docker logs 命令查询。



上述方式如果用于开发过程中的调试工作,是种快速且不错的方案,但是如果面对大规模应用部署的环境下那么日志的跟踪与调试带来的困扰显而易见,因此我们需要一个统一集中的容器日志收集与展示平台。

对于容器日志收集与展示,syslog + rsyslog + ELK(ElasticSearch、Logstash、Kibana)是一个不错的技术方案,我将简单介绍下为什么我们选用这种方案。

Syslog 是一种 RFC 协议,与平台无关,且是 UNIX 标准的日志解决方案,集成度良好。rsyslog 顾名思义是 remote 的意思,使 syslog 具备收集远端日志的功能,由于 logstash 采用 java 和 jruby开发,所以 logstash 文件库中可以加入 windows 日志文件。而 logspout 暂不支持容器-t(tty) 启动。

我们庆幸的是 Rancher 的 Catalog 真的很强大,Rancher Catalog 已经为我们提供了 ELK 的Catalog,下面我将给出 ELK 在 Rancher 中的部署视图,并简单介绍下视图中每个组件都是干什么的。



- logstash-collector:用于接收 docker container 发送过来的日志信息,并将日志信息发送到redis 队列中。在 rancher 中默认开启 TCP:6000 UDP:5000 端口用于侦听发送过来的日志报文。
- redis:日志消息队列。
- logstash-indexer:用于接收redis中未处理的日志信息,然后将该日志消息发送到elasticsearsh中进行存储及搜索分析。
- kopf:elasticsearch 的一款第三方插件,提供一个简单的管理员 web 界面。
- elasticsearch-clients:用于处理路由请求,协调数据节点与主节点。
- elasticsearch-master:用于集群操作相关的内容。
- elasticsearch-datanode: 用于存储索引数据的节点。

上述部署视图中说好的 Kibana 哪儿去了?

因为我们有自己的日志展现平台,所以这里去掉了 kibana,如果你想在 Rancher 中使用 Kibana做日志前端展现,那么很简单,只需要利用 Rancher 的 Catalog,service link:Rancher 环境中上述已经部署好的 elasticsearch-client 即可。

至此,在 Rancher 中如何部署一套完整 ELK 系统已经介绍完了,下面我将介绍如何将容器日志发送到 ELK 中。




为了完成上述的目标,我们还需要做一些准备工作,那就是需要一个运行 rsyslog 的容器。如果你不想基于 alpine 去制作 rsyslog 镜像,那么可以使用 panoptix/rsyslog 这个镜像。

下面就是关键的一步:如何让 rsyslog 发送日志到 logstash 中。

上述 rsyslog 容器启动好之后我们需要告知 rsyslog,目的接收端 logstash 的地址。过程很简单,需要在容器中/etc/rsyslog.d/ 目录下建立一个文件 60-logstash.conf



:programname, contains, “docker”的意思是过滤日志,只有 Properties 中 key 为 programname,value 包含 docker 字样的日志才会被发送给 logstash

`.`@@logstash-collector:6000;json-template 是所有用户的所有日志通过 tcp 传输到logstash-collector 的 6000 端口并且日志使用 json-template 格式化。

同样我们需要建立 01-json-template.conf,property 的 key 值我们可以通过 rsyslog 官网获取。



下面我将介绍 rsyslog 如何收集容器日志。

首先我们需要修改我们的应用容器 log-driver 为 syslog(可以通过 rancher-ui 或者rancher-compose)来完成。

其次我们需要设置我们日志接收端 rsyslog 地址,可以通过 log_opt 指定syslog-address:hostname:tcp_port 来完成。

log_opt 可以指定许多 syslog 支持的选项比如 facility 等,在此不一一列举。目前日志显的杂乱无序。如何去按照 container 或者 stack 或者 service 去区分日志呢?

syslog 的 tag 属性为我们支持了自定义的标签,通过打 tag 的方式我们可以细粒度的自行切分日志。

Rancher 对 docker 的亲和性极大程度的为我们提供了遍历。我们可以通过 go templage 语法去获取 rancher 环境下容器的特征值从而协助我们切分日志信息。



OK,现在我们再去查看 kibana 发现我们的容器日志已经展示在这里了。



最后我们可以按照 rancher catalog 规范,制作一键部署应用。

Docker 1.13.0 详细更新日志

田浩浩 发表了文章 • 0 个评论 • 6358 次浏览 • 2016-11-16 16:49 • 来自相关话题

【编者的话】Docker发布1.13.0版本,此次版本更新内容较多,以下为该版本具体的变更。 ##构建 * 添加在构建时可以指定镜像用作高速缓存源的功能。 这些镜像不需要有本地父链还可以从其他registri ...查看全部
【编者的话】Docker发布1.13.0版本,此次版本更新内容较多,以下为该版本具体的变更。

##构建

* 添加在构建时可以指定镜像用作高速缓存源的功能。 这些镜像不需要有本地父链还可以从其他registries拉取 #26839
* (试验功能)添加选项用以在成功构建之后,将镜像层级压缩到`FROM`镜像 #22641
* 修复`Dockerfile`解析空行后的逸出 #24725
* 在`docker build`时添加步数 #24978
* 在镜像构建时添加支持压缩构建 #25837
* 在`docker build`中添加`--network`参数 #27702
* 修复了在`docker build`以及`docker run`时`--label`参数的不一致行为 #26027
* 修复了当使用overlay储存驱动时镜像层级的不一致 #27209
* 现在允许使用不用的构建参数。将显示警告信息而不是错误和失败的构建 #27412
* 修复了Windows上的构建缓存问题 #27805

##贡献

* 为`Ubuntu Xenial on PPC64`添加支持构建docker debs #23438
* 为` Ubuntu Xenial on s390x`添加支持构建docker debs #26104
* 为`VMWare Photon OS`添加`RPM`构建 #24116
* 在`tgz`添加docker命令补全 #27735
* 更新安装脚本允许在中国使用镜像安装 #27005
* 为`Ubuntu 16.10 Yakkety Yak`添加`DEB`构建 #27993
* 为`Fedora 25`添加`RPM`构建 #28222

##发行版

* 更新`notary`依赖版本到0.4.2(完整的更新日志在这里#27074
* 当不同的用户将相同的层级推送到验证`registry`时, 避免不必要的blob上传 #26564
* 允许外部存储用于`registry`的凭据 #26354

##日志

* 标准化所有的日志记录驱动程序的默认日志记录标记值 #22911
* 在记录长日志时,改善了性能和内存的使用 #22982
* 为windows启用syslog驱动程序 #25736
* 添加Logentries驱动程序 #27471
* 更新AWS日志驱动程序来支持标记 #27707
* 为` fluentd`添加支持`Unix socket` #26088
* 在Windows上启用`fluentd`日志驱动程序 #28189
* 当用作`journald`字段名称时, 清理docker标签 #23725

##网络

* 添加`--attachable`支持用于启用`docker run`在swarm模式的overlay网络上运行 #25962
* 添加在`docker service create`时使用`--port`选项来支持services中host端口的PublishMode #27917
* 为Windows server 2016添加支持overlay网络驱动 (需要即将到来的ws2016更新) #28182
* 修改默认的`FORWARD`政策为`DROP` #28257
* 在windows上添加支持对预定义网络指定静态IP #22208
* 修复了在`docker run`使用IPv6地址时`--publish`参数失灵的问题#27860
* 修复了`inspect`网络是显示带有mask的gateway #25564
* 修复了在桥接网络中多个地址可能引起`--fixed-cidr` 没有正确的地址 #26659
* 在`docker network inspect`中添加创建时间戳 #26130
* 在`docker network inspect`swarm overlay网络时显示对等节点 #28078
* 为服务VIP地址启用ping #28019

##插件

* 插件功能正式上线 #28226
* 在`docker plugin remove`添加`--force`参数 #25096
* 支持动态重新加载授权插件 #22770
* 在`docker plugin ls`添加描述 #25556
* 为`docker plugin inspect`添加`-f` / `--format`参数 #25990
* 添加`docker plugin create`命令 #28164
* 发送请求的TLS同等证书给授权插件 #27383
* 在swarm模式中支持全局范围网络以及`ipam`插件 #27287

##远程API(v1.25) 以及 客户端

* 支持从一个Compose文件用于`docker stack deploy` #27998
* (试验功能) 实现checkpoint以及restore #22049
* 为`docker info`添加`--format`参数 #23808
* 从`docker volume create`移除`--name`参数  #23830
* 添加`docker stack ls` #23886
* 为`docker ps`添加新过滤`is-task` #24411
* 为`docker service create`添加`--env-file`参数 #24844
* 为`docker stats`添加`--format`参数 #24987
* 在swarm模式中使`docker node ps`模式是`self` #25214
* 在`docker service create`添加`--group` #25317
* 在service/node/stack ps输出中添加`--no-trunc` #25337
* 为`ContainerAttachOptions`添加日志用于go客户端可以请求检索容器日志做为attach进程的一部分 #26718
* 允许客户端访问旧版本服务 #27745
* 告知用户客户端移除容器正在进行中 #26074
* 为/info添加`Isolation` #26255
* 为/info添加`userns` #27840
* 在service终端请求时不允许同时有多个模式 #26643
* 为/containers/create API添加更为详细安全的指定挂载的功能 #22373
* 为`network ls`以及`volume ls`添加`--format` #23475
* 允许最高级别的`docker inspect`检阅任何类型资源 #23614
* 在`docker run`或`docker create`允许移除`--entrypoint` #23718
* 重构CLI命令:添加`docker image`以及`docker container` #26025
* 从`service ls`输出中移除`COMMAND`列 #28029
* 为`docker events`添加`--format` #26268
* 在`docker node ps`允许指定多个节点 #26299
* 在`docker images`输出中限制小数点两位 #26303
* 为`docker run`添加`--dns-option` #28186
* 为容器提交事件添加镜像ID #28128
* 为`docker info`添加外部二进制版本 #27955
* 在`docker info`输出中添加管理地址信息 #28042
* 为`docker images`添加新的引用过滤 #27872

##运行时

* 添加`--experimental`守护进程参数用于启用试验功能而非分开发布 #27223
* 添加`--shutdown-timeout`守护进程参数来指定默认超时时间(以秒计算)用于在守护进程退出之前优雅地停止容器 #23036
* 添加`--stop-timeout`来指定超时时间(以秒计算)为停止单个容器 #22566
* 添加`--userland-proxy-path`守护进程参数使其允许配置用户代理而不是在` $PATH`内硬编码`docker-proxy` #26882
* 在`dockerd`以及`docker run`添加`--init`参数用于使用tini 一个作为PID 1的zombie-reaping init进程 #26061 #28037
* 添加`--init-path`守护进程参数允许配置`docker-init`二进制路径 #26941
* 配置添加支持动态加载不安全的registry #22337
* 在Windows守护进程中添加支持storage-opt size #23391
* 改善`docker run --rm`的可靠性通过将其从客户端移动到守护进程 #20848
* 添加支持`--cpu-rt-period`以及`--cpu-rt-runtime`参数,在kernel中`CONFIG_RT_GROUP_SCHED`启用的情况下,允许容器运行在real-time threads #23430
* 允许并行地停止,暂停, 取消暂停 #24761 / #26778
* 为`overlay2`实现XFS quota #24771
* 在 `service tasks --filter`中修复了一些过滤问题 #24850
* 允许引擎在在用户namespace中运行 #25672
* 当使用devicemapper驱动程序时,修复了在设备延期移除与恢复设备之间的竞态条件 #23497
* 在Windows中添加`docker stats`支持 #25737
* 使用`--userns=host`时, 允许使用`--pid=host`以及`--net=host` #25771
* (试验功能) 添加metrics输出 #25820
* 修复了`docker stats`使用`NetworkDisabled=true`的问题  #25905
* 在Windows中添加`docker top`支持 #25891
* 记录`exec`进程的pid #27470
* 添加支持通过`getent`查找user/groups #27599
* 为系统资源管理添加新命令`docker system`还有`df`与`prune`子命令,以及`docker {container,image,volume,network} prune`子命令 #26108 #27525 / #27525
* 修复了使用devicemapper,通过设置xfs max_retries to 0 upon ENOSPC时,容器不能被停止或杀掉的问题  #26212
* 修复了使用devicemapper,`docker cp`未能复制容器volume目录到CentOS的问题 #28047
* 提升overlay(2)驱动程序 #27932
* 添加`--seccomp-profile`守护进程参数用于指定seccomp profile来覆盖默认的路径 #26276
* 修复了当守护进程设置`--default-ulimit`参数时,`docker inspect`的ulimits问题 #26405
* 在旧版本kernels上构建过程中,添加了overlay问题的解决方案 #28138
* 在`docker exec -t`添加`TERM`环境变量 #26461
* `--stop-signal`设置在`docker kill` #26464

##Swarm Mode

* 添加安全管理 #27794
* 在`docker service inspect --pretty`输出中显示终端模式  #26906
* 通过缩短在任务名字中的服务IDs, 使`docker service ps`输出更惬意 #28088
* `docker node ps`默认输出是当前节点 #25214
* 为`docker service ps`以及`docker node ps`添加`-a` / `--all`用于显示所有结果 #25983
* 为`service create`添加`--dns`, `--dns-opt`以及`--dns-search` #27567
* 为`docker service update`添加`--force` #27596
* 为`docker service ps`添加`-q` #27654
* 在`docker service ls`中显示全局service数量  #27710
* 从`docker service update`移除`--name`。这个标志仅用在`docker service create` #26988
* 修复了由于瞬态网络问题而导致的工作节点未能恢复的问题 #26646
* 添加支持健康检查的负载均衡与DNS记录 #27279
* 为`docker service create`添加`--hostname` #27857
* 为`docker service create/update`添加`--tty` #28076
* 管理者自动检测、储存以及暴露节点IP地址 #27910
* 为空闲管理者的keys和大量数据加密 #27967
* 为`docker service update`添加`--update-max-failure-ratio`, `--update-monitor`以及`--rollback`  #26421
* 修复了在`docker swarm init`上运行容器的地址自动发现问题 #26457
* (试验功能) 为查看service日志添加`docker service logs`命令 #28089
* 为`docker service create`以及`update` 通过摘要识别镜像 #28173
* 为`docker node rm --force`以及`docker swarm leave --force`添加简短(`-f`)标志  #28196
* 不要重新拉取镜像如果已经通过摘要识别到 #28265
* Windows添加支持swarm-mode  #27838

##Volume

* volumes添加支持标签 #21270
* 添加支持通过标签过滤volumes #25628
* 在`docker volume rm`添加`--force`标志用于强制清除已删除的volume的数据 #23436
* 加强`docker volume inspect`用于当创建volume时,显示所有已使用的选项 #26671
* 添加支持本地NFS volumes来解析主机名 #27329

##安全

* 修复了selinux 容器的volumes的标签问题 #23024
禁止`/sys/firmware/*`被apparmor访问 #26618

##弃用

* 弃用`docker daemon`命令。守护进程移动到了一个单独的二进制文件(`dockerd`),而且已经使用 #26834
* 弃用无版本的API #28208
* 从支持平台中移除Ubuntu 15.10 (Wily Werewolf)。Ubuntu 15.10使用期结束并且不会再收到更新 #27042
* 从支持平台中移除Fedora 22。Fedora 22使用期结束并且不会再收到更新 #27432
* 在`docker pull`中弃用`repo:shortid`语法 #27207
* 为overlay/overlay2储存驱动程序弃用没有d_type的文件系统  #27433
* 在`Dockerfile`中弃用MAINTAINER #25466
* 为`/images/json`弃用过滤参数 #27872

===========================

原文链接:Changelog - 1.13.0 (翻译:田浩浩

DockOne微信分享(一二四):轻松筹监控系统实现方案

jiadas 发表了文章 • 1 个评论 • 9292 次浏览 • 2017-06-10 14:55 • 来自相关话题

【编者的话】监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况。虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化。这样既可以更灵活的满足自身 ...查看全部
【编者的话】监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况。虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化。这样既可以更灵活的满足自身业务的监控需求,也可以为以后自建机房提供技术积累。通过以下7个方面来建设监控系统。

【3 天烧脑式 Docker 训练营 | 上海站】随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛。本次培训我们理论结合实践,从Docker应该场景、持续部署与交付、如何提升测试效率、存储、网络、监控、安全等角度进行。

WechatIMG21.jpeg

# 1 . 日志打印
完善的日志是实现监控的基础,如何打印日志关系到之后的日志过滤、存储以及分析。除了选择合适的日志库,还要满足一些日志打印的要求:

  • 日志风格:以key-value的field形式输出结构化的日志。
  • 输出时机: error日志一定都需要打印,info日志结合业务需求适当打印,日志只需要在业务层关注,model和util等不需要打印。
  • 输出格式:线上以json的格式打印日志,方便解析日志。线下为了方便查看,可以用自定义的format打印日志,线上和线下的日志格式通过etcd来控制。
  • 输出内容: 每一条日志都要携带logid、method、host和level,并且根据不同业务场景,需要携带不同业务的标识field,例如projectType、platform、payType等。
  • 用context来传递不同goroutine之间的共享信息。

# 2 . 日志切分
日志切分是运维层面的东西,不应该由日志库来承担日志切分的事情,因为Linux在日志切分上有很成熟的工具,不需要自己写码去重复实现。

目前对日志切分的需求只有2个:按天切分和删除切出来的多余日志。logrotate就能很好的满足这些需求,logrotate是基于cron来运行的,其脚本是/etc/cron.daily/logrotate,默认放在/etc/cron.daily下,每天执行一次。

有的时候程序异常或者请求激增会导致日志量暴增,有可能在短时间内打满整个磁盘。可以在logrotate的配置文件里加上maxsize来限制日志文件的大小,并且将logrotate的执行频率调高至每小时甚至每分钟,及时切分并删除超过rotate数量的日志,来防止异常情况下磁盘被打满的情况发生。

样例配置如下所示:
// logrotate config of sample
// rotate every day, and keep for 3 days
/var/log/sample.log {
daily
rotate 3
maxsize 1G
missingok
sharedscripts
postrotate
# 在切分时向程序发送SIGHUP信号
killall -SIGHUP bin_sample
endscript
}

业务程序只需要负责监听SIGHUP信号,收到该信号时再重新打开日志文件。
# 3 . 日志采集
从监控系统的角度来说,日志收集有2种方式:主动采集和被动接收,两种方式各有利弊。
##主动采集
优点:日志收集和业务程序分开,互不影响。

缺点:日志收集需要依赖额外的采集服务,过滤和存储可能还需要额外配置。
##被动接收
优点:业务程序直接将日志发送至存储,灵活性强,存储内容可在业务代码里控制。

缺点:日志存储不稳定的话会影响业务程序的正常运行;反之,日志量大的话也会压垮日志存储。

但是在建设监控系统初期,日志存储还不是很稳定的情况下,还是用主动采集的方式比较稳妥,不影响服务稳定性为主。
WechatIMG24.jpeg

Collectd功能确实很强大,它的tail插件也能满足从文件收集日志,但是tail插件配置比较复杂而且说明文档相较于Filebeat来说不是很详细。

Collectd的其他插件可以采集的数据确实很多,而且也有插件支持将数据发送到Logstash和InfluxDB,但是多数插件的功能我们用不到,而且Elastic Stack中的Beats也能够很好的收集系统参数等数据,而且跟ELK能很好的兼容。

所以在分别试用了Filebeat和Collectd这2个采集服务后,综合上述分析决定采用Filebeat来负责从日志文件中采集日志。如下所示,Filebeat的配置简单易懂:
filebeat:
spool_size: 1024 # 最大可以攒够 1024 条数据一起发送出去
idle_timeout: "5s" # 否则每 5 秒钟也得发送一次
registry_file: "registry" # 文件读取位置记录文件,会放在当前工作目录下。
config_dir: "path/to/configs/contains/many/yaml" # 如果配置过长,可以通过目录加载方式拆分配置
prospectors: # 有相同配置参数的可以归类为一个 prospector
-
fields:
log_source: "sample" # 类似 logstash 的 add_fields,此处的"log_source"用来标识该日志来源于哪个项目
paths:
- /var/log/system.log # 指明读取文件的位置
- /var/log/wifi.log
include_lines: ["^ERR", "^WARN"] # 只发送包含这些字样的日志
exclude_lines: ["^OK"] # 不发送包含这些字样的日志
-
document_type: "apache" # 定义写入 ES 时的 _type 值
ignore_older: "24h" # 超过 24 小时没更新内容的文件不再监听。
scan_frequency: "10s" # 每 10 秒钟扫描一次目录,更新通配符匹配上的文件列表
tail_files: false # 是否从文件末尾开始读取
harvester_buffer_size: 16384 # 实际读取文件时,每次读取 16384 字节
backoff: "1s" # 每 1 秒检测一次文件是否有新的一行内容需要读取
paths:
- "/var/log/apache/*" # 可以使用通配符
exclude_files: ["/var/log/apache/error.log"]
-
input_type: "stdin" # 除了 "log",还有 "stdin"
multiline: # 多行合并
pattern: '^[[:space:]]'
negate: false
match: after
output:
logstash:
hosts: ["localhost:5044"] # The Logstash hosts

Filebeat 发送的日志,会包含以下字段:

* beat.hostname beat 运行的主机名
* beat.name shipper 配置段设置的 name,如果没设置,等于 beat.hostname
* @timestamp 读取到该行内容的时间
* type 通过 document_type 设定的内容
* input_type 来自 "log" 还是 "stdin"
* source 具体的文件名全路径
* offset 该行日志的起始偏移量
* message 日志内容
* fields 添加的其他固定字段都存在这个对象里面

# 4 . 日志过滤
logstash.png

Logstash 自2009年诞生经过多年发展,已经是很成熟并且流行的日志处理框架。Logstash使用管道方式进行日志的搜集处理和输出。有点类似*NIX系统的管道命令 input | filter | output,input 执行完了会执行 filter,然后执行 output。在 Logstash 中,包括了三个阶段:输入input → 处理filter(不是必须的)→ 输出output。每个阶段都由很多的插件配合工作,比如 file、elasticsearch、redis 等等。每个阶段也可以指定多种方式,比如输出既可以输出到elasticsearch中,也可以指定到stdout在控制台打印。

Codec 是 Logstash 从 1.3.0 版开始新引入的概念(Codec 来自 Coder/decoder两个单词的首字母缩写)。在此之前,Logstash 只支持纯文本形式输入,然后以过滤器处理它。但现在,我们可以在输入 期处理不同类型的数据,这全是因为有 Codec 设置。所以,这里需要纠正之前的一个概念。Logstash 不只是一个 input | filter | output 的数据流,而是一个 input | decode | filter | encode | output 的数据流!Codec 就是用来 decode、encode 事件的。Codec 的引入,使得 Logstash 可以更好更方便的与其他有自定义数据格式的运维产品共存,比如 graphite、fluent、netflow、collectd,以及使用msgpack、json、edn 等通用数据格式的其他产品等。

Logstash 提供了非常多的插件(Input plugins、Output plugins、Filter plugins、Codec plugins),可以根据需求自行组合。其中 Filter 插件 Grok 是 Logstash 最重要的插件。Grok 通过正则表达式匹配日志内容,并将日志结构化,所以理论上只要正则掌握的够娴熟,就能解析任何形式的日志,非常适合用来解析第三方服务产生的非结构化日志。但是如果是自己写的服务,就没必要将日志输出成非结构的,增加写正则的负担,所以在上述日志打印一节中才规定线上的日志输出成json形式,方便 Logstash 解析,Logstash 提供 json 的 Filter 插件。

Logstash 的配置文件默认放在 /etc/logstash/conf.d 目录下,如果需要采集多个项目的日志,每个项目的 Logstash 配置可能不一样,那就会在 conf.d 里存放多个配置文件,以每个项目命名方便管理。但是这样会带来一个问题,因为 Logstash 会将所有配置文件合并为一个,即一条日志通过input进入到Logstash后,会经过每个配置文件里的filter和output插件,造成对日志错误的处理和输出。解决方式是在Filebeat的fileds配置项里增加区分不同项目的field,如果日志路径就能区分不同项目的话也可以不用额外加field,用 Filebeat 自带的source字段就可以,然后在每个项目对应的 Logstash 配置文件里通过IF标识项目,项目各自的日志进各自的配置,互不干扰。

下列配置示例是对一个sample服务产生的json日志,通过Filebeat采集,用json的Filter插件进行解析,并将结果输出到标准输出。
input {
beats {
port => "5044"
}
}
// The filter part of this file is commented out to indicate that it is
// optional.
filter {
if [beat] and [source] =~ "sample" {
json {
source => "message"
}
ruby {
code => "event.set('time',(Time.parse(event.get('time')).to_f*1000000).to_i)"
}
}
}
output {
if [beat] and [source] =~ "sample" {
stdout { codec => rubydebug }
}
}

# 5 . 日志存储
InfluxDB vs. Elasticsearch

根据 DB-ENGINES 的排名,InfluxDB和Elasticsearch在各自专攻的领域都是NO.1,InfluxDB统治Time Series DBMS,Elasticsearch制霸Search engine,关于它们的原理和使用,各自都有非常详细的文档和资料,这里就不再赘述。

在时序数据方面,InfluxDB表现强劲,Elasticsearch在主要的指标上均远落于下风:

数据写入:同时起4个进程写入8百64万条数据,Elasticsearch平均为 115,422 条/秒,InfluxDB平均 926,389 条/秒,写入速度是Elasticsearch的8倍。这种写入速度的差距随着数据量的增大保持相对一致。
elastic-write-768x518.png

磁盘存储:存储相同的8百64万条数据,使用默认配置的Elasticsearch需要2.1G,使用针对时序数据配置的Elasticsearch需要517MB,而InfluxDB只需要127MB,压缩率分别是前两者的16倍和4倍。
elastic-compression.png

数据查询:在24h的数据集(8百64万条数据)里随机查询1个小时内的数据,按1分钟的时间间隔聚合,Elasticsearch和InfluxDB分别单进程执行1000次这种查询,算耗时的平均值。Elasticsearch耗时4.98ms(201次查询/秒),InfluxDB耗时1.26ms(794次查询/秒),查询速度是Elasticsearch的4倍。随着数据集的增大,查询速度之间的差距逐渐拉大,最大相差10倍之多。而且随着执行查询的进程数增加,InfluxDB的查询速度增幅显著,而且在不同数据集之间的查询速度基本一致,但是Elasticsearch增幅就不大,而且随着数据集的增大查询速度是递减的。
throughput.png

WechatIMG22.png

详细的比较说明参见:InfluxDB Markedly Outperforms Elasticsearch in Time-Series Data & Metrics Benchmark

Elasticsearch强在全文搜索,InfluxDB擅长时序数据,所以还是具体需求具体分析。如果需要保存日志并经常查询的,Elasticsearch比较合适;如果只依赖日志做状态展示,偶尔查询,InfluxDB比较合适。

轻松筹的业务各有特点,单一选择Elasticsearch或者InfluxDB都不能很好的查询日志和指标展示,所以有必要InfluxDB和Elasticsearch共存。在 Logstash 里配置2个输出,同一条日志输出2份,一份保留全部字段输出至 Elasticsearch;另一份过滤文本性的字段保留指标性的字段,然后输出至 InfluxDB。

InfluxDB如果作为Logstash的输出,有个坑需要注意,就是Logstash的InfluxDB插件支持的时间戳精度太粗,不能精确到纳秒,会导致同一个值的时间戳在插入InfluxDB的时候出现异常。因为InfluxDB用measurement名、tag集和时间戳来唯一标识一条记录。如果插入InfluxDB的一条记录与已经存在的一条记录measurement名、tag集和时间戳都相同,那么filed会是新老两条记录的集合,相同field的值会被新记录覆盖。 解决方式有2种,一种是增加一个tag来标识新记录。另一种是手动提升时间戳的精度,提升至微秒,理论上每天可以支持86,400,000,000条不重复的日志,可以很大程度避免时间戳的重叠,配置如下所示:
// 业务日志输出时时间戳格式化到微秒:2006-01-02T15:04:05.999999Z07:00

// Logstash的filter根据时间戳转换
filter {
ruby {
code => "event.set('time',(Time.parse(event.get('time')).to_f*1000000).to_i)"
}
}

# 6 . 数据展示
Grafana vs. Kibana
WechatIMG23.png

比较Kibana和Grafana,Kibana在图表展示上没有Grafana美观,而且Grafana的配置更加简单灵活。既然在日志存储中决定InfluxDB和Elasticsearch共存,展示上就也需要Kibana和Grafana共同协作,Kibana从Elasticsearch中检索日志,Grafana从InfluxDB和Elasticsearch中获取展示数据。下面2张图片展示了Grafana在轻松筹业务监控上的应用:
feed.png

sample2.png

# 7 . 异常报警
即使上述6个环节都建立了,如果没有报警一切都是没有意义的,因为不可能每时每刻都盯着曲线看,所以需要设置异常阈值,让监控系统定时检查,发现异常立即发送报警通知。

报警的服务有很多,但是数据展示的Grafana自带报警功能,功能也能满足我们的报警需求,而且配置简单,所以规则简单的报警可以采用Grafana的报警服务。不过Grafana的报警只支持部分数据库,分别是Graphite, Prometheus, InfluxDB 和 OpenTSDB,所以在Elasticsearch中的日志报警还需要Elastic Stack的X-Pack。
##Condition
image2017-4-20_15-10-32.png

如上图所示,可以设置报警检查的频率,报警条件是最近的5分钟内指定指标的平均值是否大于70,如果这个条件为True则触发报警。这种报警条件还比较单一,像错误数在十分钟内超过几次才报警,当前订单数与昨天同一时间的订单数比较跌了超过百分之几就报警,控制报警通知发送的频率,等等,Grafana就不能满足了,针对这种报警规则我们自己实现了一个报警引擎,用来满足这些比较复杂的报警规则。
##Notification
Grafana的报警通知只有在状态转换时才会触发,即报警状态的时候会发送告警通知,如果到恢复之前的一段时间里条件一直是满足报警条件的,Grafana不会一直发送通知,直到恢复的时候再发送一次恢复的通知。如果触发报警,Grafana支持4中通知方式:Email、Slack、Webhook 和 PagerDuty。其中Slack是国外的一种协作工具,类似钉钉,PagerDuty是一个收费的告警平台,所以可选的只剩下Email和Webhook了。下面简单的介绍如何配置Email和Webhook
##Email
Grafana的邮件配置很简单,可以利用QQ企业邮箱的smtp服务来发送报警邮件,邮件内容是配置的报警,配置比较简单:
[smtp]
enabled = true
host = smtp.exmail.qq.com:465
user = alert@qingsongchou.com
password = ********
from_address = alert@qingsongchou.com
from_user = Grafana

##Webhook
Webhook 就是在触发报警时,Grafana主动调用配置的http服务,以POST或者PUT方式传递json数据。这样就可以在我们自己开发的http服务里增加额外的通知方式,例如短信、微信甚至电话。
##Reception
配置了报警通知,不接收不去看也是白搭。一方面我们尽量实现多种通知途径,比如邮件、微信和短信。另一方面需要项目负责人接到报警及时响应,查看问题。
# Q&A
Q:针对Grafana不支持的报警,你们自己实现的报警引擎是直接在grafana的基础上修改的么,还是独立于Grafana呢?

A:我们用Go自己实现的一个报警引擎,独立于Grafana。



Q:Logstash 你们遇到过收集慢和丢日志的情况吗?现在你们Logstash收集日志到什么规模了?

A:我们目前的日质量大概每天2亿条,高峰时候每小时2000万条左右。Logstash运行的还可以,如果后期遇到手机慢,做简单的方式是扩机器,先解决问题,再想更好的优化策略。



Q:如果类似于Nginx、MySQL这种日志,类型增加需要解析每增加一个就要去改Logstash的grok吗?

A:针对常用的服务,grok已经提供了一些正则的pattern,例如你提到的Nginx、MySQL。目前是每增加一个就需要修改grok,后期可以实现一个UI来提高修改效率。



Q:这个lostash日志格式转换怎么学习?

A:Logstash有很完善的文档,感兴趣的话可以参考https://www.elastic.co/guide/en/logstash/current/index.html



Q:据说Logstash比较吃内存,fluentd作为EFK组合也经常出现,请问你们有没有做过选型呢?

A:当时选择了ELK,就没有做太多的选型了,Logstash吃内存的问题现在还不是太突出。



Q:日志的完整性怎么保证的?怎么知道没丢日志,或丢失了多少日志?

A:Filebeat和Logstash的输出插件都有一些重试的策略,但是也免不了日志丢失。日志的完整性确实和保证日志不丢也是我们目前在尝试解决的问题。



Q:请问监控系统需要考虑高可用吗?

A:肯定是要考虑高可用,当后期更多的业务依赖监控系统后,就要保证监控系统不挂,查询要快,实时监控,报警准确等。



轻松筹,一亿用户信赖的全民众筹平台!

以上内容根据2017年6月8日晚微信群分享内容整理。分享人施佳达,轻松筹GoLang高级工程师,北邮研究生,在分布式计算与舆情分析领域有深入研究,2015年滴滴出行公共平台负责滴滴出行Web APP后端研发,目前在轻松筹主要从事Feed系统架构设计以及重明鸟监控系统的建设。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

DockOne微信分享( 一零二):基于容器的日志管理实践

Dataman数人科技 发表了文章 • 1 个评论 • 4378 次浏览 • 2017-01-06 16:15 • 来自相关话题

【编者的话】业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。 20 ...查看全部
【编者的话】业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。

2013年以来Docker迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控、日志、网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验。
# 基于ELK的日志管理系统架构
日志收集是大数据的基础,业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行分析处理;高可用性,高可靠性以及可扩展性是日志收集系统的必备要素。

ELK是目前较流行的日志一体化解决方案,提供日志收集、处理、存储、搜索、展示等功能。容器标准输出日志常用的查询方式是通过Docker命令 docker logs containerid来查看,容器内日志受容器隔离性影响不便于收集,因此当面对大型系统,用单一命令管理日志是不可行的,需要一个对于容器日志统一检索管理的方案。基于ELK实践了一套容器日志管理系统,架构如下:
1.png

# 日志采集
传统的日志采集有较成熟的解决方案,如Flume、Logstash等,但传统的采集方案不适用于容器日志。Docker本身提供了LogDriver功能,可以利用不同的driver把日志输出到不同地方,LogDriver具体有以下几种:

* None(将日志设置成不再输出)
* json-file(Docker默认的LogDriver,将日志以JSON文件的方式存储在本地)
* Syslog(标准输出日志可通过该方式传输)
* Journal
* SELF
* Fluent
* awslogs
* Splunk
* etwLogs
* gcplogs

对于这些LogDriver就不一一详细介绍了,大家有兴趣可以去Docker官网查看。可见Docker对日志提供了较为丰富的处理方式,供选择的还有优秀的开源项目Logspout等,然而这并不能满足所有的使用场景。

容器的标准输出日志可从以上驱动中选择,由于大多数用户选择标准化输出日志,故Docker没有提供采集功能,如果将日志内的文件挂载出来进行采集,多个实例同名日志则会无法区分,容器内文件日志处理、错误日志多行处理等问题时有发生,若想标准输出日志和容器内文件日志兼得,则需自己动手丰衣足食,以下为数人云日志采集系统实践。
##1. 标准输出日志
针对Marathon + Mesos环境开发了一套日志采集工具,Docker的标准输出日志json-file默认持久化在本地上,Mesos对于标准输出日志也存了一份在Sandbox下:
2.png

因此标准输出日志也可以通过Mesos文件的方式进行采集。
##2. 容器内文件日志
平台支持的文件存储是Overlay,避免了许多复杂环境的处理。关于Overlay盗用一张图:
3.jpg

容器的存储驱动运用写时复制(Copy On Write),Overlay主要分为lower和upper, 当需要修改一个文件时,使用CoW将文件从只读的Lower层复制到可写层Upper层进行修改,在Docker中,底部的只读层是image,可写层是Container,因此容器内日志在宿主机上通过Upper的文件系统可找到,例如在容器内的/var/log/test.log中写一个test字符,如图:
4.png

同理,无论是标注输出的日志还是容器内文件日志,都可以通过文件的方式进行处理,也可以同时把json-file关闭,以减轻Docker本身的压力。
##3. 自研日志采集工具
基于上述方式开发了一款日志采集工具,对日志进行统一收集管理,日志通过TCP把JSON格式化的日志输出到Logstash,包括应用ID,容器Name,容器ID,TaskID等,当然开发的过程中也遇到许多问题,如断点续传和错误日志多行处理等功能,这其中参考了Filebeat(Go语言开发)对于日志处理的方式,个人认为如果是对于传统文件日志处理,Filebeat是不错的选择,日志采集功能第一步支持:

* 容器标准输出日志采集
* 容器内文件日志采集,支持同时采集多个文件
* 断点续传 (如果Agent崩溃,从上次offset采集)
* 多行日志合并 (如:多行错误日志合并)
* 日志文件异常处理 (如:日志被rotate可以重新采集)
* TCP传输
* --add-env --add-label标签,可以通过指定命令把container的env或者label加到日志数据里,如(--add-env hostname=HOST --add-env test=ENV_NAME1 --add-label tlabel=label_name)
* Prometheus指标数据

日志处理需要提供快速的数据处理能力,在开发过程中遇到了性能问题,CPU占用非常高,针对该问题对程序作调优,使用Golang内置的包net/http/pprof,对Golang程序调优很好用,可将程序中每个函数占用CPU内存的比例通过生成SVG的方式直观的反映出来,如图:
5.jpg

Golang内置包encoding/json json的序列化、正则、反射、字节转字符串对于资源的消耗也比较高,可针对以上几方面以及程序本身进行调整。
# 日志存储后端架构
日志存储功能有Logstash、Heka、Fluentd等方案,Logstash基于R uby,支持功能丰富,但性能方面诟病较多;Heka基于Go,性能方面比Logstash好很多,不过Heka好像已经不维护了。综合考虑社区活跃度、迭代速度以及稳定性方面最终选择了Logstash,实际应用过程中比较重要的参数如下:

* --pipeline-workers (命令行参数)
* --pipeline-batch-size (命令行参数)
* LS_HEAP_SIZE=${LS_HEAP_SIZE} (根据自己的实际情况填写,可以写到环境变量活着命令行参数里面)
* workers => 8(根据自己实际情况,一般等于CPU数,配置文件参数)
* flush_size => 3000(根据自己的实际情况测试)

以上参数仅供参考,可根据实际环境进行调试。如果日志量较大,为了确保架构的稳定性,可以在中间加一层消息队列,比较常用的有Kafka、Redis等,相信大家对这方面应用比较多,不再赘述。

ES应该是索引存储的不二选择,整个架构的缓解包括ES通过Docker的方式部署,压测时用Marvel对ES的索引方式监控等,网上有很多调优资料,可自行实验。日志的展示是通过自己定制的,Kibana本身的功能比较强大的同时也略微有些学习成本,最终客户想要的是很简单的东西。

压测工具选择的是分布式压测工具Tsung,通过压测一个应用产生日志然后通过Log-Agent对日志进行采集,模拟真实环境日志采集。
# 日志告警
日志处理中,关键字报警是一个重要功能,对于监控报警主要用Prometheus + Alertmanager实现。应用运行过程中,根据日志关键字告警部的应用场景,从Logstash部分对日志做分流(具体方案可以看上面图的报警部分),自研grok_export对日志进行过滤分析生成Prometheus格式的数据,然后从Prometheus配置报警策略通过alertmanager报警。Log-Agent本身也支持Prometheus数据,Prometheus通过特定的规则查看日志的统计信息。

* Prometheus:
Prometheus是开源的监控告警系统,通过pull的方式采集时间序列,以及用http传输,数据存储在本地,支持丰富的查询语法和简单的Dashboard展示。

* Alertmanager:
Alertmanager作为Prometheus的组件,所有达到阀值的时间都通过Alertmanager报警,Alertmanager支持非常强大的告警功能,包括http、email通知,以及静默重复报警屏蔽等功能。

以上是数人云在实践容器日志系统过程中遇到的问题,更高层次的应用包括容器日志分析等,还有待继续挖掘和填坑,欢迎大家提出建议,一起交流。
#Q&A
Q:Overlay 是没有实现 inotify 接口的,是咋获取文件日志增量数据的?

A:通过循环读取文件的方式,记录文件offset。



Q:既然主要框架是 ELK,采集端不直接用 Filebeat 是因为 Filebeat 有局限性吗?

A:Filebeat没有满足我们产品基于Docker的需求,等于上面加了Docker的逻辑。



Q:自研的日志系统,打出来的每条日志格式都是规定好的吗?开发中每个人都要按这个规范来做吗?不管是什么级别的日志?

A:其实并没有,但是如果是内部使用,能规约好当然更好,可以更方便的处理,而且可以做更细粒度的分析。



Q:日志收集有做分析展示处理吗?用什么处理的。

A:对于日志内容的分析还没做,例如Nginx请求日志还是有分析意义的。



Q:采集方面有考虑直接使用系统的Syslog和Logrotate吗?

A:用过Syslog后来因为容器内的文件日志需求重新开发的。



以上内容根据2017年1月5日晚微信群分享内容整理。分享人郭已钦,数人云研发工程师。早期从事Java&JavaScript开发,爬虫大数据开发,之后开始写Go,参与开源容器管理工具Crane的研发与维护,目前在数人云做云平台研发工作。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

DockOne技术分享(十二):新浪是如何分析处理32亿条实时日志的?

Gary的影响力 发表了文章 • 4 个评论 • 67443 次浏览 • 2015-07-15 21:17 • 来自相关话题

【编者的话】我从2014年初入职新浪后就开始接触实时日志分析相关的技术,主要是ELK(Elasticsearch、Logstash、Kibana),当时是学习+ELK优化,接一些日志,小打小闹。从2015年起,我们正式得把实时日志分析作为服务提供给公司的其他部 ...查看全部
【编者的话】我从2014年初入职新浪后就开始接触实时日志分析相关的技术,主要是ELK(Elasticsearch、Logstash、Kibana),当时是学习+ELK优化,接一些日志,小打小闹。从2015年起,我们正式得把实时日志分析作为服务提供给公司的其他部门。今天要给大家分享的是在服务化的道路上,我们的想法,方案和疑问。
服务介绍
随着实时分析技术的发展及成本的降低,用户已经不仅仅满足于离线分析。目前我们服务的用户包括微博、微盘、云存储、弹性计算平台等十多个部门的多个产品的日志搜索分析业务,每天处理约32亿条(2TB)日志。
技术架构
简单介绍一下服务的技术架构:
architecture.png

这是一个再常见不过的架构了:
(1)Kafka:接收用户日志的消息队列。
(2)Logstash:做日志解析,统一成JSON输出给Elasticsearch。
(3)Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能。
(4)Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因。
努力提供更好的服务
我这次分享的重点不是这种架构的优劣或为什么选择这样的架构,而是在如此的架构上如何更好地传递实时日志分析的价值。为用户做好服务也不是修改几个配置文件,调优几个程序运行参数就能搞定的。为了提供更好的服务,我们在下面三个方向做了努力:
# 一、提升服务质量
我们首先做了Elasticsearch优化,Hardware Level由于我们当时拿到机器没有选择余地,只开启了超线程;System Level的优化如关闭swap,调整max open files等;App Level的优化如Java运行环境版本的选择,ES_HEAP_SIZE的设置,修改bulk index的queue size等,另外还设置了默认的index template,目的是更改默认的shard,replica数并将string改为not_analyzed,开启doc_values以应对elasticsearch进程OOM。详细的优化内容见Elasticsearch Optimization Checklist

随着用户数据的不断增长,index管理也成了大问题,我们需要基于大量不同的用户配置定期的create、optimize、close、delete、snapshot不同的index,在某个服务器上手工配置crontab已是不可能,而且cron是单点。于是我们开发了一个独立的Elasticsearch Index管理系统,负责以上任务的调度及执行。这个管理系统背后使用的技术是Celery,一个用Python开发的任务队列及执行系统,提供了类似crontab的定时任务配置语法,并且实现了分布式,可用性更高的架构。

最近的服务升级,我们为Elasticsearch安装了HDFS Snapshot插件,可以定期将index备份到HDFS,这个功能目前主要用于备份Kibana的配置index,用以恢复用户查看或配置可视化界面时的错误操作。

监控报警方面,System Level的监控报警(如硬盘满、损坏、服务器宕机)直接使用了在新浪内部提供了多年服务的sinawatch;App Level(如Elasticsearch JVM Heap Usage过高,Kibana能否正常访问,Kafka topic的consumer offset lag),我们开发了对应的监控报警脚本。User Level(如日志解析失败数量),主要通过elasticsearch python client执行`query`去统计或搜索。常见的报警是Logstash-filter-grok,logstash-filter-json解析日志失败会输出的json中添加_grokparserfailure、_jsonparsefailure,我们执行query判断解析错误的量。

要说明的是,Marvel是Elasticsearch很好的监控工具和插件,但是它们是商业软件,我们没有采用。Marvel是基于Kibana做的,里面对一些重要指标(如index bulk reject number)的展示很有价值。
# 二、增强易用性
增强服务的易用性就是给用户更好的用户体验,减少用户的抱怨。ELK性能优化是一方面,但它是远远不够的,我们遇到的实际情况是,用户在其他方面抱怨更多,如下:

1,用户最先抱怨的是IP解析成地区、ISP信息一点都不准,完全没有参考意义。

如对于CDN这种服务,我们解析用户IP不准,定位问题边缘节点错误,问题没法查,这是帮倒忙。原因:Logstash默认自带的IP库是国外maxmind公司的免费版本,中国的信息尤其不准。解决方案:使用我浪较新较全的IP库生成能适配maxmind geoip2 api的二进制格式IP库(maxmindDB),再开发logstash-filter-geoip2来解析IP。实测不仅IP解析准确率与公司IP库相同了,解析速度也提高了。

2,然后我们与用户都发现日志接入流程复杂,沟通困难。

人做不到机器那样分毫不差,有啥说啥。接入用户日志的时候,例如常常因为用户对日志格式表达的不全面,模棱两可,导致日志解析失败,服务对接人多次重写配置。从用户提需求到用户可以看到数据可视化效果或搜到日志,需要几个小时到几天。一来二去,用户和我们都烦了,只能求变。为此,我们正在逐步实现用户数据接入的自动化,减少接入时间和沟通成本这个过程需要3个关键:A.用户配置日志格式的界面,尽可能简洁简单;B.根据用户配置自动生成logstash config、index管理需要的配置;C.自动部署配置(logstash config等),打通日志流。

后来我们做了一个简单的用来协商日志格式的界面:
ui_log_format.png

目前我们已完成了A的一部分:用户日志格式配置界面;B的全部:开发了自动生成logstash conf的 python api;C即将开始,并且考虑使用Docker技术为我们提供一些便利。

3,部分数据可视化需求得不到满足,Kibana配置难度大。

我们起初采用官方Kibana v3,用户提出的类似SQL中的多个group by,画百分比,求指定区间占比等常见需求无法满足。之后通过三斗大神(微博@argv)定制版的Kibana 3满足了一些用户需求。Kibana 4诞生后,代码几乎是对Kibana3的重写,做了大幅改进,通过`Elasticsearch Aggregation`的强大数据统计功能及灵活的配置从Kibana 3解放出来。近期我们将迁移到Kibana 4。
#三、提供新功能
我们为Elasticsearch安装了国内medcl大神开发的ik中文分词插件elasticsearch-analysis-ik。之前被分词为『中』和『国』的中国,现在终于可以被当做一个完整的词汇,否则搜索『中国』、『美国』也会出现。微盘的一些离线搜索需求使用了我们的服务,也用到了中文分词,Elasticsearch的搜索天赋满足了他们的需求,减少了他们的痛苦。
ik_analyzer.png

我们经历过的坑和坎儿:
1,elasticsearch 进程JVM Heap High Usage( > 90% )。

很长一段时间,我们都在应对JVM Heap High Usage,他带了的问题是Old GC次数多,时间长,es节点频繁退出集群,整个集群几乎停止响应。现在我们的主要策略是开启doc_values;限制query执行时占用的JVM Heap size;analyzed string只允许做query,不允许facets或者aggs;定期close 用户不需要的index。

2,Elasticsearch Query DSL、Facets、Aggs学习困惑。

有人为此开发了使用SQL执行ES Query的插件,一定程度上减轻了进入门槛。我们给出的学习他们的建议是观察Kibana的Request Body或试用Marvel的Senese插件,它有自动完成Query、Facets、Aggs的功能。另外最常用的query是`query string query`,最常用的aggs是`Terms`、`Date Histogram`,可以应付大部分需求。

3,logstash不工作。

非官方的问题插件,及使用logstash-filter-ruby时未考虑到的异常等,导致Logstash运行时工作线程(worker thread)异常退出,Logstash僵死。我们的建议是尽可能不要在config中使用logstash-filter-ruby,尽量使用官方插件。不过我们也遇到过复杂的日志,写过250行+的config,用尽了ruby filter。当前未发现Logstash有好的成熟的监控方案,Logstash的内部状态也获取不到。我们目前通过间接的监控Kafka topic consumer是否落后或elasticsearch indexing rate来检验logstash的工作情况。

4,Kibana没有用户的概念,不同用户的数据无法隔离。

多个用户共享的Kibana Dashboard,误操作或误删时常影响其他用户,保存的dashboard太多,找到特定的dashboard很困难。官方到目前为止,未在这方面做过改进。有很多非官方的改进,我们也曾经用过三斗大神定制的Kibana3,也对Kibana index做了snapshot储存到HDFS里面。

5,与用户沟通成本高。

与我们的用户协商日志格式,数据可视化配置时,由于人的不确定性容易造成多次来回确定和修改,效率低下。我们毕竟是提供日志分析服务的,不给用户做日志运维,所以近期也在探索通过日志接入自动化、推荐用户提供给我们json格式数据,定期组织用户的Kibana培训来减少沟通成本。
Q & A
问:logstash连es出现timeout的情况有没?如何解决的?
答:我们常见的是ES Jvm Heap Usage比较高的时候会timeout,如果是服务内存小换大内存。另外不要对analyzed的string做aggs、facets,开启doc_values。

问:关于日志中异常报警的,有哪些方式?关键字过滤?
答:对于日志解析失败的情况,logstash 常见的是_grokparsefailuer和_jsonparsefailure,数据写入es后,执行query查询这两个关键词的数量即可。对于报警方案,watch是官方刚出的,其实比它早的实现方案,如Yelp的elastalert。

问:大数据分析平台(基于HDFS)跟kibana的展现会有很大区别吗?或者说最大的区别会在哪些方面?
答:你说的区别,我理解是Hadoop与Elasticsearch的区别,一个是离线分析,以job为单位,一个是实时搜索和统计,以query为单位。这里有三个关键词:实时,搜索,统计。Hadoop是离线的,es是实时的;es本质上是一个搜引擎,可以用来做全文检索等工作,Hadoop显然于此无关。统计是Hadoop与es都能做的,我不了解Hadoop有没有像Kibana这样的数据可视化组件。

问:你们的ES集群数据节点和查询节点做了分离吗?logstash是直接把数据写入查询节点还是数据节点?另外你们直接用的node模式还是transport模式呢?
答:(1)还没有做分离。(2)我们还在用http protocol模式。

PPT已经上传至微盘

===========================
以上内容根据2015年7月14日晚微信群分享内容整理。分享人高英举,就职于新浪,主要负责dip实时日志分析服务技术架构与实现,为微博,微盘,视频,cdn等多个部门提供实时日志统计和搜索服务,热衷于将开源技术服务化,产品化。微博:@gary的影响力 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesx,进群参与。

DockOne技术分享(二):集群规模下日志处理和网络方案

CMGS 发表了文章 • 1 个评论 • 11811 次浏览 • 2015-05-06 09:57 • 来自相关话题

【编者的话】本文主要介绍在容器集群中,如何管理容器日志,有哪些方法可以管理日志,这些方法分别有哪些优势和劣势。紧接着讨论了目前网络的几种方案,每种方案都会带来什么样的收益和效果。最后介绍了芒果TV的最佳实践。 我先假定今晚的听众至少小 ...查看全部
【编者的话】本文主要介绍在容器集群中,如何管理容器日志,有哪些方法可以管理日志,这些方法分别有哪些优势和劣势。紧接着讨论了目前网络的几种方案,每种方案都会带来什么样的收益和效果。最后介绍了芒果TV的最佳实践。

我先假定今晚的听众至少小范围的铺开 Docker 容器化技术在线上了,至少熟悉 Docker 的工作原理和 remote API。所以我不会过多的介绍Docker 的基本操作和使用,主要是分享集群化容器中的日志管理和网络管理

在早期 Docker 实现中,日志这块的功能都不完善,所有容器内的标准输出和错误都会写入到`/var/lib/docker/containers/{$cid}/{$cid}-log.json`中。因为没有日志自动分卷以及容器绑定,所以一旦到线上就会出现瞬间磁盘打满的情况。而这个文件同时又是 docker logs api 的 data source,加之 docker 1.6 引入的 log-driver 参数,因此对于线上日志的收集管理我们目前有这么几个方法。

  1. 监控文件,并通过管道转出数据。这种方案最大的问题是日志文件和容器是绑定的,因此需要有一个 agent 的角色来做这件事,变相的增加了开发成本,还要考虑管道的可靠性问题。另外 CentOS 6系和7系日志地址不一样,如果硬编码则扩展性不佳,如果读取系统配置,那就要考虑跨系统之间的路径问题。

  1. 通过`docker logs api`来远程重定向日志。这种方法最大的问题是你避免不了还是得有 agent 去清理日志这么个操作,否则的话磁盘依然会被打满,当然也可以配合 logrotate 来做这事,不过增加了运维成本。如果是远端调用这个 API 的话,需要考虑连接的可靠性,一旦出现重连,那就要做日志回溯,否则会丢失一部分日志。

  1. 容器内进程自己写出日志。这又有两种方案,如下:

* 进程直接写出,控制权交给了业务方,对业务不透明,可控性降低,毕竟是集群环境。这样一来也要暴露集群结构给上层。
* 映射日志设备(/dev/log)进容器,容器内进程直接写设备,隔离性减弱,单点问题追踪会很麻烦,因为这时候 stdout 和 stderr 是没有内容的,也就是`docker log`命令无任何输出。

『进程直接写出』这种方案我们试过,不过要让业务方来改代码,所以整体推进很难了。另外它还暴露了远端日志服务器地址,无论是网络上还是安全上都是有问题的。举个例子,一旦介入 SDN 等管理网络的方式,那么等于就是破坏了整体的隔离性。『映射日志设备进容器』这种方案就是定位问题容器比较麻烦,而且还是要涉及到跟业务方沟通。

  1. 使用新版的 log-driver 参数,其中包含支持 syslog,看似很美好,但是在集群环境下要考虑 syslog 单点问题。一般来说会有多个 syslog 或者支持 syslog 协议的远端 server (logstash)。如果使用远程 syslog 接受日志,大量容器日志输出并不平均,从而会产生性能热点和流量热点。如果走单机 syslog 再汇总,那就和上面的方案『进程直接输出』没多大区别了,同样是跟踪问题比较麻烦。我觉得目前这个实现更多的是方便了之前使用 syslog 方案的。

  1. 通过attach 方法截获容器输出流重定向。这种方案需要 agent 支持,有一定开发要求。目前我们采用的就是这种方案,通过一个模块实现了 consistent hash,然后把日志流量打到远端收集服务器上。这个方案只需要让业务把日志输出到 stdout/stderr 中即可,并不会增加开发成本。同时Docker 1.6中可以指定日志驱动为 none,避免了 logs 文件的产生。另外一方面可以把容器自己的 meta info 附加到日志流里面,从而实现远端的日志检索分类聚合等操作。但这个方案最大的问题是开发力量的投入,不同的 dockeclient 实现质量也不一样,当然好处也是很明显的,灵活可控,日志流向和分配都在自己受伤。

所以日志方面,从目前 Docker 实现来看,如果开发力量跟得上,agent + attach 方案是灵活性和可控性是最高的。目前 log-driver 对于上规模的集群来说还是不太好用,理想状态下我希望是可以指定多个 log-drivers,通过 hash 方案打到远端。当然具体方案的选取就得看各自公司本身的基础设施和设计目标了。

说完日志来说下网络,目前 Docker 的网络方案主要有这么几个,当然现在大家都在等 1.7,不过我认为对于生产系统而言,已有 SDN 方案的不会太过于在乎 Libnetwork,可能会研究下其和 Docker 是怎样通过 plugin 方式结合的。因为其他它案目前都是 Hook 方式去做的。

  1. 默认 NAT/BR/HOST,NAT 有性能损失,BR 有网络闪断,HOST 流控不好做,端口冲突靠业务保证没法做到透明。
  2. 网络层方案
a. 隧道方案
I. OVS,主要是有性能方面的损失,基于 VxLAN 和 GRE 协议,类似的方案还有 Kubernetes/Socketplane 的实现。
II. Weave,UDP 广播,本机建立新的 BR,通过 PCAP 互通。
III. Flannel,UDP 广播,VxLan。
隧道方案非常灵活,但是因为太过于灵活,出了网络问题(A-B 链路抖动)跟踪起来比较麻烦,大规模集群情况下这是需要考虑的一个点,毕竟即便是内网也不一定风平浪静。

b. 路由方案
I. Pipework,对于 Docker BR 本身的扩展,当然也支持 OVS macvlan 等方案的结合。现在 libnetwork 出来变相的是废了这个项目了,长远来看后继无人,因此它不是一个很好的选择。
II. Calico,基于 BGP 协议的路由方案,支持很细致的 ACL 控制,对于隔离要求比较严格的场景比较适合,对混合云亲和度比较高,因为它不涉及到二层的支持。
III. Macvlan,从逻辑和 Kernel 层来看隔离性和性能最优的方案,基于二层隔离,所以需要二层路由器支持,大多数云服务商不支持,所以混合云上比较难以实现。

路由方案没那么灵活,大多数情况下需要有一个 agent 在容器主机上去操作,一般是从 3 层或者 2 层实现隔离和跨主机容器互通的,出了问题也很容易排查。但是路由方案对本身物理网络依赖会比隧道方案要重。另外 hook 的话毕竟还是不太优美,所以得看看 libnetwork 是怎样和 Docker 结合的。

目前我们选取的是 macvlan 的方案实现的二层隔离,说轻点主要是对容器而言,可以完全当容器为一台虚拟机。说重点,是因为其对物理网络基础设施依赖程度最高。

##Q&A

问题:macvlan 是怎么做的?
答案: Linux 内核支持,直接用 agent 在 host 上生成设备塞入到容器的 namespace 中。

问题:为何不直接打日志?
答案: 容器内的话得考虑 docker 本身存储性能问题,如果是容器外得考虑卷管理问问题,如果是远端,得考虑和业务结合的问题。

问题:网络层比较成熟的选择?
答案: macvlan 进了内核,Calico 做了十来年了,这2者都会比较成熟,weave 比较简单和方便。

问题:日志丢失问题
答案: 尽可能的不让业务层去控制日志输出,即便是 socket 文件或者设备都有可能被删除从而导致日志丢失,因此尽量从平台层面控制。

问题:二进制服务跑在 Docker 里面的问题
答案: 目前我们也在做类似的事情,跑Redis。但是因为容器本身没有 init 进程,因此内核参数都是默认的,有些 binary 应用在这方面会比较敏感。我们目前也没找到比较优美的方法解决。Docker 官方仓库有不少类似的 issue。

===========================

以上内容根据2015年5月5日晚微信群分享内容整理。分享人彭哲夫,芒果TV平台部核心技术团队负责人,主要负责Docker和Redis Cluster相关的技术设施开发。之前担任过豆瓣App Engine和金山快盘的主程。在系统工程方面有非常丰富的经验。接下来,DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加我微信(liyingjiesx)参与。

关于应用日志持久化到本地的一个问题

回复

voidint 回复了问题 • 2 人关注 • 1 个回复 • 1975 次浏览 • 2017-09-21 09:19 • 来自相关话题

Docker关闭容器日志

回复

Georce 回复了问题 • 1 人关注 • 1 个回复 • 5654 次浏览 • 2015-08-13 11:36 • 来自相关话题

使用开源工具fluentd-pilot收集容器日志

Rancher 发表了文章 • 1 个评论 • 2321 次浏览 • 2017-12-20 11:49 • 来自相关话题

来自用户的最佳实践分享,如何用阿里开源的Docker日志收集工具fluentd-pilot收集机器上所有Docker应用日志。 fluentd-pilot简介 fluentd-pilot是阿里开源的docke ...查看全部
来自用户的最佳实践分享,如何用阿里开源的Docker日志收集工具fluentd-pilot收集机器上所有Docker应用日志。

fluentd-pilot简介

fluentd-pilot是阿里开源的docker日志收集工具,Github项目地址 。你可以在每台机器上部署一个fluentd-pilot实例,就可以收集机器上所有Docker应用日志。

fluentd-pilot 具有如下特性:

  • 一个单独的 fluentd 进程收集机器上所有容器的日志。不需要为每个容器启动一个 fluentd 进程。
  • 支持文件日志和 stdout。docker log dirver 亦或 logspout 只能处理 stdout,fluentd-pilot 不仅支持收集 stdout 日志,还可以收集文件日志。
  • 声明式配置。当您的容器有日志要收集,只要通过 label 声明要收集的日志文件的路径,无需改动其他任何配置,fluentd-pilot 就会自动收集新容器的日志。
  • 支持多种日志存储方式。无论是强大的阿里云日志服务,还是比较流行的 elasticsearch 组合,甚至是 graylog,fluentd-pilot 都能把日志投递到正确的地点。
rancher使用fluentd-pilot收集日志我们既然要用fluentd-pilot,就得先把它启动起来。还要有一个日志系统,日志要集中收集,必然要有一个中间服务去收集和存储,所以要先把这种东西准备好。Rancher中我们要如何做?如图,首先我们选择Rancher的应用商店中的Elasticsearch和Kibana。版本没有要求,下面使用Elasticsearch2.X和Kibana4。其次在RancherAgent主机上面部署一个fluentd-pilot容器,然后在容器里面启动的时候,我们要声明容器的日志信息,fluentd-pilot会自动感知所有容器的配置。每次启动容器或者删除容器的时候,它能够看得到,当看到容器有新容器产生之后,它就会自动给新容器按照你的配置生成对应的配置文件,然后去采集,最后采集回来的日志同样也会根据配置发送到后端存储里面去,这里面后端主要指的elasticsearch或者是SLS这样的系统,接下来你可以在这个系统上面用一些工具来查询等等。可根据实际情况,在每台Agent定义主机标签,通过主机标签在每台RancherAgent主机上跑一个pilot容器。用这个命令来部署,其实现在它是一个标准的Docker镜像,内部支持一些后端存储,可以通过环境变量来指定日志放到哪儿去,这样的配置方式会把所有的收集到的日志全部都发送到elasticsearch里面去,当然两个挂载是需要的,因为它连接Docker,要感知到Docker里面所有容器的变化,它要通过这种方式来访问宿主机的一些信息。在Rancher环境下使用以下docker-compose.yml 应用---->添加应用,在可选docker-compose.yml中添加一下内容。
version: '2'services:  pilot:    image: registry.cn-hangzhou.aliyuncs.com/acs-sample/fluentd-pilot:0.1    environment:      ELASTICSEARCH_HOST: elasticsearch      ELASTICSEARCH_PORT: '9200'      FLUENTD_OUTPUT: elasticsearch    external_links:    - es-cluster/es-master:elasticsearch    volumes:    - /var/run/docker.sock:/var/run/docker.sock    - /:/host    labels:      aliyun.global: 'true'
配置好之后启动自己的应用(例子:tomcat),我们看应用上面要收集的日志,我该在上面做什么样的声明?关键的配置有两个,一是label catalina,声明的是要收集容器的日志为什么格式(标准格式等,也可以是文件。),所有的名字都可以;二是声明access,这也是个名字,都可以用你喜欢的名字。这样一个路径的地址,当你通过这样的配置来去启动fluentd-pilot容器之后,它就能够感觉到这样一个容器的启动事件,它会去看容器的配置是什么,要收集这个目录下面的文件日志,然后告诉fluentd-pilot去中心配置并且去采集,这里还需要一个卷,实际上跟Logs目录是一致的,在容器外面实际上没有一种通用的方式能够获取到容器里面的文件,所有我们主动把目录从宿主机上挂载进来,这样就可以在宿主机上看到目录下面所有的东西。当你通过部署之后,他会自己在elasticsearch创建索引,就可以在elasticsearch的kopf上面看到会生成两个东西,都是自动创建好的,不用管一些配置,你唯一要做的事是什么呢?就可以在kibana上创建日志index pattern了。然后到日志搜索界面,可以看到从哪过来的,这条日志的内容是什么,这些信息都已经很快的出现了。Lable说明启动tomcat的时候,我们声明了这样下面两个,告诉fluentd-pilot这个容器的日志位置。
aliyun.logs.tomcat1-access   /opt/apache-tomcat-8.0.14/logs/localhost_access_log.*.txt aliyun.logs.catalina   stdout
你还可以在应用容器上添加更多的标签aliyun.logs.$name = $path
  • 变量name是日志名称,具体指随便是什么,你高兴就好。只能包含0-9a-zA-Z_和-
  • 变量path是要收集的日志路径,必须具体到文件,不能只写目录。文件名部分可以使用通配符。/var/log/he.log和/var/log/*.log都是正确的值,但/var/log不行,不能只写到目录。stdout是一个特殊值,表示标准输出
aliyun.logs.$name.format,日志格式,目前支持
  • none 无格式纯文本
  • json: json格式,每行一个完整的json字符串
  • csv: csv格式
aliyun.logs.$name.tags: 上报日志的时候,额外增加的字段,格式为k1=v1,k2=v2,每个key-value之间使用逗号分隔,例如
  • aliyun.logs.access.tags="name=hello,stage=test",上报到存储的日志里就会出现name字段和stage字段
  • 如果使用elasticsearch作为日志存储,target这个tag具有特殊含义,表示elasticsearch里对应的index

#作者简介

翟坤,随行付支付有限公司资深运维工程师。
本文版权归作者所有,转载请后台留言。

DockOne微信分享(一二四):轻松筹监控系统实现方案

jiadas 发表了文章 • 1 个评论 • 9292 次浏览 • 2017-06-10 14:55 • 来自相关话题

【编者的话】监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况。虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化。这样既可以更灵活的满足自身 ...查看全部
【编者的话】监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况。虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化。这样既可以更灵活的满足自身业务的监控需求,也可以为以后自建机房提供技术积累。通过以下7个方面来建设监控系统。

【3 天烧脑式 Docker 训练营 | 上海站】随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛。本次培训我们理论结合实践,从Docker应该场景、持续部署与交付、如何提升测试效率、存储、网络、监控、安全等角度进行。

WechatIMG21.jpeg

# 1 . 日志打印
完善的日志是实现监控的基础,如何打印日志关系到之后的日志过滤、存储以及分析。除了选择合适的日志库,还要满足一些日志打印的要求:

  • 日志风格:以key-value的field形式输出结构化的日志。
  • 输出时机: error日志一定都需要打印,info日志结合业务需求适当打印,日志只需要在业务层关注,model和util等不需要打印。
  • 输出格式:线上以json的格式打印日志,方便解析日志。线下为了方便查看,可以用自定义的format打印日志,线上和线下的日志格式通过etcd来控制。
  • 输出内容: 每一条日志都要携带logid、method、host和level,并且根据不同业务场景,需要携带不同业务的标识field,例如projectType、platform、payType等。
  • 用context来传递不同goroutine之间的共享信息。

# 2 . 日志切分
日志切分是运维层面的东西,不应该由日志库来承担日志切分的事情,因为Linux在日志切分上有很成熟的工具,不需要自己写码去重复实现。

目前对日志切分的需求只有2个:按天切分和删除切出来的多余日志。logrotate就能很好的满足这些需求,logrotate是基于cron来运行的,其脚本是/etc/cron.daily/logrotate,默认放在/etc/cron.daily下,每天执行一次。

有的时候程序异常或者请求激增会导致日志量暴增,有可能在短时间内打满整个磁盘。可以在logrotate的配置文件里加上maxsize来限制日志文件的大小,并且将logrotate的执行频率调高至每小时甚至每分钟,及时切分并删除超过rotate数量的日志,来防止异常情况下磁盘被打满的情况发生。

样例配置如下所示:
// logrotate config of sample
// rotate every day, and keep for 3 days
/var/log/sample.log {
daily
rotate 3
maxsize 1G
missingok
sharedscripts
postrotate
# 在切分时向程序发送SIGHUP信号
killall -SIGHUP bin_sample
endscript
}

业务程序只需要负责监听SIGHUP信号,收到该信号时再重新打开日志文件。
# 3 . 日志采集
从监控系统的角度来说,日志收集有2种方式:主动采集和被动接收,两种方式各有利弊。
##主动采集
优点:日志收集和业务程序分开,互不影响。

缺点:日志收集需要依赖额外的采集服务,过滤和存储可能还需要额外配置。
##被动接收
优点:业务程序直接将日志发送至存储,灵活性强,存储内容可在业务代码里控制。

缺点:日志存储不稳定的话会影响业务程序的正常运行;反之,日志量大的话也会压垮日志存储。

但是在建设监控系统初期,日志存储还不是很稳定的情况下,还是用主动采集的方式比较稳妥,不影响服务稳定性为主。
WechatIMG24.jpeg

Collectd功能确实很强大,它的tail插件也能满足从文件收集日志,但是tail插件配置比较复杂而且说明文档相较于Filebeat来说不是很详细。

Collectd的其他插件可以采集的数据确实很多,而且也有插件支持将数据发送到Logstash和InfluxDB,但是多数插件的功能我们用不到,而且Elastic Stack中的Beats也能够很好的收集系统参数等数据,而且跟ELK能很好的兼容。

所以在分别试用了Filebeat和Collectd这2个采集服务后,综合上述分析决定采用Filebeat来负责从日志文件中采集日志。如下所示,Filebeat的配置简单易懂:
filebeat:
spool_size: 1024 # 最大可以攒够 1024 条数据一起发送出去
idle_timeout: "5s" # 否则每 5 秒钟也得发送一次
registry_file: "registry" # 文件读取位置记录文件,会放在当前工作目录下。
config_dir: "path/to/configs/contains/many/yaml" # 如果配置过长,可以通过目录加载方式拆分配置
prospectors: # 有相同配置参数的可以归类为一个 prospector
-
fields:
log_source: "sample" # 类似 logstash 的 add_fields,此处的"log_source"用来标识该日志来源于哪个项目
paths:
- /var/log/system.log # 指明读取文件的位置
- /var/log/wifi.log
include_lines: ["^ERR", "^WARN"] # 只发送包含这些字样的日志
exclude_lines: ["^OK"] # 不发送包含这些字样的日志
-
document_type: "apache" # 定义写入 ES 时的 _type 值
ignore_older: "24h" # 超过 24 小时没更新内容的文件不再监听。
scan_frequency: "10s" # 每 10 秒钟扫描一次目录,更新通配符匹配上的文件列表
tail_files: false # 是否从文件末尾开始读取
harvester_buffer_size: 16384 # 实际读取文件时,每次读取 16384 字节
backoff: "1s" # 每 1 秒检测一次文件是否有新的一行内容需要读取
paths:
- "/var/log/apache/*" # 可以使用通配符
exclude_files: ["/var/log/apache/error.log"]
-
input_type: "stdin" # 除了 "log",还有 "stdin"
multiline: # 多行合并
pattern: '^[[:space:]]'
negate: false
match: after
output:
logstash:
hosts: ["localhost:5044"] # The Logstash hosts

Filebeat 发送的日志,会包含以下字段:

* beat.hostname beat 运行的主机名
* beat.name shipper 配置段设置的 name,如果没设置,等于 beat.hostname
* @timestamp 读取到该行内容的时间
* type 通过 document_type 设定的内容
* input_type 来自 "log" 还是 "stdin"
* source 具体的文件名全路径
* offset 该行日志的起始偏移量
* message 日志内容
* fields 添加的其他固定字段都存在这个对象里面

# 4 . 日志过滤
logstash.png

Logstash 自2009年诞生经过多年发展,已经是很成熟并且流行的日志处理框架。Logstash使用管道方式进行日志的搜集处理和输出。有点类似*NIX系统的管道命令 input | filter | output,input 执行完了会执行 filter,然后执行 output。在 Logstash 中,包括了三个阶段:输入input → 处理filter(不是必须的)→ 输出output。每个阶段都由很多的插件配合工作,比如 file、elasticsearch、redis 等等。每个阶段也可以指定多种方式,比如输出既可以输出到elasticsearch中,也可以指定到stdout在控制台打印。

Codec 是 Logstash 从 1.3.0 版开始新引入的概念(Codec 来自 Coder/decoder两个单词的首字母缩写)。在此之前,Logstash 只支持纯文本形式输入,然后以过滤器处理它。但现在,我们可以在输入 期处理不同类型的数据,这全是因为有 Codec 设置。所以,这里需要纠正之前的一个概念。Logstash 不只是一个 input | filter | output 的数据流,而是一个 input | decode | filter | encode | output 的数据流!Codec 就是用来 decode、encode 事件的。Codec 的引入,使得 Logstash 可以更好更方便的与其他有自定义数据格式的运维产品共存,比如 graphite、fluent、netflow、collectd,以及使用msgpack、json、edn 等通用数据格式的其他产品等。

Logstash 提供了非常多的插件(Input plugins、Output plugins、Filter plugins、Codec plugins),可以根据需求自行组合。其中 Filter 插件 Grok 是 Logstash 最重要的插件。Grok 通过正则表达式匹配日志内容,并将日志结构化,所以理论上只要正则掌握的够娴熟,就能解析任何形式的日志,非常适合用来解析第三方服务产生的非结构化日志。但是如果是自己写的服务,就没必要将日志输出成非结构的,增加写正则的负担,所以在上述日志打印一节中才规定线上的日志输出成json形式,方便 Logstash 解析,Logstash 提供 json 的 Filter 插件。

Logstash 的配置文件默认放在 /etc/logstash/conf.d 目录下,如果需要采集多个项目的日志,每个项目的 Logstash 配置可能不一样,那就会在 conf.d 里存放多个配置文件,以每个项目命名方便管理。但是这样会带来一个问题,因为 Logstash 会将所有配置文件合并为一个,即一条日志通过input进入到Logstash后,会经过每个配置文件里的filter和output插件,造成对日志错误的处理和输出。解决方式是在Filebeat的fileds配置项里增加区分不同项目的field,如果日志路径就能区分不同项目的话也可以不用额外加field,用 Filebeat 自带的source字段就可以,然后在每个项目对应的 Logstash 配置文件里通过IF标识项目,项目各自的日志进各自的配置,互不干扰。

下列配置示例是对一个sample服务产生的json日志,通过Filebeat采集,用json的Filter插件进行解析,并将结果输出到标准输出。
input {
beats {
port => "5044"
}
}
// The filter part of this file is commented out to indicate that it is
// optional.
filter {
if [beat] and [source] =~ "sample" {
json {
source => "message"
}
ruby {
code => "event.set('time',(Time.parse(event.get('time')).to_f*1000000).to_i)"
}
}
}
output {
if [beat] and [source] =~ "sample" {
stdout { codec => rubydebug }
}
}

# 5 . 日志存储
InfluxDB vs. Elasticsearch

根据 DB-ENGINES 的排名,InfluxDB和Elasticsearch在各自专攻的领域都是NO.1,InfluxDB统治Time Series DBMS,Elasticsearch制霸Search engine,关于它们的原理和使用,各自都有非常详细的文档和资料,这里就不再赘述。

在时序数据方面,InfluxDB表现强劲,Elasticsearch在主要的指标上均远落于下风:

数据写入:同时起4个进程写入8百64万条数据,Elasticsearch平均为 115,422 条/秒,InfluxDB平均 926,389 条/秒,写入速度是Elasticsearch的8倍。这种写入速度的差距随着数据量的增大保持相对一致。
elastic-write-768x518.png

磁盘存储:存储相同的8百64万条数据,使用默认配置的Elasticsearch需要2.1G,使用针对时序数据配置的Elasticsearch需要517MB,而InfluxDB只需要127MB,压缩率分别是前两者的16倍和4倍。
elastic-compression.png

数据查询:在24h的数据集(8百64万条数据)里随机查询1个小时内的数据,按1分钟的时间间隔聚合,Elasticsearch和InfluxDB分别单进程执行1000次这种查询,算耗时的平均值。Elasticsearch耗时4.98ms(201次查询/秒),InfluxDB耗时1.26ms(794次查询/秒),查询速度是Elasticsearch的4倍。随着数据集的增大,查询速度之间的差距逐渐拉大,最大相差10倍之多。而且随着执行查询的进程数增加,InfluxDB的查询速度增幅显著,而且在不同数据集之间的查询速度基本一致,但是Elasticsearch增幅就不大,而且随着数据集的增大查询速度是递减的。
throughput.png

WechatIMG22.png

详细的比较说明参见:InfluxDB Markedly Outperforms Elasticsearch in Time-Series Data & Metrics Benchmark

Elasticsearch强在全文搜索,InfluxDB擅长时序数据,所以还是具体需求具体分析。如果需要保存日志并经常查询的,Elasticsearch比较合适;如果只依赖日志做状态展示,偶尔查询,InfluxDB比较合适。

轻松筹的业务各有特点,单一选择Elasticsearch或者InfluxDB都不能很好的查询日志和指标展示,所以有必要InfluxDB和Elasticsearch共存。在 Logstash 里配置2个输出,同一条日志输出2份,一份保留全部字段输出至 Elasticsearch;另一份过滤文本性的字段保留指标性的字段,然后输出至 InfluxDB。

InfluxDB如果作为Logstash的输出,有个坑需要注意,就是Logstash的InfluxDB插件支持的时间戳精度太粗,不能精确到纳秒,会导致同一个值的时间戳在插入InfluxDB的时候出现异常。因为InfluxDB用measurement名、tag集和时间戳来唯一标识一条记录。如果插入InfluxDB的一条记录与已经存在的一条记录measurement名、tag集和时间戳都相同,那么filed会是新老两条记录的集合,相同field的值会被新记录覆盖。 解决方式有2种,一种是增加一个tag来标识新记录。另一种是手动提升时间戳的精度,提升至微秒,理论上每天可以支持86,400,000,000条不重复的日志,可以很大程度避免时间戳的重叠,配置如下所示:
// 业务日志输出时时间戳格式化到微秒:2006-01-02T15:04:05.999999Z07:00

// Logstash的filter根据时间戳转换
filter {
ruby {
code => "event.set('time',(Time.parse(event.get('time')).to_f*1000000).to_i)"
}
}

# 6 . 数据展示
Grafana vs. Kibana
WechatIMG23.png

比较Kibana和Grafana,Kibana在图表展示上没有Grafana美观,而且Grafana的配置更加简单灵活。既然在日志存储中决定InfluxDB和Elasticsearch共存,展示上就也需要Kibana和Grafana共同协作,Kibana从Elasticsearch中检索日志,Grafana从InfluxDB和Elasticsearch中获取展示数据。下面2张图片展示了Grafana在轻松筹业务监控上的应用:
feed.png

sample2.png

# 7 . 异常报警
即使上述6个环节都建立了,如果没有报警一切都是没有意义的,因为不可能每时每刻都盯着曲线看,所以需要设置异常阈值,让监控系统定时检查,发现异常立即发送报警通知。

报警的服务有很多,但是数据展示的Grafana自带报警功能,功能也能满足我们的报警需求,而且配置简单,所以规则简单的报警可以采用Grafana的报警服务。不过Grafana的报警只支持部分数据库,分别是Graphite, Prometheus, InfluxDB 和 OpenTSDB,所以在Elasticsearch中的日志报警还需要Elastic Stack的X-Pack。
##Condition
image2017-4-20_15-10-32.png

如上图所示,可以设置报警检查的频率,报警条件是最近的5分钟内指定指标的平均值是否大于70,如果这个条件为True则触发报警。这种报警条件还比较单一,像错误数在十分钟内超过几次才报警,当前订单数与昨天同一时间的订单数比较跌了超过百分之几就报警,控制报警通知发送的频率,等等,Grafana就不能满足了,针对这种报警规则我们自己实现了一个报警引擎,用来满足这些比较复杂的报警规则。
##Notification
Grafana的报警通知只有在状态转换时才会触发,即报警状态的时候会发送告警通知,如果到恢复之前的一段时间里条件一直是满足报警条件的,Grafana不会一直发送通知,直到恢复的时候再发送一次恢复的通知。如果触发报警,Grafana支持4中通知方式:Email、Slack、Webhook 和 PagerDuty。其中Slack是国外的一种协作工具,类似钉钉,PagerDuty是一个收费的告警平台,所以可选的只剩下Email和Webhook了。下面简单的介绍如何配置Email和Webhook
##Email
Grafana的邮件配置很简单,可以利用QQ企业邮箱的smtp服务来发送报警邮件,邮件内容是配置的报警,配置比较简单:
[smtp]
enabled = true
host = smtp.exmail.qq.com:465
user = alert@qingsongchou.com
password = ********
from_address = alert@qingsongchou.com
from_user = Grafana

##Webhook
Webhook 就是在触发报警时,Grafana主动调用配置的http服务,以POST或者PUT方式传递json数据。这样就可以在我们自己开发的http服务里增加额外的通知方式,例如短信、微信甚至电话。
##Reception
配置了报警通知,不接收不去看也是白搭。一方面我们尽量实现多种通知途径,比如邮件、微信和短信。另一方面需要项目负责人接到报警及时响应,查看问题。
# Q&A
Q:针对Grafana不支持的报警,你们自己实现的报警引擎是直接在grafana的基础上修改的么,还是独立于Grafana呢?

A:我们用Go自己实现的一个报警引擎,独立于Grafana。



Q:Logstash 你们遇到过收集慢和丢日志的情况吗?现在你们Logstash收集日志到什么规模了?

A:我们目前的日质量大概每天2亿条,高峰时候每小时2000万条左右。Logstash运行的还可以,如果后期遇到手机慢,做简单的方式是扩机器,先解决问题,再想更好的优化策略。



Q:如果类似于Nginx、MySQL这种日志,类型增加需要解析每增加一个就要去改Logstash的grok吗?

A:针对常用的服务,grok已经提供了一些正则的pattern,例如你提到的Nginx、MySQL。目前是每增加一个就需要修改grok,后期可以实现一个UI来提高修改效率。



Q:这个lostash日志格式转换怎么学习?

A:Logstash有很完善的文档,感兴趣的话可以参考https://www.elastic.co/guide/en/logstash/current/index.html



Q:据说Logstash比较吃内存,fluentd作为EFK组合也经常出现,请问你们有没有做过选型呢?

A:当时选择了ELK,就没有做太多的选型了,Logstash吃内存的问题现在还不是太突出。



Q:日志的完整性怎么保证的?怎么知道没丢日志,或丢失了多少日志?

A:Filebeat和Logstash的输出插件都有一些重试的策略,但是也免不了日志丢失。日志的完整性确实和保证日志不丢也是我们目前在尝试解决的问题。



Q:请问监控系统需要考虑高可用吗?

A:肯定是要考虑高可用,当后期更多的业务依赖监控系统后,就要保证监控系统不挂,查询要快,实时监控,报警准确等。



轻松筹,一亿用户信赖的全民众筹平台!

以上内容根据2017年6月8日晚微信群分享内容整理。分享人施佳达,轻松筹GoLang高级工程师,北邮研究生,在分布式计算与舆情分析领域有深入研究,2015年滴滴出行公共平台负责滴滴出行Web APP后端研发,目前在轻松筹主要从事Feed系统架构设计以及重明鸟监控系统的建设。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

使用ELK处理Docker日志(一)

Dataman数人科技 发表了文章 • 0 个评论 • 19239 次浏览 • 2017-04-18 10:31 • 来自相关话题

【编者的话】Daniel Berman(Logz.io产品经理)为了纪念Docker四岁生日,撰写一系列文章,介绍如何使用ELK收集和处理Dockerized环境日志。小数今天给大家带来的第一部分将介绍如何安装各个组件以及不同日志收集方案的特点,下一部分将侧重 ...查看全部

【编者的话】Daniel Berman(Logz.io产品经理)为了纪念Docker四岁生日,撰写一系列文章,介绍如何使用ELK收集和处理Dockerized环境日志。小数今天给大家带来的第一部分将介绍如何安装各个组件以及不同日志收集方案的特点,下一部分将侧重于分析和可视化,近期发出,记得关注我们噢~
>
> PS:工程师们已奔赴奥斯汀DockerCON2017现场,更多最佳实践后天为您奉上!



【深圳站|3天烧脑式Kubernetes训练营】培训内容包括:Kubernetes概述和架构、部署和核心机制分析、进阶篇——Kubernetes调工作原理及源码分析等。


容器运行程序时产生的日志具有“无常,分布,隔离”等特点,因此在架构中收集Docker日志面临很大的挑战,有待尝试一种强有力的日志收集和处理方案来解决此类复杂问题。

ELK (Elasticsearch,Logstash和Kibana)是处理容器日志的一种方式,尽管设置ELK工作流并不容易(难度取决于环境规格),但最终可以使用Kibana的监控面板来展示Docker日志:

.

为了纪念Docker四岁生日,我们将撰写一系列文章,介绍如何使用ELK收集和处理Dockerized环境日志。第一部分将介绍如何安装各个组件以及不同日志收集方案的特点,并建立从容器中收集日志的工作流,下一部分将侧重于分析和可视化。

日志收集的流程

Dockerized环境中的典型ELK日志收集流程如下所示:


Logstash负责从各种Docker容器和主机中提取日志,这个流程的主要优点是可以更好地用过滤器来解析日志,Logstash将日志转发到Elasticsearch进行索引,Kibana分析和可视化数据。

当然这个流程可以有多种不同的实现方式, 例如可以使用不同的日志收集和转发组件, 如Fluentd或Filebeat 将日志发送到Elasticsearch,或者,添加一个由Kafka或Redis容器组成的中间层,作为Logstash和Elasticsearch之间的缓冲区。上图显示了日志从Docker到ELK的基本流程。

那么,如何设置这个流程呢?


组件安装


可以将ELK套件安装在一个容器里,也可以使用不同的容器来分别安装各个组件。



关于在Docker上部署ELK是否是生产环境的可行性解决方案(资源消耗和网络是主要问题)仍然存在很多争议,但在开发中这是一种非常方便高效的方案。


ELK的docker镜像推荐使用 docker-elk, 它支持丰富的运行参数(可使用这些参数组合不同的版本)和文档, 而且完全支持最新版本的 Elasticsearch, Logstash, 和 Kibana.


在安装组件之前需要确保以下端口没有被占用:5601 (Kibana), 9200 (Elasticsearch), and 5044 (Logstash).

同时需要确保内核参数 vm_max_map_count 至少设置为262144:
```
sudo sysctl -w vm.max_map_count=262144
```


运行如下命令:
```
git clone https://github.com/deviantony/docker-elk.git
cd docker-elk
docker-compose up
```

正常情况下, ELK套件的三个服务(Elasticsearch, Logstash, Kibana)会启动成功,默认持久化数据目录 /var/lib/elasticsearch (Elasticsearch 的数据存储目录)

sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

73aedc3939ad dockerelk_kibana "/bin/sh -c /usr/l..." 7 minutes ago Up 6 minutes 0.0.0.0:5601->5601/tcp dockerelk_kibana_1

b684045be3d6 dockerelk_logstash "logstash -f /usr/..." 7 minutes ago Up 6 minutes 0.0.0.0:5000->5000/tcp dockerelk_logstash_1

a5778b8e4e6a dockerelk_elasticsearch "/bin/bash bin/es-..." 7 minutes ago Up 7 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp dockerelk_elasticsearch_1




测试安装组件


可通过如下的方式来确保所有组件都能正常运行。

首先尝试访问Elasticsearch运行如下命令:
```
curl localhost:9200
```

输出结果:

```
{
"name" : "W3NuLnv",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "fauVIbHoSE2SlN_nDzxxdA",
"version" : {
"number" : "5.2.1",
"build_hash" : "db0d481",
"build_date" : "2017-02-09T22:05:32.386Z",
"build_snapshot" : false,
"lucene_version" : "6.4.1"
},
"tagline" : "You Know, for Search"
}
```

打开 Kibaba 页面通过http://[serverIP]:5601:



值得注意的是需要输入索引模式才能正常进行后续处理,这个稍后将会介绍。


发送Docker日志到ELK


安装组件比较简单,相比而言将Docker日志发送到ELK有点复杂,这取决于输出日志的方式。

如果没有额外指定,容器的stdout和stderr输出(也称为“docker logs”)输出到JSON文件。所以,如果是一个小型Docker环境,使用Filebeat来收集日志将是不错的选择。但如果使用其他日志记录驱动程序,则可能需要考虑其他方法。

以下是将日志导入ELK的三种不同的方法,切记,这并不能包含所有的方案。


# 使用Filebeat


Filebeat属于Elastic的Beats系列日志收集组件, Filebeat是用Go语言开发的,支持追踪特定文件和日志加密的中间组件,它可以配置将日志导出到Logstash或者直接导出到Elasticsearch.


如上所述,若使用默认的json文件记录驱动程序,Filebeat是一种相对简便的方式,可以输出日志到ELK.Filebeat部署在主机上,或将其作为容器与ELK容器一起运行(在这种情况下,需要添加到ELK容器的链接),这里有各种Filebeat Docker images可用,有些包括运行Filebeat并将其连接到Logstash的配置。

Filebeat配置将需要指定JSON日志文件的路径(位于:/ var / lib / docker / containers / ...)和目标的详细信息(通常是Logstash容器)。

下面是一个配置的例子
```
prospectors:
- paths:
- /var/log/containers/
document_type: syslog
output:
logstash:
enabled: true
hosts:
- elk:5044
```

# 使用日志驱动

Docker从1.12开始支持Logging Driver,允许将Docker日志路由到指定的第三方日志转发层,可将日志转发到AWS CloudWatch,Fluentd,GELF或NAT服务器。

使用logging drivers比较简单,它们需要为每个容器指定,并且将需要在日志的接收端进行其他配置。

在将日志发送到ELK的上下文中,使用syslog日志驱动可能是最简单的方法。


下面是一个指定Logging Driver的例子:
```
docker run \
--log-driver=syslog \
--log-opt syslog-address=tcp://:5000
\ --log-opt syslog-facility=daemon
\ alpine ash
```

如此这样运行每一个容器,结果是将Docker容器日志流输出到syslog实例,这些日志将转发到Logstash容器进行解析和数据增强,进入Elasticsearch。


# 使用Logspout

Logspout是Docker流行和轻量级的(15.2MB)日志路由器,它将附加到主机中的所有容器,并将Docker日志流输出到syslog服务器(除非定义了不同的输出目标)。
```
sudo docker run -d --name="logspout" --volume=/var/run/docker.sock:/var/run/docker.sock gliderlabs/logspout syslog+tls://:5000
```

使用Logstash module直接将日志路由到Logstash容器,但这需要其他配置和编译工作。


# Logz.io的日志采集器


本人在 In this blog post这篇文章中介绍了Logz.io的日志采集器,像Logspout一样,它附加在Docker主机中的所有容器上,但它不仅运送Docker日志,还包含Docker统计信息和Docker守护程序事件。
```
docker run -d --restart=always -v /var/run/docker.sock:/var/run/docker.sock logzio/logzio-docker -t
```

目前它是为Logz.io ELK 套件的用户设计的,我们正在努力将它开源项目。


数据持久化


配置Logstash来解析数据至关重要,因为这部分过程将添加上下文到容器的日志中,并能够更轻松地分析数据。

在Logstash配置文件中需要配置三个主要部分:输入,过滤和输出。 (若运行的是Logstash 5.x,则该文件位于:/ usr / share / logstash / pipeline)

输入取决于日志传送方式,使用Filebeat,则需要指定Beats输入插件。如果使用logspout或syslog日志记录驱动程序,则需要将syslog定义为输入。

过滤器部分包含用于分解日志消息的所有过滤器插件,依赖于正在记录的容器类型以及该特定容器生成的日志消息。

这部分的配置没有捷径,因为每个容器都输出不同类型的日志。有很多尝试和错误涉及,但是有一些在线工具可参考, 比如:Grok Debugger

导出部分将指定Logstash输出,例子中是Elasticsearch容器。

以下是通过syslog发送的Docker日志的基本Logstash配置示例。注意一系列过滤器的使用(grok,date,mutate和if条件):


input {
syslog {
port => 5000
type => "docker"
}
}

filter {
grok {
match => { "message" => "%{SYSLOG5424PRI}%{NONNEGINT:ver} +(?:%{TIMESTAMP_ISO8601:ts}|-) +(?:%{HOSTNAME:service}|-) +(?:%{NOTSPACE:containerName}|-) +(?:%{NOTSPACE:proc}|-) +(?:%{WORD:msgid}|-) +(?:%{SYSLOG5424SD:sd}|-|) +%{GREEDYDATA:msg}" }
}
syslog_pri { }
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
mutate {
remove_field => [ "message", "priority", "ts", "severity", "facility", "facility_label", "severity_label", "syslog5424_pri", "proc", "syslog_severity_code", "syslog_facility_code", "syslog_facility", "syslog_severity", "syslog_hostname", "syslog_message", "syslog_timestamp", "ver" ]
}
mutate {
remove_tag => [ "_grokparsefailure_sysloginput" ]
}
mutate {
gsub => [
"service", "[0123456789-]", ""
]
}
if [msg] =~ "^ *{" {
json {
source => "msg"
}
if "_jsonparsefailure" in [tags] {
drop {}
}
mutate {
remove_field => [ "msg" ]
}
}
}

output {
elasticsearch {
hosts => "elasticsearch:9200"
}
}



重新启动Logstash容器以应用新的配置。检查Elasticsearch索引,确保日志流能正常工作:

```
curl 'localhost:9200/_cat/indices?v'
```

具有Logstash模式的索引:


health status index               uuid                   pri rep docs.count docs.deleted store.size pri.store.size

yellow open logstash-2017.03.05 kgJ0P6jmQjOLNTSmnxsZWQ 5 1 3 0 10.1kb 10.1kb

yellow open .kibana 09NHQ-TnQQmRBnVE2Y93Kw 1 1 1 0 3.2kb 3.2kb



打开Kibana的页面


Kibana已经创建了'logstash- *' 索引是标识,按下“创建”按钮,可在Kibana中看到日志。


结语

Docker日志记录没有完美的方案,无论选择什么解决方案,使用日志记录驱动程序,Filebeat还是SaaS监控平台,每个方案都有优缺点。值得一提的是,Docker日志很有用,但它们只代表由Docker主机生成的数据的一个维度,检索容器统计信息和守护程序事件等还需要额外的日志记录层。

综上所述,Logz.io日志收集器提供了一个全面的日志解决方案,将三个数据流一起拉到ELK中。如需统计数据,建议尝试一下Dockerbeat.本系列的下一部分将重点介绍如何在Kibana中分析和可视化Docker日志。Docker 生日快乐!

Daniel Berman是Logz.io产品经理。擅长日志分析、大数据、云计算,热爱家庭,喜欢跑步,Liverpool FC和写颠覆性的技术内容。

原文链接:https://logz.io/blog/docker-logging/

Rancher体系下容器日志采集

Rancher 发表了文章 • 1 个评论 • 2529 次浏览 • 2017-04-12 10:52 • 来自相关话题

引言 一个完整的容器平台,容器日志都是很重要的一环。尤其在微服务架构大行其道状况下,程序的访问监控健康状态很多都依赖日志信息的收集,由于Docker的存在,让容器平台中的日志收集和传统方式很多不一样,日志的输出和采集点收集和以前大有不 ...查看全部
引言

一个完整的容器平台,容器日志都是很重要的一环。尤其在微服务架构大行其道状况下,程序的访问监控健康状态很多都依赖日志信息的收集,由于Docker的存在,让容器平台中的日志收集和传统方式很多不一样,日志的输出和采集点收集和以前大有不同。本文就探讨一下,Rancher平台内如何做容器日志收集。

当前现状

纵览当前容器日志收集的场景,无非就是两种方式:一是直接采集Docker标准输出,容器内的服务将日志信息写到标准输出,这样通过Docker的log driver可以发送到相应的收集程序中;二是延续传统的日志写入方式,容器内的服务将日志直接写到普通文件中,通过Docker volume将日志文件映射到Host上,日志采集程序就可以收集它。

第一种方式足够简单,直接配置相关的Log Driver就可以,但是这种方式也有些劣势:

1. 当主机的容器密度比较高的时候,对Docker Engine的压力比较大,毕竟容器标准输出都要通过Docker Engine来处理。
2. 尽管原则上,我们希望遵循一容器部署一个服务的原则,但是有时候特殊情况不可避免容器内有多个业务服务,这时候很难做到所有服务都向标准输出写日志,这就需要用到前面所说的第二种场景模式。
3. 虽然我们可以先选择很多种Log Driver,但是有些Log Driver会破坏Docker原生的体验,比如docker logs无法直接看到容器日志。

基于以上考虑,一个完整的日志方案必须要同时满足标准输出和日志卷两种模式才可以。当然完整的日志体系中,并不仅仅是采集,还需要有日志存储和UI展现。日志存储有很多种开源的实现,这个一般用户都会有自己钟情的选择,而UI展现更是各家有各家的需求,很难形成比较好的标准,一般都是通过定制化方式解决。所以此文主要展现的方案是日志采集方案,当然在存储和UI展现上会对接开源实现,没有特殊需求的情况下,也可以拥有一个完整的体验。



Rancher下的解决方案

如上面图中所示,日志存储和UI展现可以直接使用ElasticSearch & Kibana,日志采集方面如之前所分析,需要对接两种采集模式,所以这部分采用Fluentd & Logging Helper的组合,Fluentd是很通用的日志采集程序,拥有优异的性能,相对Logstash来说同等压力下,其内存消耗要少很多。Logging Helper是可以理解微Fluentd的助手,它可以识别容器内的日志卷文件,通知Fluentd进行采集。此外,由于要保证Dokcer和Rancher体验的完整性,在Docker Log Driver的选型上支持json-file和journald,其原因:一是json-file和journald相对来说比较常用;二是这两种驱动下,docker logs依然可以有内容输出,保证了体验的完整性。

下面开始说明,整个方案的部署过程。先用一张图来描述整体的部署结构,如下:



总共划分三个ENV,其中一个ENV部署ES & Kibana,另外两个ENV分别添加json-file驱动的主机和journald驱动的主机。详细部署过程如下:

创建三个ENV,使用Cattle引擎。设置Logging Catalog方便部署,在Admin–Settings页面中添加Catalog,地址为:https://github.com/niusmallnan/rancher-logging-catalog.git



进入ES-Kibana ENV中,部署ElasticSearch & Kibana,这两个应用在Community Catalog中均可以找到,部署非常简单,需要注意的是,建议选择Elasticsearch 2.x,Kibana中的Elasicsearch Source选择elasticseach-clients:



分配两台主机并安装Docker,其中Log Driver分别选择json-file和journald,并将主机添加到各自的ENV中。 在这两个ENV中添加External Link指向之前部署的Elasticsearch地址:



然后在Jsonfile & Journald ENV中添加Rancher Logging应用,打开对应的catalog,ES link指向刚才设定的External link, 其中Volume Pattern是日志卷的匹配模式,File Pattern是日志卷内的日志文件匹配模式:



以上部署完成之后,部署一些应用并产生一些访问日志,就可以在Kibana的界面中看到:



若要使用日志卷方式,则需要在service启动的时候配置volume,volume name需要匹配之前设定的Volume Pattern:



秉承一切开源的原则,相关实现可以查看一下链接:

1. https://github.com/niusmallnan/rancher-fluentd-package
2. https://github.com/niusmallnan/logging-helper
3. https://github.com/niusmallnan/rancher-logging-catalog

总结

通过Fluentd我们可以对接很多第三方日志存储体系,但是Fluentd自身并不能完成日志采集的所有场景,所以非常需要Logging Helper的帮助。通过Logging Helper可以定制出一些额外采集规则,比如可以过滤某些容器日志等等。当然真正大规模生产环境日志平台,其实是对整个运维体系的考验, 单纯靠开源程序的组合并不能真正解决问题。

原文来源:Rancher Labs

Docker监控及日志采集神器

Rancher 发表了文章 • 1 个评论 • 5034 次浏览 • 2017-01-24 09:27 • 来自相关话题

由Rancher社区维护的应用商店最近迎来了两个明星项目——SPM 和 Logsene,来自Sematext的监控与日志工具。如果你已经熟悉Logstash,Kibana,Prometheus,Grafana这些监控或日志解决方案,那么请认真阅读本文,它将向你 ...查看全部
由Rancher社区维护的应用商店最近迎来了两个明星项目——SPM 和 Logsene,来自Sematext的监控与日志工具。如果你已经熟悉Logstash,Kibana,Prometheus,Grafana这些监控或日志解决方案,那么请认真阅读本文,它将向你展示SPM和Logsene为Rancher用户带来了什么样的功能,和其它解决方案有着什么样的差异。

#接触Sematext Docker Agent

Sematext Docker Agent是一个时下Docker原生的监控及日志采集代理(Agent)程序。它在每一个Docker宿主机运行一个非常小的容器,用以为所有集群节点以及这些节点上的容器采集日志、系统指标与事件。Agent代理程序监听所有Rancher管理的节点,在部署Sematext Docker Agent后,所有的日志、Docker事件、各项指标都能被外部所访问。

这将变得很有价值,为什么呢?因为它意味着你不再需要耗费几个小时甚至好几天时间去弄明白究竟需要采集哪些数据或如何将它们图表化。还有,你不需要花资源来维护你自己的日志监控体系,你的Docker系统指标及事件都会输出给SPM 而日志将输出给Logsene(SPM是一个应用程序性能监控服务,它支持与诸多平台进行集成,这当然也包括Docker,而Logsene 是一个日志管理服务,一个托管于Rancher的ELK应用栈,它能很好的和Kibana和Grafana一并工作)




#DevOps工具对比

有一些Docker日志与指标处理的开源工具供我们选择,比如cAdvisor以及Logspout。遗憾的是,这些工具都不具备足够的综合能力。一种解决办法是集成一系列工具来达成目标,可是这样的后果是把体系带向“Franken-monitoring(指技术大杂烩,各个组件并不能按承诺的功能正常运行)”的方向,用户将因此而背负沉重的技术债,也没有人会愿意解决这种复杂的故障。

因此,另一种解决办法像Sematext Docker Agent这样的工具,则只是将cAdvisor和Logspout进行了结合,其功能尤其关注日志管理,比如格式检查,日志语法分析,数据改进(Geo-IP地址地理位置信息,元数据标签等)以及日志路由。

#通过Rancher Catalog配置Sematext Docker Agent

在Rancher平台设置Sematext Docker Agent,你只需要选择合适的catalog模板即可(在Rancher的社区Catalog条目下查找“Sematext” )。我们来快速的浏览一下Sematex提供了哪些功能?如何在Rancher平台对其进行设置?

Docker Compose及Kubernetes自动日志标签

所有的日志均被加上了元数据标签,这包含了对Docker/Rancher Compose项目及Kubernetes的支持:

针对Docker Container

- 容器ID
- 容器名
- 镜像名


针对Docker/Rancher Compose

- 服务名
- 项目名
- 容器数(如果你设置了Scale=N)

针对Kubernetes

请注意Kubernetes容器的日志和其它Docker容器的日志并没有什么很大的不同,然而Kubernetes用户需要访问已部署的pods的日志,因此,为日志搜索而抓取Kubernetes特有的信息变得非常有用,例如:

- 命名空间
- Pod名称
- 容器名称
- Kubernetes UID

诀窍:如需启用Kubernetes标签,请设置Kubernetes=1



#日志路由

对于较为庞大的部署,你也许需要针对不同租户或应用对日志进行索引,将其输出到不同的路径或Logsene应用处理(这样你也可以区分不同的用户对不同日志的访问权)。

我们使这个变得非常简单:为你的容器简单地添加一个Docker标签,或设置LOGSENE_TOKEN环境变量(LOGSENE_TOKEN=your app token),于是Sematext Docker Agent会将日志发送至正确的索引项!用这种方式你完全不需要一个中心配置文件来映射容器和索引项/令牌,于是日志路由变得非常灵活,动态与弹性化。

#集成的日志语法分析器

日志的处理基于Docker API以及一个叫做logagent-js的库,该项目被Sematext所开源。这个分析框架包含了日志格式检测和分析标准正式Docker容器所使用的不同日志格式的模式:

- Web服务器,例如Nginx、Apache httpd或其它使用常见Web服务器日志格式
- 搜索引擎,类似Elasticsearch和Solr
- 消息队列,类似Apache Kafaka及nsq.io
- 数据库,类似MongoDB, HBase, MySQL
- 检测JSON日志格式,通常被Node.js程序所使用,例如bunyan和winston日志框架

提示: 如果要创建自定义模式,请在Rancher Catalog模板里把它们添加到叫做LOGAGENT_PATTERNS的字段里。



#自动的容器日志Geo-IP增强项

从Docker容器之外获取到经过采集运送并分析后的日志已经节约了大量的时间,但是有一些应用日志需要从其它数据源获取额外的增强信息。一个常见的案例是增强Web Server的日志信息(或者说任意包含IP地址信息的日志),为日志中的IP地址提供其地理位置信息。

Sematext Docker Agent 支持Geo-IP enrichment of docker logs。它使用Maxmind Geo-IP轻量数据库,它能为你定期的提供更新信息,无需停止容器或为其挂载包含Geo-IP数据库的新卷,或任何其它手动操作。

诀窍: 如果需要开启Geo-IP增强功能,请设置环境变量GEOIP_ENABLED=true。



#过滤容器日志

在某些场景,我们只需要收集重要应用的日志而忽略掉那些较低优先级的或较为嘈杂的服务日志(例如那些频繁的清理工作)。这样我们可以使用白名单或黑名单(针对容器名或镜像名)来处理这些容器即可,其设置采用正则表达式匹配相应的元数据字段。




#如何使用Sematext Catalog项目

在Rancher的UI里,进入社区的Catalog项目列表,搜索关键字“sematext”、“monitoring”或“logs”即可。



点击“View Details”,在“Configuration Options”选项里输入SPM和Logsene App的tokens。你可以从这里进行注册并创建你的SPM和Logsene应用,然后即可获取这些访问令牌(tokens)。如果你的Rancher集群运行在防火墙(代理)之后, 你需要在HTTPS_PROXY或 HTTP_PROXY环境变量处填写proxy URL。如果你在这个集群里同时也运行了Kubernetes,请选择KUBERNETES=1。

如果你想收集所有的日志,不要填写任何容器或镜像名的过滤值,直接点击“Launch”即可。





#总结

我们希望这篇对Rancher平台中Sematext Docker Agent的介绍,能帮助你在开始对Docker进行监控与日志处理时,不用采用大杂烩的繁琐模式。该项目完整的配置参数可从Github获得参考。 我们相信新的Catalog模板已经能覆盖最常用的选项,如果你发现一些重要项目缺失,请将其提交至Rancher community catalog(提交issue或是pull request)。结合Rancher试用一下Sematext Docker Agent 吧,所有服务将被轻松接管,你将就此高枕无忧。Rancher Community Catalog让日志监控系统能瞬间设置并运行起来,一切都变得如此容易。


原文来源:Rancher Labs
> 原文作者:Stefan Thies
> 译者:彭攀(Alan Peng),Rancher中国社区技术专家委员会成员。现为睿云智合项目交付团队技术负责人。

DockOne微信分享( 一零二):基于容器的日志管理实践

Dataman数人科技 发表了文章 • 1 个评论 • 4378 次浏览 • 2017-01-06 16:15 • 来自相关话题

【编者的话】业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。 20 ...查看全部
【编者的话】业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。

2013年以来Docker迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控、日志、网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验。
# 基于ELK的日志管理系统架构
日志收集是大数据的基础,业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行分析处理;高可用性,高可靠性以及可扩展性是日志收集系统的必备要素。

ELK是目前较流行的日志一体化解决方案,提供日志收集、处理、存储、搜索、展示等功能。容器标准输出日志常用的查询方式是通过Docker命令 docker logs containerid来查看,容器内日志受容器隔离性影响不便于收集,因此当面对大型系统,用单一命令管理日志是不可行的,需要一个对于容器日志统一检索管理的方案。基于ELK实践了一套容器日志管理系统,架构如下:
1.png

# 日志采集
传统的日志采集有较成熟的解决方案,如Flume、Logstash等,但传统的采集方案不适用于容器日志。Docker本身提供了LogDriver功能,可以利用不同的driver把日志输出到不同地方,LogDriver具体有以下几种:

* None(将日志设置成不再输出)
* json-file(Docker默认的LogDriver,将日志以JSON文件的方式存储在本地)
* Syslog(标准输出日志可通过该方式传输)
* Journal
* SELF
* Fluent
* awslogs
* Splunk
* etwLogs
* gcplogs

对于这些LogDriver就不一一详细介绍了,大家有兴趣可以去Docker官网查看。可见Docker对日志提供了较为丰富的处理方式,供选择的还有优秀的开源项目Logspout等,然而这并不能满足所有的使用场景。

容器的标准输出日志可从以上驱动中选择,由于大多数用户选择标准化输出日志,故Docker没有提供采集功能,如果将日志内的文件挂载出来进行采集,多个实例同名日志则会无法区分,容器内文件日志处理、错误日志多行处理等问题时有发生,若想标准输出日志和容器内文件日志兼得,则需自己动手丰衣足食,以下为数人云日志采集系统实践。
##1. 标准输出日志
针对Marathon + Mesos环境开发了一套日志采集工具,Docker的标准输出日志json-file默认持久化在本地上,Mesos对于标准输出日志也存了一份在Sandbox下:
2.png

因此标准输出日志也可以通过Mesos文件的方式进行采集。
##2. 容器内文件日志
平台支持的文件存储是Overlay,避免了许多复杂环境的处理。关于Overlay盗用一张图:
3.jpg

容器的存储驱动运用写时复制(Copy On Write),Overlay主要分为lower和upper, 当需要修改一个文件时,使用CoW将文件从只读的Lower层复制到可写层Upper层进行修改,在Docker中,底部的只读层是image,可写层是Container,因此容器内日志在宿主机上通过Upper的文件系统可找到,例如在容器内的/var/log/test.log中写一个test字符,如图:
4.png

同理,无论是标注输出的日志还是容器内文件日志,都可以通过文件的方式进行处理,也可以同时把json-file关闭,以减轻Docker本身的压力。
##3. 自研日志采集工具
基于上述方式开发了一款日志采集工具,对日志进行统一收集管理,日志通过TCP把JSON格式化的日志输出到Logstash,包括应用ID,容器Name,容器ID,TaskID等,当然开发的过程中也遇到许多问题,如断点续传和错误日志多行处理等功能,这其中参考了Filebeat(Go语言开发)对于日志处理的方式,个人认为如果是对于传统文件日志处理,Filebeat是不错的选择,日志采集功能第一步支持:

* 容器标准输出日志采集
* 容器内文件日志采集,支持同时采集多个文件
* 断点续传 (如果Agent崩溃,从上次offset采集)
* 多行日志合并 (如:多行错误日志合并)
* 日志文件异常处理 (如:日志被rotate可以重新采集)
* TCP传输
* --add-env --add-label标签,可以通过指定命令把container的env或者label加到日志数据里,如(--add-env hostname=HOST --add-env test=ENV_NAME1 --add-label tlabel=label_name)
* Prometheus指标数据

日志处理需要提供快速的数据处理能力,在开发过程中遇到了性能问题,CPU占用非常高,针对该问题对程序作调优,使用Golang内置的包net/http/pprof,对Golang程序调优很好用,可将程序中每个函数占用CPU内存的比例通过生成SVG的方式直观的反映出来,如图:
5.jpg

Golang内置包encoding/json json的序列化、正则、反射、字节转字符串对于资源的消耗也比较高,可针对以上几方面以及程序本身进行调整。
# 日志存储后端架构
日志存储功能有Logstash、Heka、Fluentd等方案,Logstash基于R uby,支持功能丰富,但性能方面诟病较多;Heka基于Go,性能方面比Logstash好很多,不过Heka好像已经不维护了。综合考虑社区活跃度、迭代速度以及稳定性方面最终选择了Logstash,实际应用过程中比较重要的参数如下:

* --pipeline-workers (命令行参数)
* --pipeline-batch-size (命令行参数)
* LS_HEAP_SIZE=${LS_HEAP_SIZE} (根据自己的实际情况填写,可以写到环境变量活着命令行参数里面)
* workers => 8(根据自己实际情况,一般等于CPU数,配置文件参数)
* flush_size => 3000(根据自己的实际情况测试)

以上参数仅供参考,可根据实际环境进行调试。如果日志量较大,为了确保架构的稳定性,可以在中间加一层消息队列,比较常用的有Kafka、Redis等,相信大家对这方面应用比较多,不再赘述。

ES应该是索引存储的不二选择,整个架构的缓解包括ES通过Docker的方式部署,压测时用Marvel对ES的索引方式监控等,网上有很多调优资料,可自行实验。日志的展示是通过自己定制的,Kibana本身的功能比较强大的同时也略微有些学习成本,最终客户想要的是很简单的东西。

压测工具选择的是分布式压测工具Tsung,通过压测一个应用产生日志然后通过Log-Agent对日志进行采集,模拟真实环境日志采集。
# 日志告警
日志处理中,关键字报警是一个重要功能,对于监控报警主要用Prometheus + Alertmanager实现。应用运行过程中,根据日志关键字告警部的应用场景,从Logstash部分对日志做分流(具体方案可以看上面图的报警部分),自研grok_export对日志进行过滤分析生成Prometheus格式的数据,然后从Prometheus配置报警策略通过alertmanager报警。Log-Agent本身也支持Prometheus数据,Prometheus通过特定的规则查看日志的统计信息。

* Prometheus:
Prometheus是开源的监控告警系统,通过pull的方式采集时间序列,以及用http传输,数据存储在本地,支持丰富的查询语法和简单的Dashboard展示。

* Alertmanager:
Alertmanager作为Prometheus的组件,所有达到阀值的时间都通过Alertmanager报警,Alertmanager支持非常强大的告警功能,包括http、email通知,以及静默重复报警屏蔽等功能。

以上是数人云在实践容器日志系统过程中遇到的问题,更高层次的应用包括容器日志分析等,还有待继续挖掘和填坑,欢迎大家提出建议,一起交流。
#Q&A
Q:Overlay 是没有实现 inotify 接口的,是咋获取文件日志增量数据的?

A:通过循环读取文件的方式,记录文件offset。



Q:既然主要框架是 ELK,采集端不直接用 Filebeat 是因为 Filebeat 有局限性吗?

A:Filebeat没有满足我们产品基于Docker的需求,等于上面加了Docker的逻辑。



Q:自研的日志系统,打出来的每条日志格式都是规定好的吗?开发中每个人都要按这个规范来做吗?不管是什么级别的日志?

A:其实并没有,但是如果是内部使用,能规约好当然更好,可以更方便的处理,而且可以做更细粒度的分析。



Q:日志收集有做分析展示处理吗?用什么处理的。

A:对于日志内容的分析还没做,例如Nginx请求日志还是有分析意义的。



Q:采集方面有考虑直接使用系统的Syslog和Logrotate吗?

A:用过Syslog后来因为容器内的文件日志需求重新开发的。



以上内容根据2017年1月5日晚微信群分享内容整理。分享人郭已钦,数人云研发工程师。早期从事Java&JavaScript开发,爬虫大数据开发,之后开始写Go,参与开源容器管理工具Crane的研发与维护,目前在数人云做云平台研发工作。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

容器内应用日志收集方案

Rancher 发表了文章 • 1 个评论 • 2955 次浏览 • 2016-12-16 09:16 • 来自相关话题

原文来源:Rancher Labs 容器化应用日志收集挑战 应用日志的收集、分析和监控是日常运维工作重要的部分,妥善地处理应用日志收集往往是应用容器化重要的一个课题。 Docker ...查看全部
原文来源:Rancher Labs

容器化应用日志收集挑战

应用日志的收集、分析和监控是日常运维工作重要的部分,妥善地处理应用日志收集往往是应用容器化重要的一个课题。

Docker处理日志的方法是通过docker engine捕捉每一个容器进程的STDOUT和STDERR,通过为contrainer制定不同log driver 来实现容器日志的收集,缺省json-file log driver是将容器的STDOUT/STDERR 输出保存在磁盘上,然后用户就能使用docker logs 来进行查询。

在部署一个传统的应用的时候,应用程序记录日志的方式通常记录到文件里, 一般(但不一定)会记录到/var/log目录下。应用容器化后,不同于以往将所有日志放在主机系统的统一位置,日志分散在很多不同容器的相互隔离的环境中。

如何收集应用写在容器内日志记录,有以下挑战:

1) 资源消耗
如果在每个容器运行一个日志收集进程, 比如logstatsh/fluentd 这类的日志工具,在主机容器密度高的时候,logstatsh/fluentd这类日志采集工具会消耗大量的系统资源。上面这种方法是最简单直观的,也是最消耗资源的。

2) 应用侵入
一些传统应用,特别是legacy 系统,写日志机制往往是没法配置和更改的,包括应用日志的格式,存放地址等等。日志采集机制,要尽量避免要求修改应用。

3) 日志来源识别
采用统一应用日志收集方案,日志分散在很多不同容器的相互隔离的环境中,需要解决日志的来源识别问题。

日志来源识别的功能借助了rancher平台为container_name的命名的规则特性,可以做到即使一个容器在运行过程中被调度到另外一台主机,也可以识别日志来源。

容器化应用日志收集方案

下面是我们设计的一个低资源资源消耗、无应用侵入、可以清楚识别日志来源的统一日志收集方案,该方案已经在睿云智合的客户有成功实施案例。



在该方案中,会在每个host 部署一个wise2c-logger,wise2C会listen docker engine的event,当有新容器创建和销毁时,会去判断是否有和日志相关的local volume 被创建或者销毁了,根据lables,wise2c-logger 会动态配置logstatsh的input、filter 和output,实现应用日志的收集和分发。

1) 应用如何配置
应用容器化时候,需要在为应用容器挂载一个专门写有日志的volume,为了区别该volume 和容器其它数据volume,我们把该volume 定义在容器中,通过volume_from 指令share 给应用容器,下面是一个例子:demo应用的docker-compose file



web-data 容器使用一个local volume,mount到/var/log目录(也可以是其它目录),在web-data中定义了几个标签, io.wise2c.logtype说明这个容器中包含了日志目录,标签里面的值elasticsearch、kafka可以用于指明log的output或者过滤条件等。

那么我们现在来看下wiselogger大致的工作流程:



监听新的日志容器->获取日志容器的type和本地目录->生成新的logstash配置:

1)wise2c-looger 侦听docker events 事件, 检查是否有一个日志容器创建或者被销毁;

2)当日志容器被创建后(通过container label 判断), inspect 容器的volume 在主机的path;

3)重新配置wise2c-logger 内置的logstatsh 的配置文件,设置新的input, filter 和output 规则。



这里是把wise2c-logger在rancher平台上做成catalog需要的docker-compose.yml的截图,大家可以配合上面的流程描述一起看一下。

优化

目前我们还在对Wise2C-logger 作进一步的优化:

1)收集容器的STDOUT/STDERR日志
特别是对default 使用json-file driver的容器,通过扫描容器主机的json-file 目录,实现容器STDIN/STDERR日志的收集。

2)更多的内置日志收集方案
目前内置缺省使用logstatsh 作日志的收集,和过滤和一些简单的转码逻辑。未来wise2C-logger 可以支持一些更轻量级的日志收集方案,比如fluentd、filebeat等。

Q & A

Q:有没有做过性能测试?我这边模块的日志吞吐量比较大。比如在多少量级的日志输出量基础上,主要为logger模块预留多少系统资源,保证其正常稳定工作?
A:没有做过很强的压力,但是我们现在正常使用倒没碰上过性能上的瓶颈。我们现在没有对logger做资源限制,但是能占用300~400M内存,因为有logstash的原因。

Q:「生成日志容器」是指每个应用容器要对应一个日志容器?这样资源消耗不会更大吗?k8s那种日志采集性能消耗会比这样每个应用容器对应一个日志容器高么?
A:是指每个应用容器对应一个日志容器。虽然每个应用有一个日志容器,但是,日志容器是start once的,不会占用运行时资源。

Q:你说的start once是什么意思?我说占资源是大量日志来的时候,那么多日志容器要消耗大量io的吧,CPU使用率会上升,不会影响应用容器使用CPU么?
A:不会,日志容器只生成一下,不会持续运行。

Q:怎么去监听local volume?
A:可以监听文件目录,也可以定时请求docker daemon。

Q:直接用syslog driver,能做到对应用无侵入么?
A:启动容器的时候 注明使用Syslog driver的参数即可,这样几乎没有额外资源占用。

Q:这种方案是不是要保证应用容器日志要输出到/var/log下啊?
A:不是,可以随意定义,logstah可以抓syslog。

Q:syslog driver能收集容器内的日志文件么?容器内不同流向的日志能区分么?
A:容器内应用的本地日志syslog可以收集,分流同样可以完成,但是容器内的本地日志这个我个人觉得跟容器环境下的应用无本地化、无状态化相悖吧。

Q:最后你说到,重新配置logstash中配置文件,看上去感觉你又是通过wiselog这个容器去采集所有日志的?只不过是动态配置logstash里面参数。
A:是的,现在收集工作是logstash来完成的,单纯的文件收集,可选的方案还挺多的,也没有必要再造轮子了。

Q:那这个方案其实有个疑问,为什么不学k8s那种,直接固定那目录,通过正则表达式去采集日志文件,而要动态这么做?有什么好处吗?目前我感觉这两套方案几乎一样。
A:为了减少对应用的侵入。因为很多用户的现有系统不能再修改了,这样做也是为了减少用户现有程序的修改,为了最重要的“兼容现有”。

Q:除了kibana还有没别的可视化方案?
A:针对es来说,还没有别的更好的方案。

Q:如果是挂载log目录,logstash就可以去宿主机收集了,还需要别的插件做什么?
A:通过容器可以识别出来这个应用的业务上的逻辑,可以拿到service名称。

Q:有的应用输出的log名都是一样的,不会有冲突吗,比如我启动2个容器在一个宿主机上,都往xx.log里写入会有问题。
A:不会,给每一个应用容器配一个日志卷容器就可以解决这个问题。这个问题也是我们出方案时一个棘手的问题。所以这个方案的一个好处就是,每一个应用的都可以随意设置日志目录,不用考虑和别的应用冲突,也不会和同宿主机同一应用冲突。

Q:上次听别人说全部把日志扔到标准输出里,不知道靠谱不?
A:有人报过这种处理方式,日志量大时,docker daemon会崩溃。

如何在 Rancher 中统一管理容器日志

Rancher 发表了文章 • 1 个评论 • 2674 次浏览 • 2016-12-05 09:40 • 来自相关话题

原文来源:Rancher Labs 相信大家对于容器和 docker 这个概念并不陌生,很高兴的是 docker 为我们提供了多种log-driver。 我们在使用 docker ...查看全部
原文来源:Rancher Labs

相信大家对于容器和 docker 这个概念并不陌生,很高兴的是 docker 为我们提供了多种log-driver。



我们在使用 docker 处理日志的时候多数是采用 docker logs 命令,因为 docker 默认采用的 log-driver 是 json-file,所以 docker 会捕捉每一个容器进程 STDOUTS 和 STDERR,保存在磁盘文件.json.log 中供 docker logs 命令查询。



上述方式如果用于开发过程中的调试工作,是种快速且不错的方案,但是如果面对大规模应用部署的环境下那么日志的跟踪与调试带来的困扰显而易见,因此我们需要一个统一集中的容器日志收集与展示平台。

对于容器日志收集与展示,syslog + rsyslog + ELK(ElasticSearch、Logstash、Kibana)是一个不错的技术方案,我将简单介绍下为什么我们选用这种方案。

Syslog 是一种 RFC 协议,与平台无关,且是 UNIX 标准的日志解决方案,集成度良好。rsyslog 顾名思义是 remote 的意思,使 syslog 具备收集远端日志的功能,由于 logstash 采用 java 和 jruby开发,所以 logstash 文件库中可以加入 windows 日志文件。而 logspout 暂不支持容器-t(tty) 启动。

我们庆幸的是 Rancher 的 Catalog 真的很强大,Rancher Catalog 已经为我们提供了 ELK 的Catalog,下面我将给出 ELK 在 Rancher 中的部署视图,并简单介绍下视图中每个组件都是干什么的。



- logstash-collector:用于接收 docker container 发送过来的日志信息,并将日志信息发送到redis 队列中。在 rancher 中默认开启 TCP:6000 UDP:5000 端口用于侦听发送过来的日志报文。
- redis:日志消息队列。
- logstash-indexer:用于接收redis中未处理的日志信息,然后将该日志消息发送到elasticsearsh中进行存储及搜索分析。
- kopf:elasticsearch 的一款第三方插件,提供一个简单的管理员 web 界面。
- elasticsearch-clients:用于处理路由请求,协调数据节点与主节点。
- elasticsearch-master:用于集群操作相关的内容。
- elasticsearch-datanode: 用于存储索引数据的节点。

上述部署视图中说好的 Kibana 哪儿去了?

因为我们有自己的日志展现平台,所以这里去掉了 kibana,如果你想在 Rancher 中使用 Kibana做日志前端展现,那么很简单,只需要利用 Rancher 的 Catalog,service link:Rancher 环境中上述已经部署好的 elasticsearch-client 即可。

至此,在 Rancher 中如何部署一套完整 ELK 系统已经介绍完了,下面我将介绍如何将容器日志发送到 ELK 中。




为了完成上述的目标,我们还需要做一些准备工作,那就是需要一个运行 rsyslog 的容器。如果你不想基于 alpine 去制作 rsyslog 镜像,那么可以使用 panoptix/rsyslog 这个镜像。

下面就是关键的一步:如何让 rsyslog 发送日志到 logstash 中。

上述 rsyslog 容器启动好之后我们需要告知 rsyslog,目的接收端 logstash 的地址。过程很简单,需要在容器中/etc/rsyslog.d/ 目录下建立一个文件 60-logstash.conf



:programname, contains, “docker”的意思是过滤日志,只有 Properties 中 key 为 programname,value 包含 docker 字样的日志才会被发送给 logstash

`.`@@logstash-collector:6000;json-template 是所有用户的所有日志通过 tcp 传输到logstash-collector 的 6000 端口并且日志使用 json-template 格式化。

同样我们需要建立 01-json-template.conf,property 的 key 值我们可以通过 rsyslog 官网获取。



下面我将介绍 rsyslog 如何收集容器日志。

首先我们需要修改我们的应用容器 log-driver 为 syslog(可以通过 rancher-ui 或者rancher-compose)来完成。

其次我们需要设置我们日志接收端 rsyslog 地址,可以通过 log_opt 指定syslog-address:hostname:tcp_port 来完成。

log_opt 可以指定许多 syslog 支持的选项比如 facility 等,在此不一一列举。目前日志显的杂乱无序。如何去按照 container 或者 stack 或者 service 去区分日志呢?

syslog 的 tag 属性为我们支持了自定义的标签,通过打 tag 的方式我们可以细粒度的自行切分日志。

Rancher 对 docker 的亲和性极大程度的为我们提供了遍历。我们可以通过 go templage 语法去获取 rancher 环境下容器的特征值从而协助我们切分日志信息。



OK,现在我们再去查看 kibana 发现我们的容器日志已经展示在这里了。



最后我们可以按照 rancher catalog 规范,制作一键部署应用。

Docker 1.13.0 详细更新日志

田浩浩 发表了文章 • 0 个评论 • 6358 次浏览 • 2016-11-16 16:49 • 来自相关话题

【编者的话】Docker发布1.13.0版本,此次版本更新内容较多,以下为该版本具体的变更。 ##构建 * 添加在构建时可以指定镜像用作高速缓存源的功能。 这些镜像不需要有本地父链还可以从其他registri ...查看全部
【编者的话】Docker发布1.13.0版本,此次版本更新内容较多,以下为该版本具体的变更。

##构建

* 添加在构建时可以指定镜像用作高速缓存源的功能。 这些镜像不需要有本地父链还可以从其他registries拉取 #26839
* (试验功能)添加选项用以在成功构建之后,将镜像层级压缩到`FROM`镜像 #22641
* 修复`Dockerfile`解析空行后的逸出 #24725
* 在`docker build`时添加步数 #24978
* 在镜像构建时添加支持压缩构建 #25837
* 在`docker build`中添加`--network`参数 #27702
* 修复了在`docker build`以及`docker run`时`--label`参数的不一致行为 #26027
* 修复了当使用overlay储存驱动时镜像层级的不一致 #27209
* 现在允许使用不用的构建参数。将显示警告信息而不是错误和失败的构建 #27412
* 修复了Windows上的构建缓存问题 #27805

##贡献

* 为`Ubuntu Xenial on PPC64`添加支持构建docker debs #23438
* 为` Ubuntu Xenial on s390x`添加支持构建docker debs #26104
* 为`VMWare Photon OS`添加`RPM`构建 #24116
* 在`tgz`添加docker命令补全 #27735
* 更新安装脚本允许在中国使用镜像安装 #27005
* 为`Ubuntu 16.10 Yakkety Yak`添加`DEB`构建 #27993
* 为`Fedora 25`添加`RPM`构建 #28222

##发行版

* 更新`notary`依赖版本到0.4.2(完整的更新日志在这里#27074
* 当不同的用户将相同的层级推送到验证`registry`时, 避免不必要的blob上传 #26564
* 允许外部存储用于`registry`的凭据 #26354

##日志

* 标准化所有的日志记录驱动程序的默认日志记录标记值 #22911
* 在记录长日志时,改善了性能和内存的使用 #22982
* 为windows启用syslog驱动程序 #25736
* 添加Logentries驱动程序 #27471
* 更新AWS日志驱动程序来支持标记 #27707
* 为` fluentd`添加支持`Unix socket` #26088
* 在Windows上启用`fluentd`日志驱动程序 #28189
* 当用作`journald`字段名称时, 清理docker标签 #23725

##网络

* 添加`--attachable`支持用于启用`docker run`在swarm模式的overlay网络上运行 #25962
* 添加在`docker service create`时使用`--port`选项来支持services中host端口的PublishMode #27917
* 为Windows server 2016添加支持overlay网络驱动 (需要即将到来的ws2016更新) #28182
* 修改默认的`FORWARD`政策为`DROP` #28257
* 在windows上添加支持对预定义网络指定静态IP #22208
* 修复了在`docker run`使用IPv6地址时`--publish`参数失灵的问题#27860
* 修复了`inspect`网络是显示带有mask的gateway #25564
* 修复了在桥接网络中多个地址可能引起`--fixed-cidr` 没有正确的地址 #26659
* 在`docker network inspect`中添加创建时间戳 #26130
* 在`docker network inspect`swarm overlay网络时显示对等节点 #28078
* 为服务VIP地址启用ping #28019

##插件

* 插件功能正式上线 #28226
* 在`docker plugin remove`添加`--force`参数 #25096
* 支持动态重新加载授权插件 #22770
* 在`docker plugin ls`添加描述 #25556
* 为`docker plugin inspect`添加`-f` / `--format`参数 #25990
* 添加`docker plugin create`命令 #28164
* 发送请求的TLS同等证书给授权插件 #27383
* 在swarm模式中支持全局范围网络以及`ipam`插件 #27287

##远程API(v1.25) 以及 客户端

* 支持从一个Compose文件用于`docker stack deploy` #27998
* (试验功能) 实现checkpoint以及restore #22049
* 为`docker info`添加`--format`参数 #23808
* 从`docker volume create`移除`--name`参数  #23830
* 添加`docker stack ls` #23886
* 为`docker ps`添加新过滤`is-task` #24411
* 为`docker service create`添加`--env-file`参数 #24844
* 为`docker stats`添加`--format`参数 #24987
* 在swarm模式中使`docker node ps`模式是`self` #25214
* 在`docker service create`添加`--group` #25317
* 在service/node/stack ps输出中添加`--no-trunc` #25337
* 为`ContainerAttachOptions`添加日志用于go客户端可以请求检索容器日志做为attach进程的一部分 #26718
* 允许客户端访问旧版本服务 #27745
* 告知用户客户端移除容器正在进行中 #26074
* 为/info添加`Isolation` #26255
* 为/info添加`userns` #27840
* 在service终端请求时不允许同时有多个模式 #26643
* 为/containers/create API添加更为详细安全的指定挂载的功能 #22373
* 为`network ls`以及`volume ls`添加`--format` #23475
* 允许最高级别的`docker inspect`检阅任何类型资源 #23614
* 在`docker run`或`docker create`允许移除`--entrypoint` #23718
* 重构CLI命令:添加`docker image`以及`docker container` #26025
* 从`service ls`输出中移除`COMMAND`列 #28029
* 为`docker events`添加`--format` #26268
* 在`docker node ps`允许指定多个节点 #26299
* 在`docker images`输出中限制小数点两位 #26303
* 为`docker run`添加`--dns-option` #28186
* 为容器提交事件添加镜像ID #28128
* 为`docker info`添加外部二进制版本 #27955
* 在`docker info`输出中添加管理地址信息 #28042
* 为`docker images`添加新的引用过滤 #27872

##运行时

* 添加`--experimental`守护进程参数用于启用试验功能而非分开发布 #27223
* 添加`--shutdown-timeout`守护进程参数来指定默认超时时间(以秒计算)用于在守护进程退出之前优雅地停止容器 #23036
* 添加`--stop-timeout`来指定超时时间(以秒计算)为停止单个容器 #22566
* 添加`--userland-proxy-path`守护进程参数使其允许配置用户代理而不是在` $PATH`内硬编码`docker-proxy` #26882
* 在`dockerd`以及`docker run`添加`--init`参数用于使用tini 一个作为PID 1的zombie-reaping init进程 #26061 #28037
* 添加`--init-path`守护进程参数允许配置`docker-init`二进制路径 #26941
* 配置添加支持动态加载不安全的registry #22337
* 在Windows守护进程中添加支持storage-opt size #23391
* 改善`docker run --rm`的可靠性通过将其从客户端移动到守护进程 #20848
* 添加支持`--cpu-rt-period`以及`--cpu-rt-runtime`参数,在kernel中`CONFIG_RT_GROUP_SCHED`启用的情况下,允许容器运行在real-time threads #23430
* 允许并行地停止,暂停, 取消暂停 #24761 / #26778
* 为`overlay2`实现XFS quota #24771
* 在 `service tasks --filter`中修复了一些过滤问题 #24850
* 允许引擎在在用户namespace中运行 #25672
* 当使用devicemapper驱动程序时,修复了在设备延期移除与恢复设备之间的竞态条件 #23497
* 在Windows中添加`docker stats`支持 #25737
* 使用`--userns=host`时, 允许使用`--pid=host`以及`--net=host` #25771
* (试验功能) 添加metrics输出 #25820
* 修复了`docker stats`使用`NetworkDisabled=true`的问题  #25905
* 在Windows中添加`docker top`支持 #25891
* 记录`exec`进程的pid #27470
* 添加支持通过`getent`查找user/groups #27599
* 为系统资源管理添加新命令`docker system`还有`df`与`prune`子命令,以及`docker {container,image,volume,network} prune`子命令 #26108 #27525 / #27525
* 修复了使用devicemapper,通过设置xfs max_retries to 0 upon ENOSPC时,容器不能被停止或杀掉的问题  #26212
* 修复了使用devicemapper,`docker cp`未能复制容器volume目录到CentOS的问题 #28047
* 提升overlay(2)驱动程序 #27932
* 添加`--seccomp-profile`守护进程参数用于指定seccomp profile来覆盖默认的路径 #26276
* 修复了当守护进程设置`--default-ulimit`参数时,`docker inspect`的ulimits问题 #26405
* 在旧版本kernels上构建过程中,添加了overlay问题的解决方案 #28138
* 在`docker exec -t`添加`TERM`环境变量 #26461
* `--stop-signal`设置在`docker kill` #26464

##Swarm Mode

* 添加安全管理 #27794
* 在`docker service inspect --pretty`输出中显示终端模式  #26906
* 通过缩短在任务名字中的服务IDs, 使`docker service ps`输出更惬意 #28088
* `docker node ps`默认输出是当前节点 #25214
* 为`docker service ps`以及`docker node ps`添加`-a` / `--all`用于显示所有结果 #25983
* 为`service create`添加`--dns`, `--dns-opt`以及`--dns-search` #27567
* 为`docker service update`添加`--force` #27596
* 为`docker service ps`添加`-q` #27654
* 在`docker service ls`中显示全局service数量  #27710
* 从`docker service update`移除`--name`。这个标志仅用在`docker service create` #26988
* 修复了由于瞬态网络问题而导致的工作节点未能恢复的问题 #26646
* 添加支持健康检查的负载均衡与DNS记录 #27279
* 为`docker service create`添加`--hostname` #27857
* 为`docker service create/update`添加`--tty` #28076
* 管理者自动检测、储存以及暴露节点IP地址 #27910
* 为空闲管理者的keys和大量数据加密 #27967
* 为`docker service update`添加`--update-max-failure-ratio`, `--update-monitor`以及`--rollback`  #26421
* 修复了在`docker swarm init`上运行容器的地址自动发现问题 #26457
* (试验功能) 为查看service日志添加`docker service logs`命令 #28089
* 为`docker service create`以及`update` 通过摘要识别镜像 #28173
* 为`docker node rm --force`以及`docker swarm leave --force`添加简短(`-f`)标志  #28196
* 不要重新拉取镜像如果已经通过摘要识别到 #28265
* Windows添加支持swarm-mode  #27838

##Volume

* volumes添加支持标签 #21270
* 添加支持通过标签过滤volumes #25628
* 在`docker volume rm`添加`--force`标志用于强制清除已删除的volume的数据 #23436
* 加强`docker volume inspect`用于当创建volume时,显示所有已使用的选项 #26671
* 添加支持本地NFS volumes来解析主机名 #27329

##安全

* 修复了selinux 容器的volumes的标签问题 #23024
禁止`/sys/firmware/*`被apparmor访问 #26618

##弃用

* 弃用`docker daemon`命令。守护进程移动到了一个单独的二进制文件(`dockerd`),而且已经使用 #26834
* 弃用无版本的API #28208
* 从支持平台中移除Ubuntu 15.10 (Wily Werewolf)。Ubuntu 15.10使用期结束并且不会再收到更新 #27042
* 从支持平台中移除Fedora 22。Fedora 22使用期结束并且不会再收到更新 #27432
* 在`docker pull`中弃用`repo:shortid`语法 #27207
* 为overlay/overlay2储存驱动程序弃用没有d_type的文件系统  #27433
* 在`Dockerfile`中弃用MAINTAINER #25466
* 为`/images/json`弃用过滤参数 #27872

===========================

原文链接:Changelog - 1.13.0 (翻译:田浩浩

用 ELK Stack 和 Docker 搭建日志平台

字节流 发表了文章 • 0 个评论 • 5702 次浏览 • 2016-08-27 10:35 • 来自相关话题

# 1. 架构 这次我们 ELK Stack 搭建一个日志平台,运行在 Docker 中,并配合 Filebeat 及 Log4j,收集系统日志、nginx 访问日志和 Java 由 Log4j 产生的日志,总体的架构图如下: ...查看全部
# 1. 架构

这次我们 ELK Stack 搭建一个日志平台,运行在 Docker 中,并配合 Filebeat 及 Log4j,收集系统日志、nginx 访问日志和 Java 由 Log4j 产生的日志,总体的架构图如下:

elk-structure.png


其中我们用 Elasticsearch 作为日志的存储和索引平台;Logstash 依靠强大繁多的插件作为日志加工平台,Kibana 用来从 Elasticsearch 获取数据,进行数据可视化,定制数据报表;Filebeat 用来放到各个主机中收集指定位置的日志,将收集到日志发送到 Logstash;Log4j 直接与 Logstash 连接,将日志直接发送到 Logstash(当然此处也可以用 Filebeat 收集 tomcat 的日志)。

# 2. Elasticsearch 配置

Elasticsearch 作为日志的存储和索引平台,他的 docker-compose 配置文件如下:

version: '2'
services:
elasticsearch:
image: elasticsearch:2.2.0
container_name: elasticsearch
restart: always
network_mode: "bridge"
ports:
- "9200:9200"
- "9300:9300"
volumes:
- ./data:/usr/share/elasticsearch/data


其中,主机向外暴露的端口 `9200` 作为 对外提供服务的 HTTP 端口;`9300` 作为交互的 TCP 端口;
将日志索引文件的存储目录挂载到主机的目录,防止因容器挂掉活重启导致历史日志文件丢失。

配置好 `docker-compose.yml` 文件后, 运行 `docker-compose up -d` 便以 daemon 方式启动。用 `docker ps` 命令查看启动状况.

# 3. Logstash 配置

Logstash 作为日志的加工处理平台,有很多的插件可以配置,他的 docker-compose 配置文件如下:


version: '2'
services:
logstash:
image: logstash:2.2.0-1
container_name: logstash
restart: always
network_mode: "bridge"
ports:
- "5044:5044"
- "4560:4560"
- "8080:8080"
volumes:
- ./conf:/config-dir
- ./patterns:/opt/logstash/patterns
external_links:
- elasticsearch:elasticsearch
command: logstash -f /config-dir


其中暴露的端口 `5044` 用于接收来着 Filebeat 收集的日志数据; `4569` 用于接收来着 Log4j 的日志数据;`8080` 用于接收来自插件 Logstash-input-http 的日志数据;

挂载 `conf` 目录,用于添加我们自定义的配置文件,`patterns` 用于添加我们自定义的 grok 规则文件。

同时,和 `elasticsearch` 容器连接用来传送数据。

配置好 `docker-compose.yml` 文件后, 运行 `docker-compose up -d` 便以 daemon 方式启动。用 `docker ps` 命令查看启动状况.

# 4. Filebeat 配置

Filebeat 安装在每一个需要收集日志的主机上收集指定的日志,他的 docker-compose 配置文件如下:


version: '2'
services:
filebeat:
image: olinicola/filebeat:1.0.1
container_name: filebeat
restart: always
network_mode: "bridge"
extra_hosts:
- "logstash:127.0.0.1"
volumes:
- ./conf/filebeat.yml:/etc/filebeat/filebeat.yml
- /data/logs:/data/logs
- /var/log:/var/host/log
- ./registry:/etc/registry


其中以 `extra_hosts` 的方式,指定 Logstash 的位置;挂载配置文件目录 `conf`;挂载本机的日志目录 `/data/logs`; 挂载本机的系统日志目录 `/var/log`; 挂载 `registry` 目录,用来确定 Filebeat 读取文件的位置,防止 Filebeat 因重启或挂机导致又从头开始读取日志文件,造成日志数据重复。

# 5. Kibana 配置

Kibana 的配置最为简单,仅作为数据可视化的平台,提供 HTTP 访问服务即可。他的 docker-compose 配置文件如下:


version: '2'
services:
kibana:
image: kibana:4.4.0
container_name: kibana
restart: always
network_mode: "bridge"
ports:
- "5601:5601"
external_links:
- elasticsearch:elasticsearch


其中连接到 `elasticsearch` 容器用来获取数据;暴露 `5601` 端口用于 Kibana 界面的访问;

配置好 `docker-compose.yml` 文件后, 运行 `docker-compose up -d` 便以 daemon 方式启动。用 `docker ps` 命令查看启动状况.

打开 `http://your-host:5601` 即可看到 Kibana 的界面,大致如下图的样子:



# 6. 使用配置

1)nginx 访问日志格式配置
在 nginx 配置文件中配置如内容:

log_format logstash '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$http_host" "$upstream_addr" '
'$request_time $upstream_response_time';

access_log /data/logs/nginx/access.log logstash;


2)Log4j 的接入配置
在 `log4j.properties` 文件中配置如下内容:

log4j.rootLogger = INFO,logstash

# Push to Logstash
# 注意:RemoteHost 等信息可能变化,根据具体情况配置
log4j.appender.logstash=org.apache.log4j.net.SocketAppender
log4j.appender.logstash.Port=4560
log4j.appender.logstash.RemoteHost=your-logstash-host
log4j.appender.logstash.ReconnectionDelay=60000
log4j.appender.logstash.LocationInfo=true


# 7. 附件

所有的配置文件均已发布到 Github ,有需要的同学可以前往 star 和使用。
https://github.com/asmoker/ELKStack

欢迎访问我的个人博客====>字节流的博客