feat(k8s): 实时日志流 + WebSocket exec 交互终端 + 前端流式日志查看器

后端:
  - GetPodLogsStream: 新增 K8s follow=true 流式日志读取
  - GetPodLogs handler: 支持 stream=true → chunked transfer 实时推流
  - ExecTerminal: WebSocket → K8s SPDY exec 双向代理 (交互式 bash)
  - 路由: GET /ws/k8s-exec/:id/namespaces/:ns/pods/:pod (WebSocket)

前端 DeploymentDetail:
  - 新增「实时流」按钮: fetch ReadableStream + TextDecoder 逐块渲染
  - 日志内容自动滚动追加

CD/CI 镜像更新:
  - POST /update-image 已可用 (前端表单+后端 API 均完成)
This commit is contained in:
attacker committed 2026-06-19 07:49:32 +00:00
1 parent 1a913549fc
commit 77045622fc
4 files changed
+201 -5

No files matched your search

+19
View File
@@ -467,6 +467,25 @@ func (c *Client) GetPodLogs(namespace, podName, container string, tailLines int)
return string(body), nil
}
// GetPodLogsStream returns the raw streaming response body for follow=true
func (c *Client) GetPodLogsStream(namespace, podName, container string, tailLines int) (io.ReadCloser, error) {
path := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/log?follow=true&tailLines=%d", namespace, podName, tailLines)
if container != "" {
path += "&container=" + container
}
url := c.BaseURL + path
resp, err := c.HTTPClient.Get(url)
if err != nil {
return nil, fmt.Errorf("GET logs stream: %w", err)
}
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return nil, fmt.Errorf("K8s API %d: %s", resp.StatusCode, string(body[:min(len(body), 300)]))
}
return resp.Body, nil
}
// --- Scale ---
// ScaleDeployment patches the replicas count for a deployment