1、简介
log-Pilot 是一个智能容器日志采集工具,它不仅能够高效便捷地将容器日志采集输出到多种存储日志后端,同时还能够动态地发现和采集容器内部的日志文件。
2、容器本身特性
采集目标多
容器一般推荐将日志写在标准输出,但是也有一些特殊的场景就是应用直接将日志写在容器内部。对于容器的标准输出日志来说,Docker Engine 本身就提供了一个很好的日志采集能力,但是对于容器内部的文件日志采集,现在并没有一个很好的工具能够去动态发现采集。
容器的弹性伸缩性
我们知道 Kubernetes 本身是一个分布式集群,那么我们事先就无法像传统虚拟机环境下那样,事先配置好日志的采集路径等一些信息,因此这对于容器的日志采集来说也将面临一个很大的挑战。
3、现有采集工具缺陷
缺乏动态配置的能力
目前的采集工具都需要我们事先手动配置好日志采集方式和路径等信息,由于它无法能够自动感知到容器的生命周期变化或者动态漂移,所以它无法动态地去配置。
日志采集重复或丢失
现有的一些采集工具基本上是通过 tail 的方式来进行日志采集的,那么这里就可能存在两个方面的问题:一个是可能导致日志丢失,比如采集工具在重启的过程中,而应用依然在写日志,那么就有可能导致这个窗口期的日志丢失;而对于这种情况一般保守的做法就是,默认往前多采集 1M 日志或 2M 的日志,那么这就又会可能引起日志采集重复的问题。
未明确标记日志源
一个应用可能有很多个容器,输出的应用日志也是一样的,那么当我们将所有应用日志收集到统一日志存储后端时,在搜索日志的时候,我们就无法明确这条日志具体是哪一个节点上的哪一个应用容器产生的。

4、K8s 的日志采集模式
SideCar 模式
这种模式就是在 Pod 中除了运行我们的应用程序容器, 再起一个负责日志采集的容器,比如再起一个 logstash 或 fluentd 容器。当 Pod 数量一多,这种方案资源消耗很大,对日志存储后端也会占用过多的连接数,并且日志不输出到标准输出,不能通过 kubectl logs 命令查看。

Node 代理模式
就是在每个 Node 上部署一个日志采集代理程序(如 filebeat,fluentd,或 logstash 等),一般是以 DaemonSet 的形式在每个 Node 上部署一个 Pod,来采集这个 Node 上所有容器的日志。这种模式的优点是资源消耗少,一个节点一个 Pod, 且对应用无侵入。

应用程序推送模式
直接在应用程序里将日志内容发送到日志采集服务,比如在程序里将日志发到 kafka, 再使用 logstash 从 kafka 拉取到 elasticsearch。这种方案对应用具有侵入性。
<!--传统采集模式中需要在每个 Pod 中起一个专门用来采集日志的容器。在集群规模大的情况下,会造成资源的过多占用。--><!--而Log-Pilot 采用的是 Node 采集模式,这个模式中只需要在每个节点上部署一个专门用来采集此节点上所有容器的日志的 Pod,可以避免资源的浪费。有没有一种方案或工具,既能采集 k8s 中标准输出日志,又能采集到容器内部的日志文件输出日志,并且资源消耗小,对应用无侵入呢。阿里开源的 log-pilot 基本能满足要求,只是更新较慢,目前版本基于 ELK 6,如果要适配到 ELK 7 或以上,需进行一些必要的调整。-->
5、log-pilot 特性
一个单独的 log 进程收集机器上所有容器的日志。不需要为每个容器启动一个 log 进程。
支持文件日志和 stdout。docker log dirver 亦或 logspout 只能处理 stdout,log-pilot 不仅支持收集 stdout 日志,还可以收集文件日志。
声明式配置。当您的容器有日志要收集,只要通过 label 声明要收集的日志文件的路径,无需改动其他任何配置,log-pilot 就会自动收集新容器的日志。
支持多种日志存储方式。无论是强大的阿里云日志服务,还是比较流行的 elasticsearch 组合,甚至是 graylog,log-pilot 都能把日志投递到正确的地点。

6、系统架构

<!--模拟业务服务 日志收集 日志存储 消费目的服务-->
<!--tomcat -- log-pilot -- elasticsearch --- kibana -->
7、部署Elasticsearch+kibana
# 部署Elasticsearch
[root@10-60-249-255 ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:6.8.23
# 部署Kibana (ELASTICSEARCH_URL请换成自己本地ip)
[root@10-60-249-255 ~]# docker run --name kibana -e ELASTICSEARCH_URL=http://192.168.0.71:9200 -p 5601:5601 -d kibana:6.8.23
成功访问Kibana

8、部署log-pilot
[root@10-60-249-255 ~]# vim pilot-elasticsearch-kubernetes.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: log-pilot
labels:
k8s-app: log-pilot
spec:
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
k8s-app: log-pilot
template:
metadata:
labels:
k8s-app: log-pilot
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: log-pilot
image: registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.5-fluentd
env:
- name: "LOGGING_OUTPUT"
value: "elasticsearch"
- name: "ELASTICSEARCH_HOST"
value: "192.168.0.71" #changeme
- name: "ELASTICSEARCH_PORT"
value: "9200" #changeme
- name: "NODE_NAME"
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: sock
mountPath: var/run/docker.sock
- name: root
mountPath: host
readOnly: true
- name: pos
mountPath: pilot/pos
- name: localtime
mountPath: etc/localtime
securityContext:
capabilities:
add:
- SYS_ADMIN
#terminationGracePeriodSeconds: 30
volumes:
- name: sock
hostPath:
path: var/run/docker.sock
- name: root
hostPath:
path:
- name: pos
emptyDir: {}
- name: localtime
hostPath:
path: etc/localtime
<!--<u>注意:ELASTICSEARCH_HOST 、ELASTICSEARCH_PORT 需要换成刚刚创建Elasticsearch地址。如果是集群,ELASTICSEARCH_HOSTS 变量写多个地址即可,中间用逗号隔开</u>-->

9、部署一个测试服务
[root@10-60-249-255 ~]# vim tomcat.yml
apiVersion: v1
kind: Pod
metadata:
name: tomcat
spec:
containers:
- name: tomcat
image: "tomcat:7.0"
env:
- name: aliyun_logs_catalina
value: "stdout" # 告诉 log-pilot 这个容器要收集 stdout 日志。
- name: aliyun_logs_access
value: "/usr/local/tomcat/logs/catalina.*.log" # 则表示要收集容器内 /usr/local/tomcat/logs/ 目录下所有名字匹配 catalina.*.log的文件日志。
volumeMounts:
- name: accesslogs
mountPath: /usr/local/tomcat/logs
volumes:
- name: accesslogs
emptyDir: {}

启动服务后,会自动按天创建两个索引

查询日志

欢迎大家扫码关注:

本公众号只写原创,不接广告、不接广告、不接广告。下期小伙伴想学习什么技术,可以私信发我吆。





