什么情况会导致 Pod 日志阅读器返回 EOF?

4

我正在使用client-go从kubernetes pods中连续拉取日志流。大多数情况下,一切都能按预期工作,直到任务运行几个小时。

以下是代码:

podLogOpts := corev1.PodLogOptions{ Follow: true, }
kubeJob, err := l.k8sclient.GetKubeJob(l.job.GetNamespace(), l.job.GetJobId())

...
podName := l.k8sclient.GetKubeJobPodNameByJobId(l.job.GetNamespace(), l.job.GetJobId())
req := l.k8sclient.GetKubeClient().CoreV1().Pods(l.job.GetNamespace()).GetLogs(podName, &podLogOpts)
podLogStream, err := req.Stream(context.TODO())

...
for {
    copied, err := podLogStream.Read(buf)
    if err == io.EOF {
       // here is place where error happens
       // usually after many hours, the podLogStream return EOF.
       // I checked the pod status it is still running and keeps printing data to pod stdout. why would this happend???
       break
    }

    ...
}

podLogStream会在3-4个小时后返回EOF。但是我检查了Pod的状态,发现Pod仍在运行,并且服务内部继续向stdout打印数据。那为什么会发生这种情况?如何解决?

更新 我发现每4个小时,pod stream api -- read -- 就会返回EOF,所以我必须让goroutine睡眠一秒钟并重试,通过重新创建pogLogStream对象并从新流对象中读取日志来实现。它起作用了。但是为什么会发生这种情况?


我遇到了同样的问题。我为每个Pod运行一个goroutine来收集日志。当错误是EOF时,我会中断并在通道中返回podId。然后启动goroutines的函数可以在从通道接收到podId时重新启动它。 - TheQuestioner
1个回答

1
当您联系日志端点时,发生的情况是API服务器将您的请求转发到托管您Pod的kubelet。然后,Kubelet服务器开始从文件中流式传输日志文件到API服务器,然后传输给您的客户端。由于它正在从文件而不是直接从stdout流式传输日志,因此可能会发生容器日志管理器旋转日志文件的情况,因此您将收到EOF并需要重新初始化流程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接