feat: K8s 部署清单、Token 接入加固与日志/设置页优化

- kubernetes/: 30Gi PVC、单副本 Recreate、Secret/Service/NodePort/Ingress 清单与部署文档
- 数据安全: kubeconfig/token 统一加密存储,启动迁移历史明文,DB 0600
- Token 接入: 命名空间级最小权限提示、长期 Token、自签证书 TLS 兼容
- 部署: 命名空间级 Token 下跳过 Namespace patch/枚举,节点信息容错
- 日志页: namespace → app → pod 选择顺序与作用域收窄
- 设置页: 拆分为通用/告警/LDAP/镜像源四个 tab
- 弹框: 统一 max-h 滚动与长命令换行,修复内容溢出
This commit is contained in:
logan committed 2026-10-25 23:44:07 +08:00
1 parent 2d73661dd1
commit 9f7c522157
50 files changed
+1346 -149

No files matched your search

+87 -28
View File
@@ -3,6 +3,7 @@ package services
// 镜像仓库源 — 全局设置(参照 kuboard 的国内/海外镜像选择):
// overseas = docker.io 官方源;cn = daocloud 国内镜像;custom = 用户自填 registry 前缀。
// 影响平台拉取的全部镜像:Loki / Grafana / Promtail / Fluent Bit。
// 每个组件可单独配置仓库与 tag(Loki/Grafana 的 tag 留空则跟随部署版本)。
import (
"encoding/json"
"fmt"
@@ -20,15 +21,23 @@ const (
daocloudPrefix = "docker.m.daocloud.io"
)
// ComponentImage 单个组件的镜像配置
type ComponentImage struct {
Repository string `json:"repository"` // 如 grafana/loki
Tag string `json:"tag"` // 留空表示跟随部署版本 / 使用默认
}
// ImageRegistryConfig 镜像源配置
type ImageRegistryConfig struct {
Mode string `json:"mode"` // overseas | cn | custom
CustomHost string `json:"customHost"` // custom 模式下的仓库前缀,如 swr.cn-east-2.myhuaweicloud.com/xxx
Mode string `json:"mode"` // overseas | cn | custom
CustomHost string `json:"customHost"` // custom 模式下的仓库前缀
Images map[string]ComponentImage `json:"images"` // loki/grafana/promtail/fluentbit
}
type ImageRegistryPublic struct {
Mode string `json:"mode"`
CustomHost string `json:"customHost"`
Mode string `json:"mode"`
CustomHost string `json:"customHost"`
Images map[string]ComponentImage `json:"images"`
// 示例预览(前端展示生效镜像)
SampleLoki string `json:"sampleLoki"`
SampleGrafana string `json:"sampleGrafana"`
@@ -36,31 +45,55 @@ type ImageRegistryPublic struct {
SampleFluentBit string `json:"sampleFluentBit"`
}
var defaultComponentImages = map[string]ComponentImage{
"loki": {Repository: "grafana/loki", Tag: ""}, // 跟随部署版本
"grafana": {Repository: "grafana/grafana", Tag: ""}, // 跟随部署版本
"promtail": {Repository: "grafana/promtail", Tag: "3.4.0"},
"fluentbit": {Repository: "fluent/fluent-bit", Tag: "5.1.5"},
}
func (c *ImageRegistryConfig) fillDefaults() {
if c.Images == nil {
c.Images = map[string]ComponentImage{}
}
for name, def := range defaultComponentImages {
img, ok := c.Images[name]
if !ok || (img.Repository == "" && img.Tag == "") {
c.Images[name] = def
continue
}
if img.Repository == "" {
img.Repository = def.Repository
}
c.Images[name] = img
}
}
func GetImageRegistry() *ImageRegistryConfig {
db := repository.GetDB()
if db == nil {
return &ImageRegistryConfig{Mode: RegistryOverseas}
}
db.RLock()
var raw string
for i := range db.Settings {
if db.Settings[i].Key == imageRegistrySettingKey {
raw = db.Settings[i].Value
break
}
}
db.RUnlock()
cfg := &ImageRegistryConfig{Mode: RegistryOverseas}
if raw != "" {
_ = json.Unmarshal([]byte(raw), cfg)
if db != nil {
db.RLock()
var raw string
for i := range db.Settings {
if db.Settings[i].Key == imageRegistrySettingKey {
raw = db.Settings[i].Value
break
}
}
db.RUnlock()
if raw != "" {
_ = json.Unmarshal([]byte(raw), cfg)
}
}
if cfg.Mode == "" {
cfg.Mode = RegistryOverseas
}
cfg.fillDefaults()
return cfg
}
func SaveImageRegistry(mode, customHost string) error {
func SaveImageRegistry(mode, customHost string, images map[string]ComponentImage) error {
if mode != RegistryOverseas && mode != RegistryCN && mode != RegistryCustom {
return fmt.Errorf("无效的镜像源模式")
}
@@ -70,7 +103,15 @@ func SaveImageRegistry(mode, customHost string) error {
return fmt.Errorf("自定义镜像仓库地址无效(需含域名,如 swr.cn-east-2.myhuaweicloud.com/your-ns)")
}
}
data, _ := json.Marshal(&ImageRegistryConfig{Mode: mode, CustomHost: customHost})
cfg := &ImageRegistryConfig{Mode: mode, CustomHost: customHost, Images: images}
cfg.fillDefaults()
// 清理空白输入
clean := map[string]ComponentImage{}
for name, img := range cfg.Images {
clean[name] = ComponentImage{Repository: strings.TrimSpace(img.Repository), Tag: strings.TrimSpace(img.Tag)}
}
cfg.Images = clean
data, _ := json.Marshal(cfg)
db := repository.GetDB()
newID := db.NextID("settings")
db.Lock()
@@ -97,7 +138,6 @@ func ResolveImage(official string) string {
return daocloudPrefix + "/" + strings.TrimPrefix(official, "docker.io/")
}
if !strings.Contains(strings.SplitN(official, "/", 2)[0], ".") {
// 无仓库前缀的官方镜像(grafana/loki:tag)
return daocloudPrefix + "/" + official
}
return official
@@ -110,22 +150,41 @@ func ResolveImage(official string) string {
}
return official
default:
if strings.HasPrefix(official, "docker.io/") {
return official // 官方模式保留全限定名
}
return official
}
}
// ResolveImageFor 按组件配置解析镜像;组件 tag 为空时使用 fallbackTag(通常是部署版本)。
func ResolveImageFor(component, fallbackRepo, fallbackTag string) string {
cfg := GetImageRegistry()
img, ok := cfg.Images[component]
repo := fallbackRepo
tag := fallbackTag
if ok {
if strings.TrimSpace(img.Repository) != "" {
repo = strings.TrimSpace(img.Repository)
}
if strings.TrimSpace(img.Tag) != "" {
tag = strings.TrimSpace(img.Tag)
}
}
official := repo
if !strings.Contains(repo, ":") && tag != "" {
official = repo + ":" + tag
}
return ResolveImage(official)
}
// ImageRegistryPublicConfig 对外输出(含示例预览)
func ImageRegistryPublicConfig() *ImageRegistryPublic {
cfg := GetImageRegistry()
return &ImageRegistryPublic{
Mode: cfg.Mode,
CustomHost: cfg.CustomHost,
SampleLoki: ResolveImage("docker.io/grafana/loki:3.4.0"),
SampleGrafana: ResolveImage("docker.io/grafana/grafana:11.3.0"),
SamplePromtail: ResolveImage("docker.io/grafana/promtail:3.4.0"),
SampleFluentBit: ResolveImage("docker.io/fluent/fluent-bit:5.1.5"),
Images: cfg.Images,
SampleLoki: ResolveImageFor("loki", "grafana/loki", "3.4.0"),
SampleGrafana: ResolveImageFor("grafana", "grafana/grafana", "11.3.0"),
SamplePromtail: ResolveImageFor("promtail", "grafana/promtail", "3.4.0"),
SampleFluentBit: ResolveImageFor("fluentbit", "fluent/fluent-bit", "5.1.5"),
}
}