Kubernetes 集群 e2e 测试日志采集机制解析:cluster/log-dump 的使用、原理与迁移指南
本篇技术指南聚焦 Kubernetes 官方仓库 cluster/log-dump 目录下的集群日志采集机制(log-dump.sh 与 logexporter DaemonSet),说明它如何在大规模端到端(e2e)测试失败时批量抓取 master 与 node 日志、如何通过 GCS 直传与 SSH 兜底双通道工作,以及当前仓库为何将其标记为 deprecated、如何迁移到 kubernetes/test-infra 的新机制。读完你将掌握该目录中全部脚本/模板的调用参数、可配置环境变量,以及面向自有 provider 的扩展点与迁移步骤。
一、目录定位:cluster/log-dump 是做什么的
在 Kubernetes 源码仓库中,cluster/log-dump 目录只包含四个文件:
- README.md:现状说明与迁移指引(本文主体依据);
- log-dump.sh:共 716 行的 Bash 脚本,是日志采集的实际执行器;
- logexporter-daemonset.yaml:用于在集群内以 DaemonSet 方式运行 logexporter 的模板;
- OWNERS:目录维护者名单。
其职责正如 log-dump.sh 开头的注释所述:"Call this to dump all master and node logs into the folder specified in $1 (defaults to _artifacts). Only works if the provider supports SSH." 也就是在 CI/e2e 环境里,当集群出现异常时,把控制面组件日志、节点日志、systemd 服务日志乃至串口输出统一收集到本地(或 GCS),供测试框架作为 artifact 归档、定位故障。脚本作者也遗留了 TODO(log-dump.sh):理想情况下它应该归属 test/e2e,说明它本质上是为测试配套的基础设施脚本,而非集群运行时组件。
1.1 已被官方标记为 deprecated
README 的第一句话就给出明确结论:这个目录已被弃用(deprecated)。日志采集工具(log dumping utility)已从 kubernetes/kubernetes 仓库移植到了 kubernetes/test-infra 仓库的 logexporter/cluster 位置。因此:
- 如果你需要改动
log-dump.sh里的逻辑,官方要求先把自己的测试任务迁移到新机制,再谈修改; - 新发布的
kubekins-e2e镜像中已经内置了新版log-dump.sh; - 想让测试任务直接使用镜像内置脚本,只需在测试 Job 中加入环境变量
USE_TEST_INFRA_LOG_DUMPING并设为true。
需要强调:本文对旧机制的分析仍以当前仓库 cluster/log-dump/log-dump.sh 的实际实现为准,它与新机制在**采集目标、双通道设计(SSH / DaemonSet)**上高度一致,理解它有助于你更快迁移与二次开发。
二、旧机制双通道设计:SSH 直采与 logexporter DaemonSet
从源码结构看,这套机制存在两条并行的日志采集路径,二者由 main() 依据是否有 GCS 目标目录来决定:
main() 调用序列:
1. print-deprecation-note —— 打印弃用提示
2. setup —— 探测项目、加载 kube-util.sh 等依赖
3. dump_masters —— 通过 SSH 把 master 日志抓到本地
4. 若 DUMP_ONLY_MASTER_LOGS=true,则跳过节点采集直接返回
5. 若设置了 gcs_artifacts_dir → dump_nodes_with_logexporter(DaemonSet 上传 GCS)
否则 → dump_nodes(SSH 抓回本地)
6. detect_node_failures —— 读取 GCE 实例组活动日志
脚本入口处(log-dump.sh)定义了三个位置参数:
readonly report_dir="${1:-_artifacts}" # 本地归档目录,默认 _artifacts
readonly gcs_artifacts_dir="${2:-}" # GCS 目录,非空则启用 logexporter 通道
readonly logexporter_namespace="${3:-logexporter}" # logexporter 运行命名空间,默认 logexporter
典型调用方式:
# 方式一:仅 SSH 抓取到本地 ./_artifacts
cluster/log-dump/log-dump.sh
# 方式二:指定本地目录
cluster/log-dump/log-dump.sh /tmp/my_artifacts
# 方式三:节点日志经 logexporter 直传 GCS,同时 master 日志仍抓本地
cluster/log-dump/log-dump.sh /tmp/my_artifacts gs://my-bucket/ci-logs/run-123
两条通道的取舍很清晰:master 数量少、日志量大且高度关键,始终走 SSH 本地抓取;node 数量可能成百上千,逐台 SSH 会耗尽文件描述符、耗时过长,因此优先以 DaemonSet 在每台节点上就近打包并直传 GCS,SSH 只作为兜底与补漏手段。
2.1 通道 A:SSH 抓取(dump_masters / dump_nodes)
dump_masters(log-dump.sh)与 dump_nodes(log-dump.sh)采用后台进程池并发执行 save-logs,并用 max_dump_processes=25(log-dump.sh)限制同时在跑的 SSH 连接数,避免大集群下耗尽文件描述符。
save-logs(log-dump.sh)对每台节点做的事依次为:
- 探测 journalctl:若节点可用 systemd journal,则导出安装/配置服务日志与内核日志:
- master:
kube-master-installation.service、kube-master-configuration.service; - node:
kube-node-installation.service、kube-node-configuration.service; - 公共项:
journalctl -k(内核)、-u ${svc}.service(遍历 systemd 服务列表)、以及可选的全量systemd.log(当LOG_DUMP_SYSTEMD_JOURNAL=true)。
- master:
- 不适用 journalctl 的旧式节点:改抓
kern.log、docker/log、supervisord 下的一组日志。 - 记录镜像清单:
ctr -n k8s.io images ls与docker images --all分别输出 containerd / docker 拉取镜像来源到images-containerd.log、images-docker.log。 - 尝试导出覆盖率:若节点存在
/var/log/kubelet.cov,说明二进制开启了覆盖率插桩,则进入 docker 容器把kube-apiserver.cov、kube-scheduler.cov、kube-controller-manager.cov(master)或kube-proxy.cov(node)读出。 chmod -R a+r /var/log之后调用copy-logs-from-node批量拉取文件。
copy-logs-from-node(log-dump.sh)在文件名后追加 * 以一并抓取被 logrotate 轮转的旧日志(大集群、长时运行场景下普遍存在),前缀 /var/log/ 后用 scp/gcloud 的 brace 展开形式批量下载;对 gce/gke 还会额外抓取串口输出写入 serial-1.log。
dump_nodes 还额外支持两类特殊节点:
- Windows 节点:
save-logs-windows(log-dump.sh)导出 Docker 事件日志与镜像列表,GKE 上会优先调用 GCP diagnostics 工具导出整机日志包; - Kubemark hollow 节点:当
ENABLE_HOLLOW_NODE_LOGS=true时追加kubelet-hollow-node-*.log、kubeproxy-hollow-node-*.log、npd-hollow-node-*.log(log-dump.sh)。
2.2 通道 B:logexporter DaemonSet 直传 GCS
当传入 gcs_artifacts_dir 后,dump_nodes_with_logexporter(log-dump.sh)接管节点采集。它会:
- 把 logexporter-daemonset.yaml 模板拷贝到临时目录;
- 用
sed逐个替换模板占位符(log-dump.sh):{{.NodeSelector}}←topology.kubernetes.io/zone: ${ZONE}(除非显式禁用);{{.LogexporterNamespace}}、{{.ServiceAccountCredentials}}(base64 后的 GCP 服务账号)、{{.CloudProvider}}、{{.GCSPath}}、{{.EnableHollowNodeLogs}}、{{.DumpSystemdJournal}}、{{.ExtraLogFiles}}、{{.ExtraSystemdServices}};
- 通过 cluster/kubectl.sh 下发资源;创建失败则删除命名空间并回退到对全部节点走 SSH 采集;
- 以每 15 秒一次的频率轮询 GCS 上各节点 logexporter 写入的 marker 文件(路径
<gcs>/logexported-nodes-registry),最长等待90 + NUM_NODES/3秒(log-dump.sh); - 到达超时或全部成功后,把每个 logexporter Pod 自身的日志(
kubectl logs)也抓到本地,便于排查采集过程本身的故障; - 对 marker 缺失的失败节点(
NON_LOGEXPORTED_NODES)再次回退 SSH 采集;当成功节点比例低于LOG_DUMP_EXPECTED_SUCCESS_PERCENTAGE(默认 0)时置失败标志并最终以非 0 退出。
这里的关键设计是:DaemonSet 中的 Pod 会 "AlwaysRestart",因此模板要求 logexporter 长时间 sleep(24h)不退出(见 logexporter-daemonset.yaml 注释),工作完成后由调用方自行删除 DaemonSet。
三、logexporter-daemonset.yaml 模板逐段解读
logexporter-daemonset.yaml 是一个典型的 "作业模板",共 81 行,由三个对象构成(全部集中在 {{.LogexporterNamespace}} 命名空间内):
| 对象 | 要点 | 说明 |
|---|---|---|
Namespace |
{{.LogexporterNamespace}} |
隔离 logexporter 自身资源,事后整体删除 |
Secret |
google-service-account(类型 Opaque) |
挂载 service-account.json,供 logexporter 向 GCS 鉴权上传 |
DaemonSet |
logexporter(apps/v1,matchLabels: app: logexporter) |
每节点一 Pod,就近采集并上传 |
容器的关键配置:
- 镜像:
gcr.io/k8s-testimages/logexporter:v20200401-c3269f485(历史 pin 版本); - 通过
fieldRef注入spec.nodeName为NODE_NAME,命令行以--node-name=$(NODE_NAME)传给二进制,确保每 Pod 只处理所在节点; - 命令行携带
--cloud-provider、--gcs-path、--gcloud-auth-file-path=/etc/service-account/service-account.json、--enable-hollow-node-logs、--dump-systemd-journal、--extra-log-files、--extra-systemd-services,与脚本侧的环境变量一一对应; --sleep-duration=24h:配合 AlwaysRestart 策略,防止任务未完成就被重启;- 只读挂载三个卷:service-account Secret(
/etc/service-account)、宿主机/var/log(/var/log)、宿主机/etc(/workspace/etc); - 资源请求极小:
cpu: 10m / memory: 10Mi,尽量不干扰被测集群; nodeSelector保留为占位符{{.NodeSelector}},由脚本填入 zone 标签,可让 DaemonSet 只覆盖目标可用区的节点。
模板头部注释(logexporter-daemonset.yaml)同时是一份使用须知:由于 DaemonSet Pod 会因 AlwaysRestart 反复拉起,必须由使用者自行检测"工作是否完成"并删除 DaemonSet,或设定外部超时,脚本侧正是靠 GCS marker 轮询完成这一职责。
四、可配置项与环境变量汇总
结合 log-dump.sh 与 cluster/gce/config-default.sh、cluster/gce/config-test.sh,可被外部覆盖的变量如下:
| 变量 | 默认值 | 作用 |
|---|---|---|
| 位置参数 1 | _artifacts |
本地归档目录 |
| 位置参数 2 | 空 | 非空则启用 logexporter GCS 直传通道 |
| 位置参数 3 | logexporter |
logexporter 资源所在命名空间 |
LOG_DUMP_SYSTEMD_SERVICES |
containerd |
追加采集的 systemd 服务;GCE 默认配置(config-default/config-test)均透传此变量 |
LOG_DUMP_EXTRA_FILES |
空 | 追加采集的额外日志文件名 |
LOG_DUMP_SAVE_SERVICES |
空 | 追加采集的额外 systemd 服务 |
LOG_DUMP_SYSTEMD_JOURNAL |
false |
为 true 时额外导出全量 journal 至 systemd.log |
LOG_DUMP_SSH_KEY / LOG_DUMP_SSH_USER |
空 | 使用自定义实例列表(非 gce/aws)时 SSH 所需凭据,缺失则退出 |
LOG_DUMP_SAVE_LOGS |
空 | 自定义实例列表模式下追加采集的日志文件 |
LOG_DUMP_SSH_TIMEOUT_SECONDS |
空 | 对整批 SSH 采集的尽力而为式总超时,超时即停止新起任务 |
LOG_DUMP_EXPECTED_SUCCESS_PERCENTAGE |
0 |
logexporter 成功节点占比低于该值时以非 0 退出 |
DUMP_ONLY_MASTER_LOGS |
空 | 为 true 时跳过全部节点采集 |
ENABLE_HOLLOW_NODE_LOGS |
空 | 为 true 时采集 Kubemark hollow 节点日志 |
LOGDUMP_ONLY_N_RANDOM_NODES |
空 | 只随机抽取 N 台 Linux 节点抓日志(大集群省时) |
GOOGLE_APPLICATION_CREDENTIALS |
空 | logexporter 上传 GCS 的服务账号 JSON 路径 |
KUBERNETES_PROVIDER |
由 cluster 脚本设置 | 决定走哪条采集路径与哪些 provider 专属日志 |
USE_TEST_INFRA_LOG_DUMPING(新机制) |
false |
置 true 让 kubekins-e2e 作业采用 test-infra 新版脚本 |
provider 能力矩阵(来自 log-dump.sh)也非常重要:
- master 支持 SSH 的 provider:
gce、aws; - node 支持 SSH 的 provider:
gce、gke、aws; - 支持 gcloud 命令(含串口输出、Windows 采集)的 provider:
gce、gke; - 其余 provider 必须实现自定义扩展(见下节),否则会打印 "Unknown cloud-provider" 并跳过。
默认按角色采集的日志文件清单(log-dump.sh)包括:master 侧 kube-apiserver.log、kube-apiserver-audit.log、kube-scheduler.log、kube-controller-manager.log、cloud-controller-manager.log、etcd.log、etcd-events.log、glbc.log、cluster-autoscaler.log、kube-addon-manager.log、konnectivity-server.log、fluentd.log 等;node 侧 kube-proxy.log、containers/konnectivity-agent-*.log、kubelet.cov 等;此外 aws 追加 cloud-init-output.log,gce/gke 追加 startupscript.log。
五、面向自定义部署的扩展点
脚本在 log-dump.sh 显式设计了扩展钩子:若当前 shell 环境里定义了名为 log_dump_custom_get_instances 的 Bash 函数,脚本就进入自定义实例列表模式。该函数需接受一个角色参数(master 或 node),并在标准输出逐行返回主机名:
# 在调用脚本前于当前 shell 定义,示例骨架(伪代码)
log_dump_custom_get_instances() {
case "$1" in
master) your_tool list masters ;;
node) your_tool list nodes ;;
esac
}
export -f log_dump_custom_get_instances
进入该模式后,setup(log-dump.sh)不再要求 KUBE_ROOT/cluster 下的 GCE/GKE 探测能力:若是 GKE 会额外加载 cluster/gce/util.sh 复用 ssh-to-node;否则要求显式提供 LOG_DUMP_SSH_KEY 与 LOG_DUMP_SSH_USER。dump_masters、dump_nodes、dump_nodes_with_logexporter 三处都会优先从该函数读取实例清单,从而实现把日志采集复用到自建集群或云厂商上。
另一个隐藏扩展点位于 detect_node_failures(log-dump.sh):对 gce/gke,它会按实例组读取 GCP activity log 中的 compute.instances.hostError 与 compute.instances.automaticRestart 事件,以表格形式把节点故障(含自动重启)一并输出到归档,便于区分"集群故障"与"底层宿主机故障"。
六、向 test-infra 新机制的迁移路径(README 核心指引)
回到 cluster/log-dump/README.md,当前仓库对使用者的正式建议可以归纳为三步,这也是迁移到新机制的标准动作:
-
把测试 Job 切换到新版机制:不要在本仓库内继续维护
log-dump.sh。新版kubekins-e2e镜像发布时已自动附带 test-infra 版log-dump.sh;要让 Job 使用它,只需在测试 Job 中设置环境变量:USE_TEST_INFRA_LOG_DUMPING=true随后旧的 GCE/GKE 集群日志采集即可由 kubekins-e2e 内的新脚本接管,无需再引用本仓库
cluster/log-dump。 -
确认你的 provider 属于受支持集合:目前(README 写作时点)新 log-dump 机制只支持 GCE 与 GKE 两种 provider。如果你的测试仍使用这两者,迁移后无需额外开发。
-
为非 GCE/GKE provider 做两件事:
- 在 test-infra 的
kubetest中修改logDumpPath函数,加入对你所用 provider 的处理逻辑(决定日志归档路径与触发方式); - 相应调整 test-infra 版
log-dump.sh(对应本仓库旧版位于 cluster/log-dump/log-dump.sh)以适配你的环境。
- 在 test-infra 的
之所以要求"先迁移再修改",是因为新版脚本在 kubekins-e2e 镜像内持续演进、随镜像发布自动生效,新功能与修复只会落在 test-infra 一侧;继续在本仓库改旧版会导致两份实现分叉、修复无法回流。从源码也可观察到这种"分叉管理"痕迹:旧版脚本每次运行都会先打印 100 个 - 组成的弃用横幅(print-deprecation-note,log-dump.sh),提醒尽快迁移。
七、小结
cluster/log-dump 虽然已进入弃用周期,但其设计骨架——master 日志走 SSH、node 日志经 logexporter DaemonSet 直传 GCS、失败节点自动回退 SSH、O(#nodes) 的 marker 轮询核对——为大规模 e2e 集群的故障现场保全提供了完整参考实现。无论你是要在旧集群上临时抓取现场日志,还是要为自己的 provider 二次开发采集器,都可以从 log-dump.sh 与 logexporter-daemonset.yaml 中直接借鉴:并发上限 max_dump_processes、* 通配抓取轮转日志、GCS marker 注册表、log_dump_custom_get_instances 自定义钩子等设计,至今仍是可复用的工程范本;而生产环境的长期归宿,则是随 USE_TEST_INFRA_LOG_DUMPING=true 接入的 test-infra 新版机制。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00