Files
LokiStack/backend/services/loki_manifest.go
T
logan 9f7c522157 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 滚动与长命令换行,修复内容溢出
2026-10-25 23:44:07 +08:00

244 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// LokiDeployer — k8s-yaml 模式 manifest 生成(StatefulSet/PVC/ConfigMap/Service)。
package services
import (
"crypto/sha256"
"encoding/base64"
"fmt"
)
func (d *LokiDeployer) generateManifest(ns string) string {
version := d.effectiveVersion()
image := ResolveImageFor("loki", "grafana/loki", version)
replicas := d.deployment.Replicas
if replicas < 1 {
replicas = 1
}
storageSize := d.deployment.StorageSize
if storageSize == "" {
storageSize = "20Gi"
}
cpu := d.deployment.ResourcesCPU
mem := d.deployment.ResourcesMem
if cpu == "" {
cpu = "1000m"
}
if mem == "" {
mem = "1Gi"
}
configData := d.generateLokiConfig()
secretManifest := ""
configExpandArg := ""
storageEnvBlock := ""
if sc := d.deployment.StorageConfig; sc != nil {
switch sc.StorageType {
case "s3", "oss", "minio", "azure":
secretManifest = fmt.Sprintf(`---
apiVersion: v1
kind: Secret
metadata:
name: loki-storage-credentials
namespace: %s
type: Opaque
data:
accessKey: %s
secretKey: %s`, ns,
base64.StdEncoding.EncodeToString([]byte(sc.AccessKey)),
base64.StdEncoding.EncodeToString([]byte(sc.SecretKey)))
configExpandArg = "\n - -config.expand-env=true"
storageEnvBlock = `
env:
- name: LOKI_STORAGE_ACCESS_KEY
valueFrom:
secretKeyRef:
name: loki-storage-credentials
key: accessKey
- name: LOKI_STORAGE_SECRET_KEY
valueFrom:
secretKeyRef:
name: loki-storage-credentials
key: secretKey`
}
}
// ConfigMap/Secret 更新本身不会重建 Pod。把内容摘要写入 Pod 模板以触发滚动更新。
configHash := sha256.Sum256([]byte(configData + "\n" + secretManifest))
manifest := fmt.Sprintf(`apiVersion: v1
kind: Namespace
metadata:
name: %s
---
apiVersion: v1
kind: ConfigMap
metadata:
name: loki-config
namespace: %s
data:
loki.yaml: |
%s
%s
---
apiVersion: v1
kind: Service
metadata:
name: loki
namespace: %s
labels:
app: loki
spec:
type: ClusterIP
ports:
- name: http
port: 3100
targetPort: 3100
protocol: TCP
- name: grpc
port: 9095
targetPort: 9095
protocol: TCP
selector:
app: loki
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: loki-data
namespace: %s
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: %s
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: loki
namespace: %s
labels:
app: loki
spec:
serviceName: loki
replicas: %d
selector:
matchLabels:
app: loki
template:
metadata:
labels:
app: loki
annotations:
checksum/loki-config: "%x"
spec:
securityContext:
runAsUser: 0
runAsGroup: 0
fsGroup: 0
containers:
- name: loki
image: %s
imagePullPolicy: IfNotPresent
args:
- -config.file=/etc/loki/loki.yaml%s%s
ports:
- name: http
containerPort: 3100
protocol: TCP
- name: grpc
containerPort: 9095
protocol: TCP
resources:
limits:
cpu: "%s"
memory: "%s"
requests:
cpu: "500m"
memory: "512Mi"
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop:
- ALL
livenessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 30
volumeMounts:
- name: config
mountPath: /etc/loki
readOnly: true
- name: data
mountPath: /var/lib/loki
- name: wal
mountPath: /var/lib/loki/wal
volumes:
- name: config
configMap:
name: loki-config
- name: data
persistentVolumeClaim:
claimName: loki-data
- name: wal
emptyDir: {}
`, ns, ns, indentYAML(configData, 4), secretManifest, ns, ns, storageSize, ns, replicas, configHash, image, configExpandArg, storageEnvBlock, cpu, mem)
// 多副本:追加 Headless Service(clusterIP: None + selector app:loki),
// 使 memberlist 的 join_members (loki-headless.<ns>.svc.cluster.local) 能解析到所有 Pod IP。
if replicas >= 2 {
manifest += fmt.Sprintf(`
---
apiVersion: v1
kind: Service
metadata:
name: loki-headless
namespace: %s
labels:
app: loki
spec:
clusterIP: None
ports:
- name: http
port: 3100
targetPort: 3100
protocol: TCP
- name: grpc
port: 9095
targetPort: 9095
protocol: TCP
- name: memberlist
port: 7946
targetPort: 7946
protocol: TCP
selector:
app: loki
`, ns)
}
return manifest
}
// ==================== Loki 本地配置生成 (text/template) ====================