我正在尝试通过 Gin 处理程序函数将日志从特定 pod 流式传输回客户端
import (
"context"
...
"github.com/gin-gonic/gin"
"io"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
...
"k8s.io/client-go/tools/clientcmd"
)
func Logs(c *gin.Context) {
...
clientset := i.getClient(err, configuration)
options := metav1.ListOptions{
LabelSelector: fmt.Sprintf("dhis2-id=%d", instance.ID),
}
podList, err := clientset.CoreV1().Pods("").List(context.TODO(), options)
if err != nil {
log.Fatalln(err)
}
if len(podList.Items) > 1 {
log.Fatalln("More than one pod found... TODO")
}
pod := podList.Items[0]
logOptions := v1.PodLogOptions{
Follow: true,
}
logs := clientset.
CoreV1().
Pods(pod.Namespace).
GetLogs(pod.Name, &logOptions)
reader, err := logs.Stream(context.TODO())
if err != nil {
log.Fatalln(err)
}
c.Stream(func(writer io.Writer) bool {
_, err := io.Copy(writer, reader)
if err != nil {
return false
}
return true
})
c.Status(http.StatusOK)
}
func getClient(err error, configuration *model.ClusterConfiguration) *kubernetes.Clientset {
configurationInCleartext, err := configuration.GetKubernetesConfigurationInCleartext()
if err != nil {
log.Fatalln(err)
}
config, err := clientcmd.NewClientConfigFromBytes(configurationInCleartext)
if err != nil {
log.Fatalln(err)
}
clientConfig, err := config.ClientConfig()
if err != nil {
log.Fatalln(err)
}
clientset, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
log.Fatalln(err)
}
return clientset
}
我面临两个问题
它不流。它获取日志直到“现在”,然后它不会继续
它得到的日志被两个换行符分隔,而不仅仅是一个。一个例子可以在下面看到
...
2021/06/09 16:25:55 端点命中:/health
2021/06/09 16:25:59 端点命中:/health
2021/06/09 16:26:05 端点命中:/health
2021/06/09 16:26:09 端点命中:/health
2021/06/09 16:26:15 端点命中:/health
2021/06/09 16:26:19 端点命中:/health
2021/06/09 16:26:25 端点命中:/health
2021/06/09 16:26:29 端点命中:/health
任何关于我做错了什么的线索?
更新:下面的代码修复了流媒体缺失的问题,但仍有一个\n太多
(灵感来自:https://github.com/kubernetes/kubectl/blob/master/pkg/cmd/logs/logs.go#L418)
c.Stream(func(writer io.Writer) bool {
bytes, err := bufferedReader.ReadBytes('\n')
if err != nil {
return false
}
_, err = writer.Write(bytes)
if err != nil {
return false
}
return true
})