十七. k8s--日誌收集方案

k8s容器日誌收集方案

一. 在Node上部署logging agent

將日誌文件轉發到後端存儲裏保存起來json

  • 不難看到,這裏的核心就在於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文件的寫法以下:api

    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文件。這對磁盤是很大的浪費。因此說,除非萬不得已或者應用容器徹底不能修改,不然仍是建議你直接使用方案一,或者直接使用方案三。app

三. 送過sidecar容器直接把日誌文件發送到遠程存儲

  • 至關於把方案一里的logging agent,放在了應用pod裏。

  • 在這種方案裏,你的應用還能夠直接把日誌輸出到固定的文件裏而不是stdout,你的logging-agent還可使用fluentd,後端存儲還能夠是ElasticSearch。只不過,fluentd的輸入源變成了應用的日誌文件。通常來講,咱們會把fluentd的輸入源配置保存在一個ConfigMap裏,以下因此:elasticsearch

    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中,這個配置,以下所示:ide

    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裏。post

  • 這種方案部署簡單,而且對宿主機很是友好,可是這個sidecar容器極可能會消耗較多的資源,甚至拖垮應用容器。因爲日誌沒有輸出到stdout上,因此你經過kubectl logs 是看不到日誌信息的。性能

總結

以上,就是k8s最經常使用的三種收集日誌的手段了,綜合對比以上方案,比較建議你將應用日誌輸出到stdout和stderr,而後經過在宿主機上部署logging-agent的方式集中處理日誌、這種方案不但簡單,並且kubectl logs依然可使用,也是官方推薦的一種。google

轉載: http://www.javashuo.com/article/p-dgjmrfdr-ea.html

相關文章
相關標籤/搜索