k8s☞18日志系统

阅读量: zyh 2021-06-17 16:21:58
Categories: > Tags:

前言

k8s的集群日志收集结构,一般分为下面几种:

  1. 集群节点级模式,节点程序收集系统(k8s和容器)底层日志,并传输到日志系统。
  2. 伪边车容器模式,边车容器程序只负责将共享卷里的文件日志读取并传输到节点的stdout和stderr,然后节点级Pod收集器获取日志并传输到日志系统。
  3. 边车容器模式,边车容器程序通过共享卷从应用程序那收集日志,然后传输到日志系统。
  4. 应用容器模式,主容器程序直接将日志流式传输到日志系统。

k8s的日志收集分两部分:

自身日志

采用daemonset方式在每一个节点上部署一个日志收集程序。对节点的日志目录采集:

应用日志

集群节点级模式(模式1)

采用daemonset方式在每一个节点上部署一个日志收集程序。对节点的日志目录采集:

例如:官方的示例EFK,fluentd(节点级收集器)=》elasticsearch =》 kibana

✨这种方式,需要主容器程序将日志输出到stdout和stderr。

伪边车容器模式(模式2)

前提:主容器程序需要将日志以文件形式放在共享卷中。

通过边车容器程序将日志文件重新读取并输出到stdout,比如用tail -n+1 -f log.file

然后通过集群节点级模式的方式收集日志。

💥相比于模式1,主容器程序写入一次日志文件,同时边车容器程序又重新读取文件日志,对磁盘负担增大。

✨这种方式,目的是解决日志文件在本地,但又不想给每一个pod部署一个日志收集程序。毕竟日志收集程序占用资源多。

总的来说是:磁盘压力大,CPU和内存额外开销小。

一个Pod例子:

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: {}

边车容器模式(模式3)

前提:主容器程序需要将日志以文件形式放在共享卷(例如通过emtyDir共享日志目录)。

通过边车容器程序将文件日志重新读取并发送到远程日志系统,例如用filebeat;

💥相比于模式1,主容器程序写入一次日志文件,同时边车容器程序又重新读取文件日志,对磁盘负担增大。

💥相比于模式2,无需将日志在写入到节点级,磁盘负担压力小了50%。但filebeat程序CPU和内存消耗大。

每一个运行的pod中添加一个日志收集容器filebeat,通过共享卷共享日志目录收集应用日志,将收集后的日志数据传输到logstash

logstash 通过 filebeat 配置的标签创建不同的索引

filebeat示例

节点级DaemonSet类型filebeat,收集k8s节点日志并传输到kafka

https://www.elastic.co/guide/en/beats/filebeat/7.17/running-on-kubernetes.html

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: k8s-logs
  namespace: kube-system
spec:
  selector:
    matchLabels:
      project: k8s
      app: filebeat
  template:
    metadata:
      labels:
        project: k8s
        app: filebeat
    spec:
      hostAliases:
      - ip: "10.200.16.51"
        hostnames:
        - "data01"
      - ip: "10.200.16.52"
        hostnames:
        - "data02"
      - ip: "10.200.16.53"
        hostnames:
        - "data03"
      containers:
      - name: filebeat
        image: docker.elastic.co/beats/filebeat:7.17.1
        args: [
          "-c", "/etc/filebeat.yml",
          "-e",
        ]
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 500m
            memory: 500Mi
        securityContext:
          runAsUser: 0
        volumeMounts:
        - name: filebeat-config
          mountPath: /etc/filebeat.yml
          subPath: filebeat.yml
        - name: k8s-logs
          mountPath: /messages
      volumes:
      - name: filebeat-config
        configMap:
          name: k8s-logs-filebeat-config
      - name: k8s-logs
        hostPath:
          path: /var/log/messages
          type: File
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: k8s-logs-filebeat-config
  namespace: kube-system
data:
  filebeat.yml: |-
    filebeat.shutdown_timeout: 5s
    close_removed: true
    clean_removed: true
    filebeat.inputs:
    - type: log
      enabled: true
      paths:
      - /messages
      tags: ["k8s","messages"]
      fields:
        log_topic: zz.it.elk.k8s.messages
      fields_under_root: true
    output.kafka:
      hosts: ["data01:8123", "data01:8123", "data01:8123"]
      username: elk
      password: 123456
      sasl.mechanism: 'SCRAM-SHA-256'

      topic: '%{[log_topic]}'
      partition.round_robin:
        reachable_only: false

      required_acks: 1
      compression: gzip
      max_message_bytes: 1000000

logstash 配置

input {
  beats {
    port => 5044
  }
}

filter {

}

output {
  elasticsearch {
    hosts => ["http://xxx:9200"]
    index => "k8s-syslog-%{+YYYY.MM.dd}"
  }
}

# 调试用
stdout {
  codec => rubydebug
}

节点级filebeat

- type: log
  paths:
    - /messages
  fields:
    app: k8s
    type: module
  fields_under_root: true
  output.logstash:
    hosts: ['xxx:5044']