zoukankan      html  css  js  c++  java
  • 十七. k8s--日志收集方案

    k8s容器日志收集方案

    一. 在Node上部署logging agent

    将日志文件转发到后端存储里保存起来

    • 不难看到,这里的核心就在于logging agent,它一般都会以DaemonSet的方式运行在节点上,然后将宿主机上的容器日志目录挂载进去,最后由logging-agent把日志转发出去。
    • 举个例子,我们可以通过Fluentd项目作为宿主机上的logging-agent,然后把日志转发到远端的ElasticSearch里保存起来供将来进行检索。具体的操作过程官网很多kubernetes的部署里,会自动为你启用logrotate,在日志文件超过10MB的时候自动对日志文件进行roate操作。
    • 可以看到在Node上部署logging agent最大的优点,在于只需要部署一个agent,并且不会对应用和pod有任何入侵性。所以这个方案在社区里是最常用的一种。
    • 但是这种方案的不足之处就在于,它要求应用输出的日志,都必须是直接输出到容器的stdout和stderr里

    二. 对特殊情况的一个处理

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

    • 现在我的应用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: {}
      
    • 在这种情况下,你用kubectl logs命令是看不到应用的任何日志的。这时我们就可以为这个pod添加两个sidecar容器,分别将上述两个日志文件里的内容重新以stdout和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和stderr对应的json文件。这对磁盘是很大的浪费。所以说,除非万不得已或者应用容器完全不能修改,否则还是建议你直接使用方案一,或者直接使用方案三。

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

    • 相当于把方案一里的logging agent,放在了应用pod里。

    • 在这种方案里,你的应用还可以直接把日志输出到固定的文件里而不是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来指定的。这里用到了Volume来把ConfigMap挂在到Pod里。

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

    总结

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

    转载: https://juejin.im/post/5cb939b0e51d456e311649e0

  • 相关阅读:
    解决 el-table在ie11中默认状态下不是百分百展开的问题
    在vue中使用lexible.js 通过props传的style样式无法转换成rem
    解决 el-select 与 el-radio 组合字体发生闪烁问题
    解决element生成的下拉菜单,不在父级之下,而是在body之下,通过父级控制该下拉菜单的样式,达到不跟别的地方冲突的目的
    解决nvm use提示切换node版本成功,实际却没有切换过对应版本
    vue-element-admin安装失败的问题
    今天转正了,感谢博客园让我找到工作!
    electron-vue中点击按钮,实现打开程序目录里面的某个文件
    项目实战---模拟站酷网站
    vue实现选项卡切换效果
  • 原文地址:https://www.cnblogs.com/peitianwang/p/11661369.html
Copyright © 2011-2022 走看看