前文:
Logging Operator 的文章去年拖更很久了,原以为不会再有进度,不过最近在本人的 KubeGems 我的项目中遇到解决日志可察看性局部的需要时,又从新钻研了下它,于是有了本系列的第三篇。
Logging Operator是 BanzaiCloud 下开源的一个云原生场景下的日志采集计划。它在 2020 年 3 月的时候通过重构后的 v3 版本,底层凭借高效的 fluentbit 和插件丰盛的 flunetd,Logging Operator 简直曾经完满的适配了 kubernetes 模式下的日志采集场景,将来可期。去年偶然间发现 Rancher 在 2.5 版本之后也采纳了 Logging Operator 作为对立的日志解决方案,足以阐明它正在被一些以 Kubernetes 为外围的治理平台承受,并集成至外部(也包含小白的 KubeGems)。
本文作为后面两篇的续篇,次要跟大家谈谈最近小白用 Logging Operator 来解决用户需要时的案例以及感触,所以我不打算花篇幅对其架构和应用再做形容,感兴趣的同学能够往前翻翻小白的文章。
对于指标
利用在容器化的过程中,因为容器文件系统的临时性,开发者始终面临本人的日志文件落盘和输入 stdout 的两难抉择,当研发将利用日志治理的权力交给平台时,意味着平台要做的货色远比利用一对一采集要简单。在泛滥需要中,某天有 SRE 同学发问:“咱们在阿里云中能够看到日志采集的实时速率,咱们须要为此定制品质监控指标”。这个问题也点醒了我,对于咱们在做公有云时,站在平台里面对日志采集的管道外部的察看始终是处于信息缺失的盲区。好在 fluentbit 和 fluentd 都有独立的 prometheus 插件来裸露外部的指标,不过在用 Logging Operator 后,它的指标采集依靠 prometheus operator,且架构足够清晰,因而咱们也能够有更多的抉择来满足研发的需要。
首先,咱们在定义 logging 时能够让 fluent bit(d)开启 prometheus 的采集
spec:
fluentdSpec:
metrics:
serviceMonitor: true
serviceMonitorConfig:
honorLabels: true // 关上 honorLabels 次要是为了放弃组件原有的 label,防止标签被笼罩。fluentbitSpec:
metrics:
serviceMonitor: true
这里能够看到 Logging Operator 次要依附
ServiceMonitor
来做采集端的服务发现,这里须要集群外部运行 Prometheus Operator 以反对该 CRD。如果集群外部没有改资源类型,也能够借助 Prometheus 本身的服务发现机制来实现指标的发现和采集。
不过这里仅仅只申明了采集端的指标入口,这外面默认只蕴含了 Fluent bit(d)外部根本的运行状态,如果要进一步实现对日志速率的监控,就得须要 Flunetd 出马了。早些年谷歌的 GKE 上还在用 Fluentd 作为日志采集器时,偶然间胡乱看 (有目标的剽窃) 的一条 Prometheus 插件配置引起了我的趣味
<filter **>
@type prometheus
<metric>
type counter
name logging_entry_count
desc Total number of log entries generated by either application containers or system components
</metric>
<labels>
container: $.kubernetes.container_name
pod: $.kubernetes.pod_name
</labels>
</filter>
这条规定将匹配所有进入 Fluentd 的日志,并进入到 Prometheus 这个 filter 进行计数解决。并将统计后的指标以 logging_entry_count
命名,依照日志中的一些元数据信息作为指标的 label,用于辨别来至不同的容器。
因为须要解析日志的 kubernetes 元数据,这里又须要 Fluentd 的
kubernetes-metadata-filter
插件来做容器元数据的提取。在 Logging Operator 中 Kubernetes 的元数据在 Fluent Bit 中解析,无需再在 Fluentd 额定增加该插件
尽管当初谷歌 GKE 当初也将日志采集器换成 Fluent Bit,但下面这条配置在 Logging Operator 中并不“过期”。有了前事不忘; 后事之师,咱们能够在租户的日志采集器(Flow / ClusterFlow)中将 Prometheus 插件引入进来用于剖析日志速率。当中最简略的实际如下:
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
name: default
namespace: demo
spec:
- prometheus:
labels:
container: $.kubernetes.container_name
namespace: $.kubernetes.namespace_name
node: $.kubernetes.host
pod: $.kubernetes.pod_name
metrics:
- desc: Total number of log entries generated by either application containers
or system components
name: logging_entry_count
type: counter
globalOutputRefs:
- containers-console
match:
- select:
labels:
what.you.want: collect
当上述指标入库 Prometheus 之后,咱们便能够通过这条语句查出以后集群下日志采集器的利用速率
sum by (pod) (rate(logging_entry_count[1m]))
此时,如果云平台是基于多租户多环境架构,那么你甚至能够依照租户环境、租户级别别离来聚合日志的速率。
上述仅仅是对日志总体速率的采集监控,如果咱们须要对日志内呈现的特定的内容或者对日志的 byte 进行统计时,就须要联合其它的插件进行组合。以后 Logging Operator 反对的插件还远不如 Fluentd 丰盛,不过咱们能够参照官网文档,编写须要的 plugin 集成至 Operator。Logging Operator Developers 手册
对于日志组件外部的监控和告警,Logging Operator 有一套本人的规定,能够在 logging 这个 CR 中启用这个性能
spec:
fluentbitSpec:
metrics:
prometheusRules: true
fluentdSpec:
metrics:
prometheusRules: true
这里的
prometheusRules
同样是 Prometheus Operator 治理的资源,如果集群内没有此资源类型,可手动为 Prometheus 配置 Rules
回到最后的问题,如果须要将日志的采集速率作为利用的量化指标时 ,利用logging_entry_count
即可。
对于采样
大多数状况下,日志架构不应该对业务日志采取一些不可控的策略,造成利用日志的不残缺,例如采样。在这里显然我也不举荐你在现有的架构中启用此性能。不过有时候,或者是局部魔法师无奈无效控制程序的“洪荒之力”而疯狂输入时,平台对于这类俏皮的利用时就能够采样的计划,毕竟 保障整个日志通道的可用性 是平台第一优先要思考因素。
Logging Operator 在日志采样方面,采纳了 Throttle 这个插件限速器,用一句话总结这个插件就是为每个进入到 filter 日志的管道引入了漏桶算法,让其抛弃到超过速率限度的日志。
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
name: default
namespace: demo
spec:
- throttle:
group_bucket_limit: 3000
group_bucket_period_s: 10
group_key: kubernetes.pod_name
globalOutputRefs:
- containers-console
match:
- select:
labels:
what.you.want: collect
- group_key: 日志采样的聚合 key,通常咱们依照 pod 名称来做聚合,亦或间接填写 kubenretes.metadata 的其它值聚合也行
- group_bucket_period_s: 采样的工夫范畴,默认 60s
- group_bucket_limit: 采样期间的日志桶最大容量
日志的采样速率由公式 group_bucket_limit / group_bucket_period_s
计算,当 group_key
中的日志速率超过值时则会丢到后续日志。
因为 Throttle 并没有采纳令牌桶的算法,所以它不会有 burst 来应答突发日志量的采集。
对于日志落盘
后面说到,所有基于容器的应用程序,日志的最佳实际是将日志定向到 stdout
、stderr
中,但并不是所有“魔法师”都会遵循此约定,日志文件落盘依然是当下少数研发的抉择。尽管实践上来说容器的规范 (谬误)输入也是将日志流集中重定到 /var/log/containers
下的日志文件上,但依然受限于运行时配置或者其余硬盘起因带来不可控的因素。
对于日志落盘的场景,以后业界也无对立的解决方案,但归总起来其实也就 2 个实现形式:
-
sidecar 计划
此计划是将日志采集器追随利用容器一起运行在 pod 当中,通过 volume 共享日志门路的形式采集。常见的是形式是为 kubernetes 开发一套独自的控制器,并采纳
MutatingWebhook
在 pod 启动阶段将 sidecar 的信息注入。sidecar 的计划劣势在于为每个利用的 sidecar 配置绝对独立,但劣势除占用过多资源外,采集器的更新迭代需追随利用的生命周期,对于继续保护不太优雅。
-
node agent 计划
此计划将日志采集器以
DaemonSet
的形式运行在每个 Node 当中,而后在操作系统层面进行集中采集。通常此计划须要平台的研发须要做肯定门路策略,将固定hostpath
的 vulume 挂载给容器用于利用日志落盘时应用。除此之外,咱们晓得所有 Kubernetes 默认的存储类型或者第三方的遵循 CSI 规范的存储,都会将 Volume 挂载到/var/lib/kubelet/pods/<pod_id>/volumes/kubernetes.io~<type>/<pvc_id>/mount
目录下,所以对于 node agent 更加优雅一点的计划是在 node agent 中赋予调用 Kubernetes API 的权限,让其通晓被采集容器日志映射在主机下的门路。node agent 的计划的劣势在于配置集中管理,采集器跟利用容器解耦,互不影响。毛病在于采集器存在吞吐有余的危险。
能够看到上述两个计划中,不论哪一个都与 Logging Operator 沾不上关系。的确,当下社区对此场景下还没有一个卓有成效的计划,不过依照其思路,咱们能够将 日志文件转成规范(谬误)输入流 来变相处理这个问题。
用 tail
来举个直观的例子来阐明上述的计划。
...
containers:
- args:
- -F
- /path/to/your/log/file.log
command:
- tail
image: busybox
name: stream-log-file-[name]
volumeMounts:
- mountPath: /path/to/your/log
name: mounted-log
...
尽管 tail
是一个极其简略粗犷的形式,且无奈解决日志轮转等问题,但它确实为 Logging Operator 提供了一个新的日志落盘场景下的计划。尽管看上去与 sidecar 一模一样,不过最大的区别在于,此计划能与 Logging Operator 现有的日志管道无缝兼容,日志被采集后依然能在 flow 阶段进行解决。
总结
Logging Operator 站在自动化运维的角度的确无效解决了 Kubernetes 场景下日志架构简单和利用日志采集难的问题,尽管当下对落盘日志的反对还不够全面。但随着接入的用户逐步成长,当初的问题在未来或者还有更好的解决方案。不过,当下它确实不失为最好的云原生日志架构之一。
关注公众号【云原生小白】,回复「入群」退出 Loki 学习群