使用 Sidecar Logs 读取结果时任务结果缺失

问题描述

当启用 results-from: sidecar-logs 时,如果控制器无法读取 Pod 日志,PipelineRunTaskRun 可能无法解析结果。这通常表现为结果收集中缺少 Task 结果或 Pipeline 结果。

错误表现

  • PipelineRun 显示结果收集失败:

    Failed to get PipelineResult from TaskRun Results for PipelineRun <pipelinerun-name>: invalid pipelineresults [<result-name>], the referenced results don't exist
  • TaskRun 显示缺少 Task 结果引用:

    Invalid task result reference: Could not find result with name variables for task <task-name>
  • Pod 仍存在,但无法获取 sidecar 日志:

    unable to retrieve container logs for containerd://<container-id>

根因分析

为了绕过 4 KB 终止消息大小限制,Tekton 可以通过 results-from: sidecar-logs(Tekton v0.61.0 起的 Beta 功能)从 sidecar 日志读取结果。该机制依赖 Kubernetes Pod 日志 API 来获取 sidecar 输出。如果日志 API 无法返回数据,Tekton 就无法解析结果,导致缺失 TaskResult 或 PipelineResult 引用。

常见触发原因包括:

  • Pod 日志不可用,尽管 Pod 仍存在。
  • 在使用基于文件日志的节点上,/var/log/containers/var/log/pods 下的日志条目被删除或过于频繁地轮转。
  • kubelet 或容器运行时临时不一致或重启。
  • Pod 或容器垃圾回收在结果收集前删除了日志。

故障排查

  1. 确认 TektonConfig 和 feature-flags ConfigMap 中已启用 results-from: sidecar-logs
    $ kubectl get tektonconfig config -o yaml
    
    spec:
      pipeline:
        results-from: sidecar-logs
    $ kubectl get configmap feature-flags -n tekton-pipelines -o yaml
    
    data:
      results-from: sidecar-logs
  2. 查看 PipelineRun 和 TaskRun 事件,确认结果收集失败。
    $ kubectl describe pipelinerun -n ${namespace} ${pipelinerun_name}
    
    Failed to get PipelineResult from TaskRun Results for PipelineRun <pipelinerun-name>: invalid pipelineresults [<result-name>], the referenced results don't exist
    $ kubectl describe taskrun -n ${namespace} ${taskrun_name}
    
    Invalid task result reference: Could not find result with name variables for task <task-name>
  3. 直接检查 sidecar 日志。如果以下命令返回类似错误,说明日志已无法访问:
    $ kubectl logs -n ${namespace} ${taskrun_pod} -c sidecar-tekton-log-results
    
    unable to retrieve container logs for containerd://<container-id>
  4. 检查 Tekton 控制器是否具备 Pod 日志的 RBAC 权限。缺失权限也会导致日志获取失败:
    $ kubectl auth can-i get pods/log \
      -n ${namespace} \
      --as=system:serviceaccount:tekton-pipelines:tekton-pipelines-controller
    
    yes
  5. 在节点上确认 Pod 日志文件和符号链接仍存在,且 kubelet/containerd 状态正常。

解决方案

推荐做法是延长已终止 Pod 的保留时间,以保证在收集结果时 sidecar 日志仍可访问。

  1. 在控制平面上增加 terminated-pod-gc-threshold(例如设置为 1000),观察效果。
    • 原因:在高负载环境中,许多 TaskRun Pod 可能同时完成。如果终止 Pod 数量超过阈值,Pod GC 会立即清理它们。Pod 被删除后,sidecar 的日志 API 不可用,导致无法收集结果。提高阈值可以延长清理时间窗口,给 Tekton 更多时间读取 sidecar 日志并提取结果。
    • 修改方式:参考 kube-controller-manager flags 中的 --terminated-pod-gc-threshold
    • 容量规划:估算短时间窗口(如 1 分钟)内进入 SucceededFailed 状态的 Pod 数量,并留有余量。可根据平台的工作负载指标或流水线完成数估算峰值,设置阈值高于峰值。
    • 注意:托管 Kubernetes 服务(如 EKS、AKS、GKE)通常无法访问控制平面,可能无法配置此参数。
  2. 确保节点磁盘空间充足。
    • 原因:节点磁盘压力时,kubelet 和 containerd 可能会主动清理日志和 Pod 目录,导致 sidecar 日志在控制器读取前被删除或截断。
    • 修改方式:查看并调整 KubeletConfiguration 中的驱逐配置,调整磁盘压力阈值以符合容量规划。
    • 运维建议:监控构建节点存储利用率,提前清理,避免磁盘压力触发驱逐或日志清理。
  3. 确认日志保留设置(如 kubelet 日志轮转)与流水线预期时长匹配。
    • 原因:日志轮转过快或保留文件过少,会导致 sidecar 输出在结果解析前消失,即使 Pod 仍存在。
    • 修改方式:检查 KubeletConfiguration 中的 containerLogMaxSizecontainerLogMaxFiles
  4. 考虑切换回默认的 termination-message 方式。
    • 原因:termination-message 方式不依赖 Pod 日志,完全避免上述日志可用性问题。
    • 权衡:该方式结果大小限制为 4 KB,若 Task 结果超出限制,流水线会失败,可能影响用户体验。
    • 修改方式:在 TektonConfig 中设置 results-from: termination-message。注意若通过 TektonConfig 部署 Tekton,直接修改 feature-flags ConfigMap 不会生效,因 operator 会自动回滚 ConfigMap 变更。

预防措施

  • 监控集群中 Pod 日志 API 的可用性。
  • 保持 Task 结果大小合理,尽早收集结果。
  • 在不稳定的日志环境中,将 Beta 功能视为可能不如 GA 功能稳定,定期评估其使用情况。

相关内容