k8s容器日志收集方案

 Docker君   2019-04-23 11:54   3943 人阅读  0 条评论

k8s容器日志收集方案  第1张

第一种:在 Node 上部署 logging agent,将日志文件转发到后端存储里保存起来


如下图:


k8s容器日志收集方案  第2张

   不难看到,这里的核心就在于 logging agent ,它一般都会以 DaemonSet 的方式运行在节点上,然后将宿主机上的容器日志目录挂载进去,最后由 logging-agent 把日志转发出去。

   举个例子,我们可以通过+Fluentd+项目作为宿主机上的+logging-agent,然后把日志转发到远端的+ElasticSearch+里保存起来供将来进行检索。具体的操作过程官网很多kubernetes的部署里,会自动为你启用logrotate,在日志文件找过10MB的时候自动对日志文件进行roate操作。

   可以看到在Node上部署logging agent最大的优点,在于只需要部署一个agent,并且不会对应用和pod有任何入侵性。所以这个方案是最常用的一种。

   但是这种方案的不足之处就在于,它要求应用输出的日志,都必须是直接输出到容器的stdout和stderr里。

第二种:对特殊情况的一个处理


   当容器的日志只能输出到某些文件里的时候,我们可以通过一个sidecar容器把这些日志文件重新输出到sidecar的stdout和stderr、如下图:


k8s容器日志收集方案  第3张

   现在我的应用pod只有一个容器,它会把日志输出到容器里的/var/log/1.log和2.log这两个文件里。这个pod的YAML文件如下所示:


apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}


   在这种情况下,你用kubect命令是看不到应用的任何日志的。而且最常用的方案一,也是没办法使用的。这时我们就可以为这个pod添加两个sidecar容器,分别将上述两个日志文件里的内容重新以stout和stderr的方式输出来,这个YAML文件的写法如下:


apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-1
    image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-2
    image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}


   注意:由于sidecar跟主容器之间是共享Volume的,所以这里的sidecar方案的性能损耗并不高,只是多占用一点cpu和内存。但是,这时候宿主机上实际会存在两份相同的日志文件:一份是应用本身自己写入的;另一份是sidecar的stdout和dtderr对应的json文件。这对磁盘是很大的浪费。所以说,除非万不得已或者应用容器完全不能被修改,否则还是建议你直接使用方案一,或者直接使用方案三。


第三种:送过sidecar容器直接把日志文件发送到远程存储


   相当于把第一种里的logging agent,放在了应用pod里。如下图:


k8s容器日志收集方案  第4张

   在这种方案里,你的应用还可以直接把日志输出到固定的文件里而不是stdout,你的logging-agent还可以使用fluentd,后端存储还可以是ElasticSearch。只不过,fluentd的输入源变成了应用的日志文件。一般来说,我们会把fluentd的输入源配置保存在一个ConfigMap里,如下所以:


apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
data:
  fluentd.conf: |
    <source>
      type tail
      format none
      path /var/log/1.log
      pos_file /var/log/1.log.pos
      tag count.format1
    </source>
    
    <source>
      type tail
      format none
      path /var/log/2.log
      pos_file /var/log/2.log.pos
      tag count.format2
    </source>
    
    <match **>
      type google_cloud
    </match>


   我们在应用pod的定义里,就可以新命一个Fluentd容器作为sidecar,专门负责将应用生成的1.log和2.log转发到ElasticSearch中,这个配置,如下所示:


apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-agent
    image: k8s.gcr.io/fluentd-gcp:1.30
    env:
    - name: FLUENTD_ARGS
      value: -c /etc/fluentd-config/fluentd.conf
    volumeMounts:
    - name: varlog
      mountPath: /var/log
    - name: config-volume
      mountPath: /etc/fluentd-config
  volumes:
  - name: varlog
    emptyDir: {}
  - name: config-volume
    configMap:
      name: fluentd-config


   如上所示,这个Fluentd容器使用的输入源,就是通过引用我们前面写的ConfigMap来指定的。这里用到了Projected Volume来把ConfigMap挂载到Pod里。

   这种方案虽然部署简单,并且对宿主机非常友好,但是这个sidecar容器很可能会消耗较多的资源,甚至拖垮应用容器。由于日志没有输出到stdout上,所以你通过kubectl logs 是看不到日志信息的。


总结

   以上,就是k8s最常用的三种收集日志的手段了,综合对比以上方案,比较建议将应用日志输出到stdout和stderr,然后通过在宿主机上部署logging-agent的方式集中处理日志、这种方案不但简单,而且kubectl logs依然可以使用,也是官方推荐的一种。


往期精彩

《Docker是什么?》

Kubernetes是什么?

《Kubernetes和Docker到底有啥关系?》

教你如何快捷的查询选择网络仓库镜像tag

《Docker镜像进阶:了解其背后的技术原理》

《教你如何修改运行中的容器端口映射》

k8s学习笔记:介绍&上手

k8s学习笔记:缩扩容&更新

《Docker君带你认识Docker Swarm》

Docker 基础用法和命令帮助

在K8S上搭建Redis集群

灰度部署、滚动部署、蓝绿部署


k8s容器日志收集方案  第5张

k8s容器日志收集方案  第6张

k8s容器日志收集方案  第7张

dockerchina

k8s容器日志收集方案  第8张



本文地址:https://dockerworld.cn/?id=13
版权声明:本文为原创文章,版权归 Docker君 所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

还没有留言,还不快点抢沙发?