- 云原生
- 容器运行时
【免费下载链接】kata-containers
Kata Containers is an open source project and community working to build a standard implementation of lightweight Virtual Machines (VMs) that feel and perform like containers, but provide the workload isolation and security advantages of VMs. https://katacontainers.io/
导读
本文基于 Kata Containers 官方文档整理,完整讲解如何将 Kata 运行时产生的日志导入 Fluentd,进而汇入 Elastic/Fluentd/Kibana(EFK)或 Elastic/Logstash/Kibana(ELK)日志分析栈。文章覆盖两条主流路径:默认logfmt格式经 systemd journal 间接导入,以及通过--log-format=json让 Kata 直接产出 JSON 并写入独立日志文件后直接导入。同时结合仓库源码(src/runtime/cmd/kata-runtime/main.go、src/runtime/pkg/katautils/logger.go等)说明底层日志机制,并给出 Katashimv2运行时(与containerd集成)下的日志分离方案与已知注意事项。读完本文,你将能够在自己的 Kubernetes/CRI-O 环境中复现完整的 Kata 日志采集、解析、过滤与可视化链路。
提示:本文不涉及任何"日志轮转(log rotation)"话题。生产环境的日志增长控制应由现有监控栈自行处理。
Kata 日志体系概览
Kata Containers 的日志由栈中多个组件共同产生:运行时(kata-runtime)、代理(agent)、shim(以及历史版本的proxy)都会输出日志。默认情况下,这些日志会写入系统日志(systemd journal),也可以被配置为写入独立文件。
日志的默认格式是logfmt结构化日志(即key=value键值对形式),但可以通过命令行选项切换为 JSON 格式。这两点正是本文两条导入路径的分水岭:
| 维度 | 选项 A(默认) | 选项 B |
|---|---|---|
| 存储位置 | systemd journal(系统日志) | 独立日志文件(如/var/log/kata-runtime.log) |
| 日志格式 | logfmt | JSON |
| 导入 Fluentd 的方式 | systemd插件读取 journal +parser插件解析logfmt | tail插件直接读取文件 +json解析 |
从源码看,kata-runtime通过 src/runtime/cmd/kata-runtime/main.go 中的全局命令行标志定义了两个关键选项:
--log:设置日志文件路径(默认值为/dev/null,即默认不写文件);--log-format:设置日志格式(默认text,可选json)。
同时在 src/runtime/cmd/kata-runtime/main.go 中,log-format被严格限定为text或json两个取值,传入其他值会直接报错unknown log-format %q,并由配套单测 main_test.go 覆盖验证。
关于 Kata 各组件日志的详细字段要求,可以参考 kata-log-parser 工具的文档:默认每个日志记录需包含level、name、pid、source、time(RFC3339 带纳秒)以及msg字段。这为我们后续在 Kibana 中按字段过滤提供了依据。
测试栈搭建:minikube + EFK
部分验证可以在本地完成,但要完整测试日志导入链路,需要一个真实的运行环境。官方文档采用minikube + EFK addon + Kata Containers的组合:
- 按照 minikube 安装指南 安装启用了 Kata Containers 的
minikube; - 启用 EFK addon:
$ minikube addons enable efk注意:EFK 的安装与启动可能需要一段时间,可用
kubectl get pods -n=kube-system检查进度,等待所有 Pod 进入Running状态。
不同安装中组件路径与版本可能不同,请按实际环境调整。
路径一:从 systemd journal 直接导入logfmt日志
这条路径利用 Fluentd 的两个组件:读取 journal 的systemd插件与解析logfmt的parser插件,分两步将 Kata 日志导入 EFK。
让 Fluentd 能读到 journal:给 minikube 打补丁
minikube 默认将systemd-journald配置为Storage=volatile,journal 数据存放在/run/log/journal。而 minikube 自带的 EFK Fluentd 部署默认只挂载/var/log(与/var/lib/docker/containers),不会挂载/run/log,因此 Fluentd Pod 默认读不到系统 journal。
解决办法是修改 EFK addon 的 YAML,把/run/log也挂载进 Fluentd 容器。官方文档给出的 patch 如下(针对deploy/addons/efk/fluentd-es-rc.yaml.tmpl):
diff --git a/deploy/addons/efk/fluentd-es-rc.yaml.tmpl b/deploy/addons/efk/fluentd-es-rc.yaml.tmpl index 75e386984..83bea48b9 100644 --- a/deploy/addons/efk/fluentd-es-rc.yaml.tmpl +++ b/deploy/addons/efk/fluentd-es-rc.yaml.tmpl @@ -44,6 +44,8 @@ spec: volumeMounts: - name: varlog mountPath: /var/log + - name: runlog + mountPath: /run/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true @@ -57,6 +59,9 @@ spec: - name: varlog hostPath: path: /var/log + - name: runlog + hostPath: + path: /run/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers注意:修改后需要重新构建自己的 minikube 镜像以固化该改动,或另寻其他方式(重新)启动 Fluentd 容器让改动生效。
Fluentd 从 systemd 拉取 Kata 日志
在 Fluentd 配置中加入以下<source>片段,使用systemd插件读取 journal,并按SYSLOG_IDENTIFIER过滤出 Kata 相关条目:
<source> type systemd tag kata-containers path /run/log/journal pos_file /run/log/journal/kata-journald.pos filters [{"SYSLOG_IDENTIFIER": "kata-runtime"}, {"SYSLOG_IDENTIFIER": "kata-shim"}] read_from_head true </source>参数说明:
path:journal 目录路径(minikube 默认/run/log/journal);pos_file:记录读取位置的文件,避免重复导入;filters:仅捕获SYSLOG_IDENTIFIER为kata-runtime或kata-shim的日志条目;read_from_head true:从 journal 头部开始读取。
注意:上述片段为"较旧风格",以匹配 minikube 内置 Fluentd 版本。若使用较新的 Fluentd,可能需要将
filters改为matches、并在type前加@(如@type)。若确有此类更新需求,Fluentd 自身日志中会有相应警告。
应用配置并重启 Fluentd Pod(kill 后由 ReplicationController 重新创建,以加载新的 ConfigMap):
$ kubectl apply -f new-fluentd-cm.yaml $ kubectl delete pod -n=kube-system fluentd-es-XXXXX随后打开 Kibana,并启动一个基于 QEMU 的 Kata 测试 Pod 以产生日志:
$ minikube addons open efk $ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/packaging/kata-deploy $ kubectl apply -f examples/nginx-deployment-qemu.yaml(具体路径与版本号请按实际安装调整。)
在 Kibana 中即可看到kata-runtime标记的记录出现:
按该 tag 过滤后,可只查看 Kata 相关条目:
展开任意一条记录,可以看到导入进来的有用信息,并可进一步按SYSLOG_IDENTIFIER区分 Kata 各组件、按PRIORITY过滤关键问题等。
用 logfmt 解析器把MESSAGE拆成可过滤字段
Kata 产生的大量信息以logfmt形式打包在MESSAGE字段中(其字段要求见 kata-log-parser 文档)。原样导入后,Kibana 中无法直接对这些子字段进行过滤:
解决办法是再加一个parserfilter,把MESSAGE里的logfmt子字段解析为独立字段,并统一加上kata_前缀以示来源:
<filter kata-containers> @type parser key_name MESSAGE format logfmt reserve_data true inject_key_prefix kata_ </filter>参数说明:
key_name MESSAGE:要解析的字段;format logfmt:指定解析格式;reserve_data true:保留原始数据(包括MESSAGE本身);inject_key_prefix kata_:为解析出的新字段统一添加kata_前缀。
minikube 自带的 Fluentd 版本未预装logfmt解析器,因此官方文档在本地先行验证了解析效果。经解析后的一条记录示例如下:
2020-02-21 10:31:27.810781647 +0000 kata-containers: {"_BOOT_ID":"590edceeef5545a784ec8c6181a10400", "_MACHINE_ID":"3dd49df65a1b467bac8d51f2eaa17e92", "_HOSTNAME":"minikube", "PRIORITY":"6", "_UID":"0", "_GID":"0", "_SYSTEMD_SLICE":"system.slice", "_SELINUX_CONTEXT":"kernel", "_CAP_EFFECTIVE":"3fffffffff", "_TRANSPORT":"syslog", "_SYSTEMD_CGROUP":"/system.slice/crio.service", "_SYSTEMD_UNIT":"crio.service", "_SYSTEMD_INVOCATION_ID":"f2d99c784e6f406c87742f4bca16a4f6", "SYSLOG_IDENTIFIER":"kata-runtime", "_COMM":"kata-runtime", "_EXE":"/opt/kata/bin/kata-runtime", "SYSLOG_TIMESTAMP":"Feb 21 10:31:27 ", "_CMDLINE":"/opt/kata/bin/kata-runtime --config /opt/kata/share/defaults/kata-containers/configuration-qemu.toml --root /run/runc state 7cdd31660d8705facdadeb8598d2c0bd008e8142c54e3b3069abd392c8d58997", "SYSLOG_PID":"14314", "_PID":"14314", "MESSAGE":"time=\"2020-02-21T10:31:27.810781647Z\" level=info msg=\"release sandbox\" arch=amd64 command=state container=7cdd31660d8705facdadeb8598d2c0bd008e8142c54e3b3069abd392c8d58997 name=kata-runtime pid=14314 sandbox=1c3e77cad66aa2b6d8cc846f818370f79cb0104c0b840f67d0f502fd6562b68c source=virtcontainers subsystem=sandbox", "SYSLOG_RAW":"<6>Feb 21 10:27 kata-runtime[14314]: time=\"2020-02-21T10:31:27.810781647Z\" level=info msg=\"release sandbox\" ...", "_SOURCE_REALTIME_TIMESTAMP":"1582281087810805", "kata_level":"info", "kata_msg":"release sandbox", "kata_arch":"amd64", "kata_command":"state", "kata_container":"7cdd31660d8705facdadeb8598d2c0bd008e8142c54e3b3069abd392c8d58997", "kata_name":"kata-runtime", "kata_pid":14314, "kata_sandbox":"1c3e77cad66aa2b6d8cc846f818370f79cb0104c0b840f67d0f502fd6562b68c", "kata_source":"virtcontainers", "kata_subsystem":"sandbox"}可以看到,MESSAGE中的logfmt键值对被拆解为kata_level、kata_command、kata_subsystem等可直接在 Kibana 中过滤的字段。
路径一小结:通过systemd插件从 journal 捕获 Kata 日志,再用logfmt解析器把MESSAGE转为 JSON 字段,即可在 Elastic/Kibana 中做进一步分析。
路径二:让 Kata 直接输出 JSON 日志文件
Fluentd 与 Elastic 的底层数据格式都是 JSON。如果让 Kata 直接输出 JSON,整体导入与处理链路会更高效。这里有两个可做组合的选项:
- 让 Kata 输出 JSON 格式(
--log-format=json)而不是默认的logfmt; - 让 Kata 直接写日志文件(
--log=/var/log/kata-runtime.log),从而绕开 systemd 格式文件的解析,避免 Fluentd 解析或跳过大量与 Kata 无关的 journal 条目。
理论上也可以只把--log-format=json加到 runtime 上、再把logfmt解析器换成json解析器,让 Kata 以 JSON 形式向 journal 发消息——但这样仍需要解析 systemd 文件,收益有限,官方文档选择直接演示完整的"Kata JSON 日志文件"方案。
修改 kata-qemu 启动脚本
从 Kata Deploy 安装(见 tools/packaging/kata-deploy)的默认环境下,最简单的方式是编辑/opt/kata/bin/kata-qemu这个 shell 脚本,在其中追加--log-format=json与--log=/var/log/kata-runtime.log两个参数:
#!/usr/bin/env bash /opt/kata/bin/kata-runtime --config "/opt/kata/share/defaults/kata-containers/configuration-qemu.toml" --log-format=json --log=/var/log/kata-runtime.log $@kata-runtime对这两个参数的解析实现在 src/runtime/cmd/kata-runtime/main.go:--log指定路径并以追加写模式打开日志文件(O_CREATE|O_WRONLY|O_APPEND|O_SYNC),--log-format=json则把日志格式切换为logrus.JSONFormatter。
用 tail 插件读取 JSON 日志文件
在 Fluentd 配置中加入以下<source>片段,用tail插件跟踪该日志文件:
<source> type tail tag kata-containers path /var/log/kata-runtime.log pos_file /var/log/kata-runtime.pos format json time_format %iso8601 read_from_head true </source>要点:
format json:告知解析器日志为 JSON;time_format %iso8601:Kata 生成的是iso8601格式时间戳,且放在名为time的字段中——这正是 Fluentd 解析器默认寻找的时间字段;pos_file:记录文件读取偏移,避免重复导入;read_from_head true:从文件头部开始读取。
导入后的记录效果如下:
字段膨胀问题与瘦身
直接导入 JSON 后,Elastic 中会出现大量看似雷同的字段:
它们其实并非完全相同,而是来自某一条 Kata 日志——例如kill命令产生的记录中包含了完整的EndpointProperties(网卡接口属性)对象,JSON 片段示例如下:
{ ... "EndpointProperties": { "Iface": { "Index": 4, "MTU": 1460, "TxQLen": 0, "Name": "eth0", "HardwareAddr": "ClgKAQAL", "Flags": 19, "RawFlags": 69699, "ParentIndex": 15, "MasterIndex": 0, "Namespace": null, "Alias": "", "Statistics": { "RxPackets": 1, "TxPackets": 5, "RxBytes": 42, "TxBytes": 426, "RxErrors": 0, "TxErrors": 0, "RxDropped": 0, "TxDropped": 0, "Multicast": 0, "Collisions": 0, "RxLengthErrors": 0, "RxOverErrors": 0, "RxCrcErrors": 0, "RxFrameErrors": 0, "RxFifoErrors": 0, "RxMissedErrors": 0, "TxAbortedErrors": 0, "TxCarrierErrors": 0, "TxFifoErrors": 0, "TxHeartbeatErrors": 0, "TxWindowErrors": 0, "RxCompressed": 0, "TxCompressed": 0 ...如果这些新字段并非必需,可以在写入 Elastic 前用 Fluentd 的record_transformerfilter 的remove_keys选项将其删除,控制索引字段数量与存储成本。
为所有字段统一添加kata_前缀
上述直接导入方式中,所有字段都保留原生名称(如arch、level)。为了便于存储与处理、避免与其他数据源的字段冲突,最好统一加上kata_前缀。Fluentd 无法直接在 input 或 match 阶段完成前缀注入,但可以在 filter/parse 阶段完成(正如前面处理logfmt数据时那样)。具体做法是:先把 Kata JSON 日志作为单行文本拉入,再用 JSON 解析 filter 加前缀:
# Pull in as a single line... <source> @type tail path /var/log/kata-runtime.log pos_file /var/log/kata-runtime.pos read_from_head true tag kata-runtime <parse> @type none </parse> </source> <filter kata-runtime> @type parser key_name message # drop the original single line `message` entry reserve_data false inject_key_prefix kata_ <parse> @type json </parse> </filter>要点:
<parse> @type none</parse>:先把每一行原样作为单条message记录接收;key_name message:告诉解析器要解析的字段名;reserve_data false:丢弃原始的整行message,避免冗余;inject_key_prefix kata_:为所有解析出的字段加kata_前缀。
Katashimv2运行时的日志处理差异
当使用 Katashimv2运行时与containerd集成(配置方式见 containerd-kata.md)时,日志路由与经典 CRI-O 场景不同,需要调整上述方法才能在 Fluentd 中正确过滤。
shimv2日志有两大特点:
- Kata 日志经由
containerd转发,会与containerd自身的日志混在一起(例如出现在 containerd 的 stdout 或系统 journal 中); - 与此同时,Kata
shimv2始终会以 systemd 名称kata把日志写入系统 journal。
这一点在 src/runtime/README.md 中有明确说明:shimv2运行时通过containerd记录日志,并始终以kata标识符写系统日志(syslog/journald),可用sudo journalctl -t kata查看。底层实现对应 src/runtime/pkg/katautils/logger.go 中的SYSLOGTAG = "kata"常量与sysLogHook(它通过logrus的 syslog hook 以kata为标识写入系统日志)。
据此,可以在 Fluentd 中用rewrite_tag_filter(Fluentd v0.12 风格)把混在一起的日志按SYSLOG_IDENTIFIER拆开:
<source> type systemd path /path/to/journal # capture the containerd logs filters [{ "_SYSTEMD_UNIT": "containerd.service" }] pos_file /tmp/systemd-containerd.pos read_from_head true # tag those temporarily, as we will filter them and rewrite the tags tag containerd_tmp_tag </source> # filter out and split between kata entries and containerd entries <match containerd_tmp_tag> @type rewrite_tag_filter # Tag Kata entries <rule> key SYSLOG_IDENTIFIER pattern kata tag kata_tag </rule> # Anything that was not matched so far, tag as containerd <rule> key MESSAGE pattern /.+/ tag containerd_tag </rule> </match>配置逻辑:
<source>只捕获containerd.service的 journal 条目,先统一打上临时 tagcontainerd_tmp_tag;<match>中第一条规则把SYSLOG_IDENTIFIER为kata的条目重打为kata_tag;- 第二条规则把剩余未匹配的条目(
MESSAGE匹配任意内容)打为containerd_tag,实现 Kata 与 containerd 日志的分离。
已知注意事项(Caveats)
在使用上述方案前,应了解以下几点可能影响采集与处理的限制:
- 日志损坏风险:启用 Kata 完整 debug(尤其是启用 agent 内核日志消息)时,由于多个输出流重叠,Kata 可能产生损坏的日志行(对应历史 issue:kata-containers/runtime#985)。
- JSON 日志能力范围:目前只有
kata-runtime能生成 JSON 日志并写入文件;其他组件(如proxy与shim)目前只能向系统 journal 汇报日志,尚不具备该能力,有待后续版本扩展。
总结
本文围绕 Kata Containers 日志的 Fluentd 导入,给出了两条完整可落地的路径:
- 默认路径(journal + logfmt):利用 Fluentd 的
systemd插件从系统 journal 捕获kata-runtime/kata-shim条目,再用parserfilter 把MESSAGE中的logfmt数据拆解为带kata_前缀的可过滤字段,最终在 Kibana 中按SYSLOG_IDENTIFIER、PRIORITY、kata_level等字段灵活筛选; - JSON 路径(文件 + json):通过
kata-qemu启动脚本给kata-runtime追加--log-format=json --log=/var/log/kata-runtime.log,让 Kata 直接产出 JSON 日志文件,Fluentd 用tail+json解析直接导入;如需统一字段命名,可先用@type none逐行拉入再用 JSON 解析 filter 加kata_前缀,并可配合record_transformer的remove_keys删除不需要的嵌套字段。
对于与containerd集成的 Katashimv2运行时,日志会同时流向 containerd 与系统 journal(标识符kata),可使用rewrite_tag_filter按SYSLOG_IDENTIFIER拆分 Kata 与 containerd 日志。最后请留意已知 caveat:全量 debug 可能产生损坏日志行,且目前仅kata-runtime支持 JSON 文件日志。具体方案的选择,应结合自身栈的版本与运维习惯决定。
- 云原生
- 容器运行时
【免费下载链接】kata-containers
Kata Containers is an open source project and community working to build a standard implementation of lightweight Virtual Machines (VMs) that feel and perform like containers, but provide the workload isolation and security advantages of VMs. https://katacontainers.io/
相关推荐
SafeLine日志聚合:ELK/EFK日志分析集成
SafeLine日志聚合:ELK/EFK日志分析集成 概述 在Web应用防火墙(WAF)的日常运维中,日志分析是至关重要的一环。SafeLine作为一款强大的开
WAF网络安全应用安全如何永久免费使用AI编程助手:终极破解方案指南
如何永久免费使用AI编程助手:终极破解方案指南 你是否经常遇到AI编程助手Cursor的试用限制?当看到"Too many free trial account
开发工具CLIOpCore-Simplify:黑苹果配置终极自动化解决方案
OpCore Simplify:黑苹果配置终极自动化解决方案 还在为复杂的黑苹果配置而苦恼吗?OpCore Simplify是一款革命性的 自动化EFI生成工具
开发工具CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考