ELK收集k8s容器日志最佳实践
简介
- 关于日志收集这个主题,这已经是第三篇了,为什么一再研究这个课题,因为这个课题实在太重要,而当今优秀的开源解决方案还不是很明朗;
- 就docker微服务化而言,研发有需求标准输出,也有需求文件输出,每次登录到服务器上去查看日志又多有不妥;现有的解决方案ELK,每次收集新应用日志都要更改配置文件重新适配日志路径足以让我们崩溃;
- 对于k8s,没有日志系统推行工作就无法进行,总不能让开发小伙伴登录到k8s上去找日志吧,鬼知道在哪个pod里;当然,k8s官方提供了解决方案efk,efk最大的问题就是无法对日志有效分组,所有日志都在一个索引里,影响查询速度不说,对于研发小伙伴查找属于自己应用的日志也很困难,不得不说,这个解决方案很鸡肋;
- 综上三条,能够统筹普通应用、docker微服务、k8s的日志收集方案迫在眉睫,今天就将能解决这些问题的日志收集方案的最佳实践分享给大家;
- 该实践采用的是阿里云的开源工具 log-pilot 采集日志,采集的过程中就将各种日志打标分类,类似最近比较火的垃圾分类,逻辑结构图如下:
- 三种节点类型:
- k8s使用daemonset类型的副本集,使每个节点运行一个
log-pilot
来收集日志,该日志会含有k8s_container_name、k8s_pod、k8s_node_name、 k8s_pod_namespace
等打标数据,输出到相应的logstash
来做索引 - 运行docker微服务的主机上运行一个
log-pilot
来收集日志,该日志会含有docker_container、topic、index
等打标数据,输出到相应的logstash
来做索引 - 普通非容器程序的日志可以采用
filebeat
收集,日志中可以自定义标签和字段,输出到对应的logstash
来做索引
- k8s使用daemonset类型的副本集,使每个节点运行一个
log-pilot 说明和配置
- 容器日志采集模式现在流行的方式有 SideCar模式和 Node模式,SideCar模式会占用大量资源,而Node模式需要只能的
logging agent
配合,而log-pilot
就是那个只能的agent - log-pilot 可同时支持stdout和容器内文件日志采集,支持声明式日志配置,同时拥有自动感知(发现)机制、自动checkpoint及具柄保持机制和自动日志数据打标
- log-pilot 除拥有上述功能,还支持多插件多后端,低消耗,高性能,具体情况请看 K8S 日志实践
log-pilot 插件支持
log-pilot 工作模式
log-pilot 配置方法
- 在
Kubernetes
下,Log-Pilot
可以依据环境变量aliyun_logs_$name = $path
动态地生成日志采集配置文件,其中包含两个变量:$name
是我们自定义的一个字符串,它在不同的场景下指代不同的含义,在本场景中,将日志采集到ElasticSearch
的时候,这个$name
表示的是Index
。- 另一个是
$path
,支持两种输入形式,stdout
和容器内部日志文件的路径,对应日志标准输出和容器内的日志文件。 - 第一种约定关键字
stdout
表示的是采集容器的标准输出日志,如本例中我们要采集tomcat
容器日志,那么我们通过配置标签aliyun.logs.catalina=stdout
来采集tomcat
标准输出日志。 - 第二种是容器内部日志文件的路径,也支持通配符的方式,通过配置环境变量
aliyun_logs_access=/usr/local/tomcat/logs/*.log
来采集 tomcat 容器内部的日志。当然如果你不想使用aliyun
这个关键字,Log-Pilot
也提供了环境变量PILOT_LOG_PREFIX
可以指定自己的声明式日志配置前缀,比如PILOT_LOG_PREFIX: "aliyun,custom"
。
- 此外,
Log-Pilot
还支持多种日志解析格式,通过aliyun_logs_$name_format=<format>
标签就可以告诉 Log-Pilot 在采集日志的时候,同时以什么样的格式来解析日志记录,支持的格式包括:none、json、csv、nginx、apache2
和regxp
。 Log-Pilot
同时支持自定义tag
,我们可以在环境变量里配置aliyun_logs_$name_tags="K1=V1,K2=V2"
,那么在采集日志的时候也会将K1=V1
和K2=V2
采集到容器的日志输出中。自定义tag
可帮助您给日志产生的环境打上tag
,方便进行日志统计、日志路由和日志过滤。log-pilot 在k8s上的配置
cat > ops-log-pilot-filebeat-ds.yaml << EOF apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: ops-log-pilot-filebeat-ds namespace: ops spec: selector: matchLabels: app: log-pilot-filebeat release: stable template: metadata: labels: app: log-pilot-filebeat release: stable spec: containers: - name: log-pilot-filebeat image: registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.6-filebeat env: - name: "NODE_NAME" valueFrom: fieldRef: fieldPath: spec.nodeName - name: "PILOT_LOG_PREFIX" value: "glinux" - name: "LOGGING_OUTPUT" value: "logstash" # 请确保集群到ES网络可达 - name: "LOGSTASH_HOST" value: "logstash.glinux.top" - name: "LOGSTASH_PORT" value: "5053" volumeMounts: - name: sock mountPath: /var/run/docker.sock - name: root mountPath: /host readOnly: true - name: varlib mountPath: /var/lib/filebeat - name: varlog mountPath: /var/log/filebeat - name: localtime mountPath: /etc/localtime readOnly: true livenessProbe: failureThreshold: 3 exec: command: - /pilot/healthz initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 2 securityContext: capabilities: add: - SYS_ADMIN volumes: - name: sock hostPath: path: /var/run/docker.sock - name: root hostPath: path: / - name: varlib hostPath: path: /var/lib/filebeat type: DirectoryOrCreate - name: varlog hostPath: path: /var/log/filebeat type: DirectoryOrCreate - name: localtime hostPath: path: /etc/localtime EOF # 调用方法 kubectl apply -f ops-log-pilot-filebeat-ds.yaml
log-pilot 在docker主机上配置
docker run -d \ --name log-pilot-filebeat \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /etc/localtime:/etc/localtime \ -v /:/host:ro \ --cap-add SYS_ADMIN \ -e PILOT_LOG_PREFIX=glinux \ -e LOGGING_OUTPUT=logstash \ -e LOGSTASH_HOST=logstash.glinux.top \ -e LOGSTASH_PORT=5063 \ --restart=always \ registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.5-filebeat
logstash 配置方法
- logstash的三个实例,我是运行在同一台机器上,同时kibana也是运行在这台机器上
- 当然也可以通过一个logstash实例,配置中采用判断条件建立不同索引,但会影响性能,所以这里我起了三个实例
- logstash的主要功能是将收集到的日志进行拆分,采用某些字段建成索引,传递给
elasticsearch
集群 - 这里强烈建议使用阿里云的
elasticsearch
集群,可以先使用免费版1核2G内存20G SSD 三组
,原因是阿里云和elastic有合作,es有授权,很多功能可以使用,比如用户管理,监控等,后面会说到logstash 处理k8s日志
- logstash 监控配置文件,监控信息会体现在kibana中
cat > /data/logslogstash.yml << EOF xpack.monitoring.elasticsearch.url: http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200 xpack.monitoring.elasticsearch.username: "user" xpack.monitoring.elasticsearch.password: "pass" EOF
配置文件
cat > /data/conf/logstash-k8s.conf << EOF input { beats { host => "0.0.0.0" port => "5043" } } filter { grok { match => { "message" => "%{TIMESTAMP_ISO8601:log-timestamp} %{LOGLEVEL:log-level} %{JAVALOGMESSAGE:log-msg}" } } mutate { # remove_field => ["message"] remove_field => ["beat"] } } output { stdout { codec => rubydebug } elasticsearch { hosts => ["http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200"] user => ["user"] password => ["pass"] index => "%{k8s_container_name}-%{+YYYY.MM.dd}" } } EOF
启动命令
docker run -p 5053:5043 -d \ --user root \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ --name logstash-k8s \ --restart=always \ -v /data/conf/logstash-k8s.conf:/usr/share/logstash/pipeline/logstash.conf \ -v /data/conf/logstash.yml:/usr/share/logstash/config/logstash.yml \ logstash:6.6.2
logstash 处理docker日志
配置文件
cat > /data/conf/logstash-docker.conf << EOF input { beats { host => "0.0.0.0" port => "5043" } } filter { grok { match => { "message" => "%{TIMESTAMP_ISO8601:log-timestamp} %{LOGLEVEL:log-level} %{JAVALOGMESSAGE:log-msg}" } } mutate { # remove_field => ["message"] remove_field => ["beat"] } } output { stdout { codec => rubydebug } elasticsearch { hosts => ["xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200"] user => ["user"] password => ["pass"] index => "%{docker_container}-%{+YYYY.MM.dd}" } } EOF
启动命令
docker run -p 5063:5043 -d \ --user root \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ --name logstash-docker \ --restart=always \ -v /data/conf/logstash-docker.conf:/usr/share/logstash/pipeline/logstash.conf \ -v /data/conf/logstash.yml:/usr/share/logstash/config/logstash.yml \ logstash:6.6.2
elasticsearch 说明
- 如上所述,elasticsearch 使用阿里云的产品 阿里云 · Elasticsearch
- 可以先使用免费版
1核2G内存20G SSD 三组
- 开通后会有 地址、用户名、密码等信息,这些是要填写在logstash的输出配置文件中
- 阿里云和elastic有合作,es有授权,用户管理、用户登录、索引监控、节点监控、logstash监控等功能均可正常使用
- 除以上外,定期清理es的索引也很有必要,可以参考我之前的博客 ELK:收集Docker容器日志 中 定时删除过期日志索引文件 章节
- 使用阿里云的es后,kibana上会有授权体现,这里贴两张图展示一下功能
kibana 的监控
kibana 的管理
kibana 说明和配置
- 下面步骤操作完毕启动后,此处访问
http://IP:5603
,用户名和密码同elasticserach
的,输入即可登录kibana,如此建立索引,就可以正常的玩耍了kibana 配置文件
- 如下的配置文件会屏蔽掉许多没用的插件功能模块,如上图显示的清爽界面
cat > /data/conf/kibana-es-aliyun.yml << EOF # Default Kibana configuration from kibana-docker. server.name: kibana server.host: "0" elasticsearch.hosts: http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200 elasticsearch.username: user elasticsearch.password: pass xpack.monitoring.ui.container.elasticsearch.enabled: true timelion.enabled: false console.enabled: false xpack.grokdebugger.enabled: false xpack.searchprofiler.enabled: false xpack.canvas.enabled: false xpack.ml.enabled: false xpack.infra.enabled: false xpack.apm.enabled: false xpack.graph.enabled: false EOF
kibana 启动命令
docker run -p 5603:5601 -d \ --user root \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ --name kibana-es-aliyun \ --restart=always \ -e ELASTICSEARCH_URL=http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200 \ kibana:6.6.2
- 下面来看下优秀的登录界面
日志收集效果验证
docker日志收集案例 tomcat
- 注意
label
的配置docker run -it -d --name tomcat -p 10080:8080 \ -v /var/logs/:/usr/local/tomcat/logs \ --label glinux.logs.catalina=stdout \ --label glinux.logs.access=/usr/local/tomcat/logs/localhost_access_log.*.txt \ tomcat
- 日志收集效果如下图:
k8s日志收集案例 tomcat
- 注意env的配置
cat > tomcat-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: tomcat
spec:
containers:
- name: tomcat
image: "tomcat:7.0"
env:
# 1、stdout为约定关键字,表示采集标准输出日志
# 2、配置标准输出日志采集到ES的catalina索引下
- name: glinux_logs_catalina
value: "stdout"
# 1、配置采集容器内文件日志,支持通配符
# 2、配置该日志采集到ES的access索引下
- name: glinux_logs_access
value: "/usr/local/tomcat/logs/catalina.*.log"
# 容器内文件日志路径需要配置emptyDir
volumeMounts:
- name: tomcat-log
mountPath: /usr/local/tomcat/logs
volumes:
- name: tomcat-log
emptyDir: {}
EOF
# 调用
kubectl apply -f tomcat-pod.yaml -n ops
- 日志收集效果如下图:
参考文档
- 在阿里,我们是怎么做 K8S 日志实践: https://toutiao.io/posts/k0qse0/preview
- 利用 Log-Pilot + Elasticsearch + Kibana 搭建 kubernetes 日志解决方案: https://help.aliyun.com/document_detail/86552.html
- log-pilot filebeat说明文档: https://github.com/AliyunContainerService/log-pilot/blob/master/docs/filebeat/docs.md
- json格式化在线:https://www.bejson.com
- visual-paradigm:https://online.visual-paradigm.com/w/odyqcwvx/diagrams.jsp#diagramlist:proj=0&new=BubbleDiagram