Kubernetes日志收集

小丫1年前技术文章497

关于容器日志

Docker的日志分为两类,一类是Docker引擎日志;另一类是容器日志。引擎日志一般都交给了系统日志,不同的操作系统会放在不同的位置。本文主要介绍容器日志,容器日志可以理解是运行在容器内部的应用输出的日志,默认情况下,docker logs显示当前运行的容器的日志信息,内容包含 STOUT(标准输出)和STDERR(标准错误输出)。日志都会以json-file的格式存储于 /var/lib/docker/containers/<容器id>/<容器id>-json.log,不过这种方式并不适合放到生产环境中。

  • 默认方式下容器日志并不会限制日志文件的大小,容器会一直写日志,导致磁盘爆满,影响系统应用。(docker log-driver支持log文件的rotate)

  • Docker Daemon收集容器的标准输出,当日志量过大时会导致Docker Daemon成为日志收集的瓶颈,日志的收集速度受限。

  • 日志文件量过大时,利用docker logs -f查看时会直接将Docker Daemon阻塞住,造成docker ps等命令也不响应。

Docker提供了logging drivers配置,用户可以根据自己的需求去配置不同的log-driver,可参考官网Configure logging drivers[1]。但是上述配置的日志收集也是通过Docker Daemon收集,收集日志的速度依然是瓶颈。

log-driver 日志收集速度

syslog 14.9 MB/s

json-file 37.9 MB/s


能不能找到不通过Docker Daemon收集日志直接将日志内容重定向到文件并自动rotate的工具呢?答案是肯定的采用S6[2]基底镜像。

S6-log将CMD的标准输出重定向到/.../default/current,而不是发送到 Docker Daemon,这样就避免了Docker Daemon收集日志的性能瓶颈。本文就是采用S6基底镜像构建应用镜像形成统一日志收集方案。


关于Kubernetes日志

Kubernetes日志收集方案分成三个级别:

应用(Pod)级别

Pod级别的日志,默认是输出到标准输出和标准输入,实际上跟Docker容器的一致。使用kubectl logs pod-name -n namespace查看,具体参考:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#logs。

节点级别


Node级别的日志 , 通过配置容器的log-driver来进行管理,这种需要配合logrotare来进行,日志超过最大限制,自动进行rotate操作。


集群级别

集群级别的日志收集,有三种。

节点代理方式

在Node级别进行日志收集。一般使用DaemonSet部署在每个Node中。

优点:耗费资源少,因为只需部署在节点,且对应用无侵入。

缺点:只适合容器内应用日志必须都是标准输出。


使用sidecar container作为容器日志代理

也就是在Pod中跟随应用容器起一个日志处理容器,有两种形式:

一种是直接将应用容器的日志收集并输出到标准输出(叫做Streaming sidecar container),但需要注意的是,这时候,宿主机上实际上会存在两份相同的日志文件:一份是应用自己写入的;另一份则是sidecar的stdout和stderr对应的JSON文件。这对磁盘是很大的浪费,所以说,除非万不得已或者应用容器完全不可能被修改。


另一种是每一个Pod中都起一个日志收集agent(比如Logstash或Fluebtd)也就是相当于把方案一里的logging agent放在了Pod里。但是这种方案资源消耗(CPU,内存)较大,并且日志不会输出到标准输出,kubectl logs会看不到日志内容。


应用容器中直接将日志推到存储后端,这种方式就比较简单了,直接在应用里面将日志内容发送到日志收集服务后端。

日志架构

通过上文对Kubernetes日志收集方案的介绍,要想设计一个统一的日志收集系统,可以采用节点代理方式收集每个节点上容器的日志,日志的整体架构如图所示:

image.png

解释如下:

  1. 所有应用容器都是基于S6基底镜像的,容器应用日志都会重定向到宿主机的某个目录文件下比如/data/logs/namespace/appname/podname/log/xxxx.log

  2. log-agent内部包含Filebeat,Logrotate等工具,其中Filebeat是作为日志文件收集的agent

  3. 通过Filebeat将收集的日志发送到Kafka

  4. Kafka在将日志发送的ES日志存储/kibana检索层

  5. Logstash作为中间工具主要用来在ES中创建index和消费Kafka的消息

整个流程很好理解,但是需要解决的是:

  1. 用户部署的新应用,如何动态更新Filebeat配置

  2. 如何保证每个日志文件都被正常的rotate

  3. 如果需要更多的功能则需要二次开发Filebeat,使Filebeat支持更多的自定义配置

付诸实践

解决上述问题,就需要开发一个log-agent应用以DaemonSet形式运行在Kubernetes集群的每个节点上,应用内部包含Filebeat,Logrotate和需要开发的功能组件。

第一个问题,如何动态更新Filebeat配置,可以利用http://github.com/fsnotify/fsnotify工具包监听日志目录变化create、delete事件,利用模板渲染的方法更新Filebeat配置文件。


第二个问题,利用http://github.com/robfig/cron工具包创建CronJob,定期rotate日志文件,注意应用日志文件所属用户,如果不是root用户所属,可以在配置中设置切换用户。

/var/log/xxxx/xxxxx.log {
  su www-data www-data
  missingok
  notifempty
  size 1G
  copytruncate
}


第三个问题,关于二次开发filebeat,可以参考博文:https://www.jianshu.com/p/fe3ac68f4a7a


相关文章

数据湖技术之iceberg(十二)Flink与Iceberg整合-SQL API操作

数据湖技术之iceberg(十二)Flink与Iceberg整合-SQL API操作

1.SQL API 创建Iceberg表并写入数据StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnv...

Linux解锁线程基本概念和线程控制,步入多线程学习的大门(1)

Linux解锁线程基本概念和线程控制,步入多线程学习的大门(1)

1、线程初识1.1线程的概念线程是进程内部的一个执行分支,线程是CPU调度的基本单位那什么是进程呢?我们之前学习了解到的进程是加载到内存中的程序进程 = 内核数据结构 + 进程代码和数据。今天我们要推...

trino容器设置nodeselector(七)

trino容器设置nodeselector(七)

查看node labelkubectl get nodes --show-labels2、在容器中设置nodeselector属性  nodeSelector:     dps: "1"查看k8s...

Redis 运维规范_运维管理规范

三、运维管理规范1、密码认证 云上 Redis 的权限控制:账号管理+白名单设置+阿里云子账号权限。对于线下 Redis 可以通过设置密码和 bind 参数文件控制访问。2、合理设置备份策略 Redi...

apache Hbase2.x  使用hbck2修复工具

apache Hbase2.x 使用hbck2修复工具

1、背景默认情况下apache hbase 使用hbck2时,无法使用-j 来加载hbck2的jar包,无法进行修复2、解决办法是由于默认情况下只使用自带的hbase hbck修复命令,大部分功能在2...

PG的统计信息(二)

1.2.4 pg_statio_user_tables 指标含义通过对pg_statio_user_tables的查询,如果heap_blks_read,idx_blks_read很高说明shared...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。