feat: 路由改名/kubectl预装/导出YAML精简/Service标签页优化/Alpine镜像源换清华
- 路由 /deploy/credentials → /deploy/configureTools - kubectl 改为预装(Dockerfile) + 种子数据 preinstall - 导出YAML精简: Service/Ingress/Deployment 全面清理运行时字段 - DeploymentEditService 只显示匹配 selector 的关联 Service - Alpine 镜像源 mirrors.aliyun.com → mirrors.tuna.tsinghua.edu.cn
This commit is contained in:
1 parent
dd7cb6895e
commit
451f65f9c8
9 files changed
+109
-29
No files matched your search
+8
-3
@@ -17,7 +17,7 @@ FROM golang:1.24-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# 使用国内 Alpine 镜像源加速 // Logan.Li
|
||||
RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories
|
||||
RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.tuna.tsinghua.edu.cn|g' /etc/apk/repositories
|
||||
RUN apk add --no-cache git ca-certificates tzdata
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
@@ -74,15 +74,20 @@ RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
FROM alpine:3.20
|
||||
|
||||
# 使用国内 Alpine 镜像源加速 // Logan.Li
|
||||
RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories
|
||||
RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.tuna.tsinghua.edu.cn|g' /etc/apk/repositories
|
||||
|
||||
# 安装运行时依赖(核心最小集,重型工具改为懒加载)// Logan.Li
|
||||
# bash=kubectl交互终端, curl=健康检查, git=流水线代码拉取, docker-cli=镜像构建推送
|
||||
# kubectl/maven/nodejs/helm → 见「发布配置→工具配置」Tab,首次使用自动下载
|
||||
# kubectl=预装(~50MB,K8s交互终端必需),maven/nodejs/helm → 工具配置Tab懒加载
|
||||
# Pod文件浏览/exec 通过 WebSocket channel 协议直连 K8s API,无需 kubectl
|
||||
RUN --mount=type=cache,target=/var/cache/apk \
|
||||
apk add ca-certificates tzdata bash curl git docker-cli docker-cli-buildx
|
||||
|
||||
# kubectl 预装(~50MB,国内网络从 dl.k8s.io 下载约10s)// Logan.Li
|
||||
ARG KUBECTL_VERSION=v1.32.0
|
||||
RUN curl -sLo /usr/local/bin/kubectl https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \
|
||||
chmod +x /usr/local/bin/kubectl
|
||||
|
||||
# npm 淘宝镜像加速(node 懒加载后生效)
|
||||
RUN npm config set registry https://registry.npmmirror.com 2>/dev/null || true
|
||||
# Maven 阿里云镜像加速(maven 懒加载后生效)
|
||||
|
||||
@@ -269,6 +269,10 @@ func cleanResourceYAML(obj map[string]interface{}) {
|
||||
delete(meta, "annotations")
|
||||
}
|
||||
}
|
||||
// 移除空的 labels
|
||||
if labels, ok := meta["labels"].(map[string]interface{}); ok && len(labels) == 0 {
|
||||
delete(meta, "labels")
|
||||
}
|
||||
}
|
||||
|
||||
// 删除 status
|
||||
@@ -276,11 +280,21 @@ func cleanResourceYAML(obj map[string]interface{}) {
|
||||
|
||||
// 清理 spec 中的运行时字段
|
||||
if spec, ok := obj["spec"].(map[string]interface{}); ok {
|
||||
// Service: 移除动态分配的 clusterIP 和 nodePorts
|
||||
if obj["kind"] == "Service" {
|
||||
kind, _ := obj["kind"].(string)
|
||||
|
||||
// Service: 移除动态分配字段和默认值
|
||||
if kind == "Service" {
|
||||
delete(spec, "clusterIP")
|
||||
delete(spec, "clusterIPs")
|
||||
// nodePorts 在 ports 数组内 — 仅移除 NodePort 类型的 nodePort 字段
|
||||
delete(spec, "internalTrafficPolicy")
|
||||
delete(spec, "ipFamilies")
|
||||
delete(spec, "ipFamilyPolicy")
|
||||
// sessionAffinity 默认 "None" → 移除
|
||||
if sa, ok := spec["sessionAffinity"].(string); ok && sa == "None" {
|
||||
delete(spec, "sessionAffinity")
|
||||
}
|
||||
delete(spec, "allocateLoadBalancerNodePorts")
|
||||
// 移除 ports 内的 nodePort(仅 NodePort/LoadBalancer 类型)
|
||||
if ports, ok := spec["ports"].([]interface{}); ok {
|
||||
for _, p := range ports {
|
||||
if pm, ok := p.(map[string]interface{}); ok {
|
||||
@@ -290,8 +304,9 @@ func cleanResourceYAML(obj map[string]interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// Deployment: 清理 template.metadata 和 template.spec 中的运行时字段
|
||||
if obj["kind"] == "Deployment" {
|
||||
// Deployment / StatefulSet / DaemonSet: 清理运行时和默认值
|
||||
if kind == "Deployment" || kind == "StatefulSet" || kind == "DaemonSet" {
|
||||
// 清理 template
|
||||
if template, ok := spec["template"].(map[string]interface{}); ok {
|
||||
if tMeta, ok := template["metadata"].(map[string]interface{}); ok {
|
||||
delete(tMeta, "creationTimestamp")
|
||||
@@ -304,8 +319,54 @@ func cleanResourceYAML(obj map[string]interface{}) {
|
||||
}
|
||||
if tSpec, ok := template["spec"].(map[string]interface{}); ok {
|
||||
delete(tSpec, "nodeName")
|
||||
delete(tSpec, "serviceAccountName") // 移除 default 值
|
||||
// 清理容器内的 terminationMessagePath/Policy 默认值
|
||||
if containers, ok := tSpec["containers"].([]interface{}); ok {
|
||||
for _, c := range containers {
|
||||
if cm, ok := c.(map[string]interface{}); ok {
|
||||
if tmp, ok := cm["terminationMessagePath"].(string); ok && tmp == "/dev/termination-log" {
|
||||
delete(cm, "terminationMessagePath")
|
||||
}
|
||||
if tmp, ok := cm["terminationMessagePolicy"].(string); ok && tmp == "File" {
|
||||
delete(cm, "terminationMessagePolicy")
|
||||
}
|
||||
// 清理默认 imagePullPolicy
|
||||
if ip, ok := cm["imagePullPolicy"].(string); ok && ip == "Always" {
|
||||
delete(cm, "imagePullPolicy")
|
||||
}
|
||||
// 清理空 resources
|
||||
if res, ok := cm["resources"].(map[string]interface{}); ok && len(res) == 0 {
|
||||
delete(cm, "resources")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 清理 dnsPolicy 默认值
|
||||
if dp, ok := tSpec["dnsPolicy"].(string); ok && dp == "ClusterFirst" {
|
||||
delete(tSpec, "dnsPolicy")
|
||||
}
|
||||
if rp, ok := tSpec["restartPolicy"].(string); ok && rp == "Always" {
|
||||
delete(tSpec, "restartPolicy")
|
||||
}
|
||||
if tp, ok := tSpec["terminationGracePeriodSeconds"].(float64); ok && tp == 30 {
|
||||
delete(tSpec, "terminationGracePeriodSeconds")
|
||||
}
|
||||
}
|
||||
}
|
||||
// 清理默认值
|
||||
if rhl, ok := spec["revisionHistoryLimit"].(float64); ok && rhl == 10 {
|
||||
delete(spec, "revisionHistoryLimit")
|
||||
}
|
||||
if pds, ok := spec["progressDeadlineSeconds"].(float64); ok && pds == 600 {
|
||||
delete(spec, "progressDeadlineSeconds")
|
||||
}
|
||||
}
|
||||
|
||||
// Ingress: 清理默认值
|
||||
if kind == "Ingress" {
|
||||
if ic, ok := spec["ingressClassName"].(string); ok && ic == "" {
|
||||
delete(spec, "ingressClassName")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1605,13 +1605,14 @@ func (h *KubernetesHandler) listDeploymentsWithNS(c *gin.Context, ns string) {
|
||||
deps, err := client.ListDeployments()
|
||||
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
|
||||
type DepSummary struct {
|
||||
Namespace string `json:"namespace"`
|
||||
Name string `json:"name"`
|
||||
Replicas int `json:"replicas"`
|
||||
AvailableReplicas int `json:"available_replicas"`
|
||||
ReadyReplicas int `json:"ready_replicas"`
|
||||
Image string `json:"image"`
|
||||
Paused bool `json:"paused"`
|
||||
Namespace string `json:"namespace"`
|
||||
Name string `json:"name"`
|
||||
Replicas int `json:"replicas"`
|
||||
AvailableReplicas int `json:"available_replicas"`
|
||||
ReadyReplicas int `json:"ready_replicas"`
|
||||
Image string `json:"image"`
|
||||
Paused bool `json:"paused"`
|
||||
Selector map[string]string `json:"selector,omitempty"` // matchLabels — 前端 Service Tab 关联用
|
||||
}
|
||||
result := []DepSummary{}
|
||||
for _, d := range deps.Items {
|
||||
@@ -1625,6 +1626,7 @@ func (h *KubernetesHandler) listDeploymentsWithNS(c *gin.Context, ns string) {
|
||||
ReadyReplicas: d.Status.ReadyReplicas,
|
||||
Image: image,
|
||||
Paused: d.Spec.Paused,
|
||||
Selector: func() map[string]string { if d.Spec.Selector != nil { return d.Spec.Selector.MatchLabels }; return nil }(),
|
||||
})
|
||||
}
|
||||
c.JSON(200, models.Response{Code: 200, Data: result})
|
||||
|
||||
@@ -66,9 +66,9 @@ func PredefinedTools() []DeployTool {
|
||||
{
|
||||
Name: "kubectl",
|
||||
DisplayName: "Kubectl",
|
||||
Description: "Kubernetes 命令行工具,用于 K8s 集群交互",
|
||||
Description: "Kubernetes 命令行工具,用于 K8s 集群交互(已预装在镜像中)",
|
||||
Category: "k8s",
|
||||
InstallMethod: ToolLazy,
|
||||
InstallMethod: ToolPreinstall,
|
||||
BinaryName: "kubectl",
|
||||
InstallPath: "/usr/local/bin/kubectl",
|
||||
CheckCommand: "kubectl version --client --short 2>/dev/null || kubectl version --client 2>/dev/null",
|
||||
|
||||
@@ -290,10 +290,16 @@ type DeploymentItem struct {
|
||||
|
||||
type DeploymentSpec struct {
|
||||
Replicas int `json:"replicas"`
|
||||
Selector *LabelSelector `json:"selector,omitempty"` // matchLabels — 前端 Service 关联用
|
||||
Template DeploymentTemplate `json:"template"`
|
||||
Paused bool `json:"paused"`
|
||||
}
|
||||
|
||||
// LabelSelector K8s 标签选择器
|
||||
type LabelSelector struct {
|
||||
MatchLabels map[string]string `json:"matchLabels,omitempty"`
|
||||
}
|
||||
|
||||
type DeploymentTemplate struct {
|
||||
Spec PodSpec `json:"spec"`
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user