feat(logs): 数据源连接方式自动探测
CI / Backend (go vet + test) (push) Canceled after 0s
CI / Frontend (lint + build + test) (push) Canceled after 0s

部署完成及启动时实测 cluster-svc(API proxy) 与 url 直连,
选择可用方式并落库,兼容平台/Loki 分别在主机或集群内的组合。
This commit is contained in:
logan committed 2026-10-30 01:23:45 +08:00
1 parent b433b5f9dd
commit 7624baa564
3 files changed
+61

No files matched your search

+2
View File
@@ -84,6 +84,8 @@ func main() {
// 清理旧版本删除部署后残留的托管数据源(幂等) // 清理旧版本删除部署后残留的托管数据源(幂等)
services.CleanupOrphanManagedLogSources() services.CleanupOrphanManagedLogSources()
// 异步重新探测运行中部署的数据源连接方式(平台/Loki 可能在主机或集群内)
go services.EnsureLogSourcesForRunningDeployments()
// 补齐/升级内置告警规则(幂等):启动即执行,存量环境也能拿到「默认启用+绑默认通道」 // 补齐/升级内置告警规则(幂等):启动即执行,存量环境也能拿到「默认启用+绑默认通道」
seed.SeedAlertRules() seed.SeedAlertRules()
+37
View File
@@ -2,6 +2,7 @@
package services package services
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
@@ -485,6 +486,32 @@ func CleanupOrphanManagedLogSources() {
db.Unlock() db.Unlock()
} }
// AutoDetectLogSource 探测数据源的可用连接方式,返回最终选择(cluster-svc / url)。
//
// 交付环境组合很多:平台可能在主机或集群内,Loki 也可能在主机或集群内。
// cluster-svc 走 kube-apiserver 的 service proxy,不依赖集群 DNS;url 直连
// 则需要平台能访问到该地址。这里按「代理优先、URL 兜底」实测,避免按部署
// 模式硬编码导致某种组合连不上。
func AutoDetectLogSource(ctx context.Context, src *models.LogSource) string {
if src.ClusterID != nil {
probe := *src
probe.TargetType = "cluster-svc"
if _, status, err := lokiProxyGET(ctx, &probe, "/ready", nil); err == nil && status == 200 {
src.TargetType = "cluster-svc"
return "cluster-svc"
}
}
if src.URL != "" {
probe := *src
probe.TargetType = "url"
if _, status, err := lokiProxyGET(ctx, &probe, "/ready", nil); err == nil && status == 200 {
src.TargetType = "url"
return "url"
}
}
return ""
}
// EnsureLogSourceForDeployment 部署成功后自动注册查询数据源(host→url;k8s→cluster-svc)。 // EnsureLogSourceForDeployment 部署成功后自动注册查询数据源(host→url;k8s→cluster-svc)。
// 已存在同名数据源时:平台托管的自动刷新连接信息,用户手填的不覆盖。 // 已存在同名数据源时:平台托管的自动刷新连接信息,用户手填的不覆盖。
func EnsureLogSourceForDeployment(d *models.LokiDeployment) { func EnsureLogSourceForDeployment(d *models.LokiDeployment) {
@@ -506,8 +533,18 @@ func EnsureLogSourceForDeployment(d *models.LokiDeployment) {
// 这里换成主机真实 IP,平台才能连上。 // 这里换成主机真实 IP,平台才能连上。
target.URL = reachableEndpoint(d) target.URL = reachableEndpoint(d)
target.ClusterID = nil target.ClusterID = nil
} else {
// k8s 部署:集群内 Service 地址也记下来,作为 URL 直连候选
target.URL = d.Endpoint
} }
// 实测可用性后决定连接方式:主机/集群内平台、主机/集群内 Loki 都兼容
detectCtx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
if method := AutoDetectLogSource(detectCtx, target); method != "" {
log.Printf("[log-source] %q 自动选择连接方式: %s", target.Name, method)
}
cancel()
db := repository.GetDB() db := repository.GetDB()
db.Lock() db.Lock()
for i := range db.LogSources { for i := range db.LogSources {
+22
View File
@@ -236,3 +236,25 @@ kubectl -n log get secret lokistack-token -o jsonpath='{.data.token}' | base64 -
- 如果集群策略要求短期凭证,可改用 `kubectl -n log create token lokistack --duration=24h` 定期轮换。 - 如果集群策略要求短期凭证,可改用 `kubectl -n log create token lokistack --duration=24h` 定期轮换。
- 上面的 Namespace 由管理员创建,平台 Token 本身没有集群级权限;只有确实需要平台自建命名空间时,才额外授予 `namespaces: create/get` 的 ClusterRole(create 无法按名称限制,预建 `log` 更安全)。 - 上面的 Namespace 由管理员创建,平台 Token 本身没有集群级权限;只有确实需要平台自建命名空间时,才额外授予 `namespaces: create/get` 的 ClusterRole(create 无法按名称限制,预建 `log` 更安全)。
## 10. 数据源连接方式(部署后自动探测)
平台自动注册的数据源不再按部署模式硬编码,部署完成后会实测两种方式:
1. **cluster-svc**:经 kube-apiserver 的 service proxy 访问
`/<namespace>/services/loki:3100/proxy`,不依赖集群 DNS / ClusterIP 直通;
2. **url**:直接访问 Loki 地址(Service DNS、主机 IP:3100 或 Ingress 域名)。
先试 cluster-svc,失败再试 url,选通的写入数据源。
| 平台位置 | Loki 位置 | 实际可用方式 |
|---|---|---|
| 集群内 | 集群内 | cluster-svc |
| 主机 | 集群内 | cluster-svc(平台能访问 apiserver:6443 时);否则 url(NodePort/Ingress) |
| 集群内 | 主机 | url(主机 IP:3100,需网络可达) |
| 主机 | 主机 | url |
注意:
- `cluster-svc` 需要凭据具备 `services/proxy` 权限(本文第 9 节的 Role 已包含);
- 平台与 API Server / Loki 之间的网络必须放行;跨 VPC 时走 VPN、专线或公网 Ingress;
- 自动探测只决定“连接方式”,不会隐藏数据源;连接失败时“测试连接”会返回具体错误。