k8s集群上会跑各种各样的系统和应用程序的pod,而为了快速发现问题和更好的做日志监控,就必须要做日志的采集和集中存储展示了。综合考虑之下,我们推荐使用EFK技术栈来实现这个目的。

k8s日志采集架构选型

1,每台节点采用DaemonSet部署agent:
原理:每台节点采用DaemonSet部署一个采集日志的agent,从/var/log/containers/目录采集所有容器的日志,而容器中的日志需要遵循docker的日志规范,把日志打入stdout/stderr,这样k8s会自动在/var/log/containers/目录生成对应容器的日志。
优点:部署维护简单,且能收集所有容器的日志
缺点:需要应用程序日志支持stdout/stderr输出,如果每个节点的日志规模过多,单个采集日志的agent可能成为瓶颈,不太灵活

2,pod的SideCar方式:
原理:每个pod通过SideCar方式部署一个采集日志的agent
优点:每个pod可单独配置agent,灵活性高
缺点:每个pod都需要一个SideCar比较麻烦

3,应用程序直接推送日志到日志存储:
原理:部署在pod的应用程序支持把日志直接推送到日志存储程序
优点:不用维护日志采集程序,运维简单
缺点:需要应用程序定制开发,开发成本大

总结:
建议采用1+2的方案就行日志采集,1能适应大部分场景,如果特殊应用程序不支持日志stdout/stderr的输出,采用2进行采集。

k8s日志采集软件选型

确定了整体采集架构,就需要确定通过哪个软件实现了。通常我们使用的有如下四种,我们进行大致的对比,选择适合我们的软件。
1,logstash
大名鼎鼎ELK开源架构中的一员,优点是支持复杂日志的解析功能非常强大,缺点是性能相对比较差
2,filebeat
类似于logstash,属于轻量级的日志采集开源软件,采用go语言编写,性能比logstash好。
3,fluent
Treasure Data资助的有数据采集,处理,聚合功能的开源工具,是CNCF的项目,采用c和ruby开发,插件众多,性能好,是k8s官方推荐的容器日志采集软件。
4,fluentbit
Treasure Data资助的有数据采集,处理功能的开源工具,是CNCF的项目,采用c语言开发,相对fluent功能较少,插件较少。这个软件诞生的初衷就是为了开发一款轻量级和性能更好的日志采集工具。 fluentbit性能和其它3款对比最好,更适合于资源受限情况下的日志采集,且完美支持k8s。
fluentbit官方给的和fluent的对比见:
https://docs.fluentbit.io/manual/about/fluentd-and-fluent-bit

总结:
建议使用fluentbit来通过DaemonSet方式部署在节点进行容器日志采集,因为有更好的性能和更少的资源消耗。需要特殊复杂的日志解析处理case,可以用fluent或者filebeat使用SideCar方式采集。

k8s日志存储选型

考虑到日志存储+日子分析+数据展示绘图的需求,故开源实现里面最优秀的就是ELK架构了,故建议采用elasticsearch做日志存储+kibana做绘图展示。

部署flunetbit

本文安装的flunetbit使用fluentbit 1.4的官方文档中kubernetes相关部分完成部署

# kubectl create namespace logging
# kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/fluent-bit-service-account.yaml
# kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/fluent-bit-role.yaml
# kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/fluent-bit-role-binding.yaml

先获取访问elasticsearch的用户名elastic和对应密码,然后下载configmap manifest,根据使用的elasticsearch环境修改fluent-bit-configmap.yaml中相关output-elasticsearch.conf的配置。主要字段说明如下:
1,HTTP_User和HTTP_Passwd:为访问elasticsearch的认证
2,tls和tls.verify:默认elasticsearch必须使用https访问,故需要开启tls认证。而elasticsearch的证书为自签名证书,故可以关闭tls验证功能。
3,Logstash_Format:开启logstash日志格式的兼容
4,Logstash_Prefix:当Logstash_Format开启之后,此字段配置了index的前缀名字,如果配置为k8s-fluentbit,则index name格式为mydata-YYYY.MM.DD。而YYYY.MM.DD的value取值为每条日志生成的时间的年月日。
5,Time_Key:当Logstash_Format开启之后,默认此字段的value为@timestamp,会自动给每条message中添加一个@timestamp字段。这个字段的取值也是每条日志的生成时间,目前在k8s环境,@timestamp的value为k8s container日志的time字段的value。
6,Current_Time_Index:不使用每条日志的时间作来生成相关的时间戳字段,例如Logstash_Prefix和Time_Key配置中的相关时间戳字段。

# kubectl get secret quickstart-es-elastic-user -o=jsonpath='{.data.elastic}' | base64 --decode; echo
J1fO9bu88j8pYK8rIu91a73o

# wget https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/output/elasticsearch/fluent-bit-configmap.yaml

# vim fluent-bit-configmap.yaml
  output-elasticsearch.conf: |
    [OUTPUT]
        Name            es
        Match           *
        Host            ${FLUENT_ELASTICSEARCH_HOST}
        Port            ${FLUENT_ELASTICSEARCH_PORT}
        Logstash_Format On
        Logstash_Prefix k8s-fluentbit
        Replace_Dots    On
        Retry_Limit     False
        tls             On
        tls.verify      Off
        HTTP_User       elastic
        HTTP_Passwd     J1fO9bu88j8pYK8rIu91a73o
        Type            flb

# kubectl apply -f fluent-bit-configmap.yaml

下载daemonset manifest,根据使用的elasticsearch环境修改相关的3个配置:
1,由于我们使用的k8s为1.18.2版本,故需要修改apiVersion为新版本:

apiVersion: apps/v1

2,在spec下面添加selector,由于默认的manifest apply的时候会报'Missing required field "selector"',故需要添加一个selector(和spec.template.metadata.labels.k8s-app的值相同,通过这个manifest创建的pod都会有此label),标识了daemonset操作的对象:

  selector:
    matchLabels:
      k8s-app: fluent-bit-logging

3,修改FLUENT_ELASTICSEARCH_HOST的value为如下:

value: "quickstart-es-http.default.svc"

应用manifest,在所有节点都会启动一个pod:

# kubectl apply -f fluent-bit-ds.yaml

# kubectl get pods -n logging -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
fluent-bit-b5sfx   1/1     Running   0          43m   10.109.125.213   work3                
fluent-bit-cdxsl   1/1     Running   0          43m   10.105.104.131   master2              
fluent-bit-cqtsd   1/1     Running   0          43m   10.99.1.102      work1                
fluent-bit-js8rf   1/1     Running   0          43m   10.100.136.2     master3              
fluent-bit-z2kbc   1/1     Running   0          43m   10.97.40.73      master1              
fluent-bit-zw***   1/1     Running   0          43m   10.107.199.125   work2                

通过kibana查看日志是否正常流入elasticsearch:
k8s使用EFK实现日志采集存储展示_第1张图片

参考

https://docs.fluentbit.io/manual/about/what-is-fluent-bit
https://gist.github.com/StevenACoffman/4e267f0f60c8e7fcb3f77b9e504f3bd7
https://docs.fluentbit.io/manual/installation/kubernetes
https://docs.fluentbit.io/manual/pipeline/outputs/elasticsearch
https://docs.fluentbit.io/manual/pipeline/outputs/tcp-and-tls
https://kubernetes.io/zh/docs/concepts/workloads/controllers/daemonset/