什么情况导致Pod Log Reader返回EOF

问题描述

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

代码如下:

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 仍在运行,并且里面的服务不断地将数据打印到标准输出。那么为什么会发生这种情况呢?如何解决

更新 我发现每 4 小时 pod 流 api - 读取 - 将返回 EOF,因此我必须通过重新创建 pogLogStream 并从新的流对象读取日志,使 goroutine 休眠并稍后重试。有用。但为什么会发生这种情况??

解决方法

当您联系日志端点时,apiserver 将您的请求转发到托管您的 pod 的 kubelet。 Kubelet 服务器然后开始将日志文件 to the apiserver 的内容流式传输到您的客户端。由于它正在从文件和 not from the stdout directly 流式传输日志,因此日志文件可能会轮换 by container log manager,因此您会收到 EOF 并需要重新初始化流。