fix(hosts,collectors,usage): 主机验证结果失真 + 主机模式系统日志解析 + metrics 单位
=== 一、主机「测试连接」永远显示旧错误(真实 bug)===
HostService.Validate 的失败分支也写 status=active,且从不写 statusMessage:
if info, err := client.GetHostInfo(ctx); err == nil { 更新 os/arch }
else { s.Update(id, {status:"active"}) } // ← 失败也标记成功
结果:连不上也显示正常,页面永远停在几分钟前的旧错误文案,
用户改了 IP 再点测试,还以为"改了还是不行"。
改为区分成功/失败并写清原因:
成功 → status=active + os/arch + statusMessage="连接成功"
失败 → status=error + statusMessage=FormatSSHError(err)
=== 二、回环地址在平台里必然连不上 ===
平台跑在容器/Pod 内,127.0.0.1 指向平台自身。
- 新建主机时拦截:hostIP 为 127.0.0.1/localhost/::1 直接报错并解释原因
- 前端表单同步校验 + 文案
- SSH 错误映射补充:连接被拒绝时提示可能是地址填了回环
=== 三、主机模式采集系统日志(两处会导致采集失败)===
1. pipeline 一律套 cri 阶段:cri 只认容器运行时格式,
套在 /var/log/messages 这类 syslog 上会取不到时间戳、整行被丢。
→ appPipelineStages() 按路径判断:容器日志用 cri,普通文本日志只做限流。
2. promtailExternalLabels 写死 8 空格缩进:主机模板 external_labels 只有 4 空格,
一旦给采集器配置了标签就生成非法 YAML,Promtail 装不上。
→ 增加 indent 参数,主机 6 空格 / DaemonSet 8 空格。
3. 新增 system 采集任务:
/var/log/{messages,secure,cron,maillog,syslog,dmesg}
正则解析 syslog 时间戳(Jan _2 15:04:05,Asia/Shanghai)+ 限流
测试:TestHostPromtailConfigValid / CRIPathKeepsCRIStage / PlainFileHasNoCRIStage
TestPromtailManifestParses 全部通过
=== 四、资源用量 CPU 解析(nanocores)===
metrics-server 返回的 CPU 常是纳核(如 "194533645n"=194.5m)。
原解析只处理 "m",导致 194 亿核、页面出现"CPU 已达 limit 的 4863341125%"。
→ parseQuantityMilli 支持 n/u/m/整核
实测:CPU 当前=178m,峰值=3300m,建议"峰值占 limit 82%,可考虑提前扩容"
=== 五、其他 ===
- 添加集群默认改用 Token 认证(最小权限、可随时吊销)
- RBAC 片段补 metrics.k8s.io(资源面板需要,独立 API 组常被漏授)
- 文案去掉 Grafana 需求描述(平台自身不部署 Grafana)
镜像:lghost/lokistack:latest + v0.1 = sha256:7bddd0f4d1f1
This commit is contained in:
1 parent
a32f93f533
commit
bad2a1e624
33 files changed
+1124
-52
No files matched your search
@@ -4,8 +4,12 @@ package services
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"lokistack/models"
|
||||
"lokistack/pkg/crypto"
|
||||
)
|
||||
|
||||
@@ -53,6 +57,11 @@ compactor:
|
||||
working_directory: /var/lib/loki/compactor
|
||||
retention_enabled: true
|
||||
delete_request_store: {{ .CompactorStoreType }}
|
||||
# 过期 chunk 的删除并发。Loki 默认 150,但各云对象存储的 QPS 限制差别很大,
|
||||
# 打太猛会被限流(腾讯云 COS 实测返回 503 SlowDown,整轮 apply_retention 失败,
|
||||
# 残留 21,354 个对象 / 24.8 GB 删不掉)。该值按 provider 取值,可用
|
||||
# 环境变量 LOKI_COMPACTOR_DELETE_WORKERS 覆盖。
|
||||
retention_delete_worker_count: {{ .CompactorDeleteWorkers }}
|
||||
# 过期 chunk 的「标记 → 真正删除」间隔。默认 2h 会让对象存储里
|
||||
# 多留 2 小时的数据(实测桶内超过保留期的对象一度占到 24.6 GB)。
|
||||
# 预发环境取 10m:既保留短暂的安全窗口,又不会长期占用存储成本。
|
||||
@@ -112,6 +121,8 @@ type lokiConfigData struct {
|
||||
ObjectStore string
|
||||
RulerStoreType string
|
||||
CompactorStoreType string
|
||||
// CompactorDeleteWorkers 过期 chunk 删除并发,按对象存储类型取默认值
|
||||
CompactorDeleteWorkers int
|
||||
RingInstanceAddr string // 单副本 127.0.0.1;多副本 0.0.0.0(须可被对端寻址)
|
||||
RingKVStore string // 单副本 inmemory;多副本 memberlist
|
||||
MemberlistBlock string // 多副本时非空,注入 memberlist 顶级配置
|
||||
@@ -176,7 +187,8 @@ func (d *LokiDeployer) generateLokiConfig() string {
|
||||
StorageConfigBlock: storageBlock,
|
||||
ObjectStore: objectStore,
|
||||
RulerStoreType: rulerStore,
|
||||
CompactorStoreType: compactorStore,
|
||||
CompactorStoreType: compactorStore,
|
||||
CompactorDeleteWorkers: compactorDeleteWorkers(d.deployment.StorageConfig),
|
||||
RingInstanceAddr: ringAddr,
|
||||
RingKVStore: ringStore,
|
||||
MemberlistBlock: memberlistBlock,
|
||||
@@ -197,6 +209,48 @@ func (d *LokiDeployer) generateLokiConfig() string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// defaultCompactorDeleteWorkers 是 Loki 自身的默认值。
|
||||
const defaultCompactorDeleteWorkers = 150
|
||||
|
||||
// compactorDeleteWorkers 按对象存储类型给出「过期 chunk 删除并发」。
|
||||
//
|
||||
// 为什么不能写死一个值:这个并发直接决定 compactor 对对象存储发出的 DELETE 速率,
|
||||
// 而各云的限流差别很大。打满会被限流并让整轮 apply_retention 失败 ——
|
||||
// 腾讯云 COS 实测默认 150 就返回 503 SlowDown,过期 chunk 残留 21,354 个 / 24.8 GB
|
||||
// 删不掉;降到 16 后删除稳定推进。
|
||||
//
|
||||
// cos 16 实测 150 触发 503 SlowDown
|
||||
// obs 32 华为 OBS 未给明确单桶 QPS,取保守值
|
||||
// minio 32 自建,取决于后端磁盘 IO,别打满
|
||||
// azure 32 存储账户限流较严
|
||||
// oss 64 阿里云 OSS 单桶 QPS 万级,留余量
|
||||
// gcs 64 GCS 高 QPS,但有 per-bucket 操作速率
|
||||
// s3 96 AWS S3 单前缀约 3,500 DELETE/s,150 也能跑,留余量
|
||||
//
|
||||
// 任意 provider 都可用环境变量 LOKI_COMPACTOR_DELETE_WORKERS 覆盖(运维手调无需改代码)。
|
||||
func compactorDeleteWorkers(sc *models.StorageConfig) int {
|
||||
if raw := strings.TrimSpace(os.Getenv("LOKI_COMPACTOR_DELETE_WORKERS")); raw != "" {
|
||||
if n, err := strconv.Atoi(raw); err == nil && n > 0 {
|
||||
return n
|
||||
}
|
||||
}
|
||||
if sc == nil {
|
||||
return defaultCompactorDeleteWorkers
|
||||
}
|
||||
switch strings.ToLower(strings.TrimSpace(sc.StorageType)) {
|
||||
case "cos":
|
||||
return 16
|
||||
case "obs", "minio", "azure":
|
||||
return 32
|
||||
case "oss", "gcs":
|
||||
return 64
|
||||
case "s3":
|
||||
return 96
|
||||
default:
|
||||
return defaultCompactorDeleteWorkers
|
||||
}
|
||||
}
|
||||
|
||||
func (d *LokiDeployer) buildStorageConfigBlock() string {
|
||||
if d.deployment.StorageConfig == nil {
|
||||
return ""
|
||||
|
||||
Reference in new issue
Block a user