Skip to main content
Glama
main.go12.3 kB
package main import ( "embed" "fmt" "io/fs" "net/http" "os" "github.com/fatih/color" "github.com/gin-contrib/cors" "github.com/gin-contrib/gzip" "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" "github.com/weibaohui/k8m/pkg/cb" "github.com/weibaohui/k8m/pkg/comm/utils" "github.com/weibaohui/k8m/pkg/controller/admin/cluster" "github.com/weibaohui/k8m/pkg/controller/admin/config" "github.com/weibaohui/k8m/pkg/controller/admin/inspection" "github.com/weibaohui/k8m/pkg/controller/admin/mcp" "github.com/weibaohui/k8m/pkg/controller/admin/menu" "github.com/weibaohui/k8m/pkg/controller/admin/user" "github.com/weibaohui/k8m/pkg/controller/chat" "github.com/weibaohui/k8m/pkg/controller/cluster_status" "github.com/weibaohui/k8m/pkg/controller/cm" "github.com/weibaohui/k8m/pkg/controller/cronjob" "github.com/weibaohui/k8m/pkg/controller/deploy" "github.com/weibaohui/k8m/pkg/controller/doc" "github.com/weibaohui/k8m/pkg/controller/ds" "github.com/weibaohui/k8m/pkg/controller/dynamic" "github.com/weibaohui/k8m/pkg/controller/gatewayapi" "github.com/weibaohui/k8m/pkg/controller/helm" "github.com/weibaohui/k8m/pkg/controller/ingressclass" "github.com/weibaohui/k8m/pkg/controller/k8sgpt" "github.com/weibaohui/k8m/pkg/controller/log" "github.com/weibaohui/k8m/pkg/controller/login" "github.com/weibaohui/k8m/pkg/controller/node" "github.com/weibaohui/k8m/pkg/controller/ns" "github.com/weibaohui/k8m/pkg/controller/param" "github.com/weibaohui/k8m/pkg/controller/pod" "github.com/weibaohui/k8m/pkg/controller/rs" "github.com/weibaohui/k8m/pkg/controller/sso" "github.com/weibaohui/k8m/pkg/controller/storageclass" "github.com/weibaohui/k8m/pkg/controller/sts" "github.com/weibaohui/k8m/pkg/controller/svc" "github.com/weibaohui/k8m/pkg/controller/template" "github.com/weibaohui/k8m/pkg/controller/user/apikey" "github.com/weibaohui/k8m/pkg/controller/user/mcpkey" "github.com/weibaohui/k8m/pkg/controller/user/profile" "github.com/weibaohui/k8m/pkg/flag" helm2 "github.com/weibaohui/k8m/pkg/helm" "github.com/weibaohui/k8m/pkg/lua" "github.com/weibaohui/k8m/pkg/middleware" _ "github.com/weibaohui/k8m/pkg/models" // 注册模型 "github.com/weibaohui/k8m/pkg/service" _ "github.com/weibaohui/k8m/swagger" "github.com/weibaohui/kom/callbacks" "k8s.io/klog/v2" ) //go:embed ui/dist/* var embeddedFiles embed.FS var Version string var GitCommit string var GitTag string var GitRepo string var InnerModel = "Qwen/Qwen2.5-7B-Instruct" var InnerApiKey string var InnerApiUrl string var BuildDate string // Init 完成服务的初始化,包括加载配置、设置版本信息、初始化 AI 服务、注册集群及其回调,并启动资源监控。 func Init() { // 初始化配置 cfg := flag.Init() // 从数据库中更新配置 err := service.ConfigService().UpdateFlagFromDBConfig() if err != nil { klog.Errorf("加载数据库内配置信息失败 error: %v", err) } cfg.Version = Version cfg.GitCommit = GitCommit cfg.GitTag = GitTag cfg.GitRepo = GitRepo cfg.BuildDate = BuildDate cfg.ShowConfigInfo() // 打印版本和 Git commit 信息 klog.V(2).Infof("版本: %s\n", Version) klog.V(2).Infof("Git Commit: %s\n", GitCommit) if !cfg.Debug { gin.SetMode(gin.ReleaseMode) } // 初始化ChatService service.AIService().SetVars(InnerApiKey, InnerApiUrl, InnerModel) go func() { // 初始化kom // 先注册回调,后面集群连接后,需要执行回调 callbacks.RegisterInit() // 先把自定义钩子注册登记 service.ClusterService().SetRegisterCallbackFunc(cb.RegisterDefaultCallbacks) if cfg.InCluster { klog.V(6).Infof("启用InCluster模式,自动注册纳管宿主集群") // 注册InCluster集群 service.ClusterService().RegisterInCluster() } else { klog.V(6).Infof("未启用InCluster模式,忽略宿主集群纳管") } // 再注册其他集群 service.ClusterService().ScanClustersInDB() service.ClusterService().ScanClustersInDir(cfg.KubeConfig) service.ClusterService().RegisterClustersByPath(cfg.KubeConfig) // 启动时是否自动连接集群 if cfg.ConnectCluster { // 调用 AllClusters 方法获取所有集群 clusters := service.ClusterService().AllClusters() // 遍历集群,进行连接 for _, clusterInfo := range clusters { klog.Infof("连接集群:%s", clusterInfo.ClusterID) service.ClusterService().Connect(clusterInfo.ClusterID) } } // 打印集群连接信息 klog.Infof("处理%d个集群,其中%d个集群已连接", len(service.ClusterService().AllClusters()), len(service.ClusterService().ConnectedClusters())) }() // 启动watch go func() { service.McpService().Init() service.ClusterService().DelayStartFunc(func() { service.PodService().Watch() service.NodeService().Watch() service.PVCService().Watch() service.PVService().Watch() service.IngressService().Watch() service.McpService().Start() // 启动集群巡检 lua.InitClusterInspection() // 启动helm 更新repo定时任务 helm2.StartUpdateHelmRepoInBackground() }) }() } // main 启动并运行 Kubernetes 管理服务,完成配置初始化、集群注册与资源监控,配置 Gin 路由和中间件,挂载前端静态资源,并提供认证、集群与资源管理、AI 聊天、用户与平台管理等丰富的 HTTP API 接口。 func main() { Init() r := gin.Default() cfg := flag.Init() // 开启Recovery中间件 if !cfg.Debug { r.Use(middleware.CustomRecovery()) } if cfg.Debug { // Debug 模式 注册 pprof 路由 pprof.Register(r) } r.Use(cors.Default()) r.Use(gzip.Gzip(gzip.BestCompression)) r.Use(middleware.SetCacheHeaders()) r.Use(middleware.AuthMiddleware()) r.Use(middleware.EnsureSelectedClusterMiddleware()) r.MaxMultipartMemory = 100 << 20 // 100 MiB // 挂载子目录 pagesFS, _ := fs.Sub(embeddedFiles, "ui/dist/pages") r.StaticFS("/public/pages", http.FS(pagesFS)) assetsFS, _ := fs.Sub(embeddedFiles, "ui/dist/assets") r.StaticFS("/assets", http.FS(assetsFS)) monacoFS, _ := fs.Sub(embeddedFiles, "ui/dist/monacoeditorwork") r.StaticFS("/monacoeditorwork", http.FS(monacoFS)) r.GET("/favicon.ico", func(c *gin.Context) { favicon, _ := embeddedFiles.ReadFile("ui/dist/favicon.ico") c.Data(http.StatusOK, "image/x-icon", favicon) }) // MCP Server sseServer := GetMcpSSEServer("/mcp/k8m/") r.GET("/mcp/k8m/sse", adapt(sseServer.SSEHandler)) r.POST("/mcp/k8m/sse", adapt(sseServer.SSEHandler)) r.POST("/mcp/k8m/message", adapt(sseServer.MessageHandler)) r.GET("/mcp/k8m/:key/sse", adapt(sseServer.SSEHandler)) r.POST("/mcp/k8m/:key/sse", adapt(sseServer.SSEHandler)) r.POST("/mcp/k8m/:key/message", adapt(sseServer.MessageHandler)) // @title k8m API // @version 1.0 // @securityDefinitions.apikey BearerAuth // @in header // @name Authorization // @description 请输入以 `Bearer ` 开头的 Token,例:Bearer xxxxxxxx。未列出接口请参考前端调用方法。Token在个人中心-API密钥菜单下申请。 r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) // 直接返回 index.html r.GET("/", func(c *gin.Context) { index, err := embeddedFiles.ReadFile("ui/dist/index.html") // 这里路径必须匹配 if err != nil { c.String(http.StatusInternalServerError, "Internal Server Error") return } c.Data(http.StatusOK, "text/html; charset=utf-8", index) }) r.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) r.GET("/healthz", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok"}) }) auth := r.Group("/auth") { login.RegisterLoginRoutes(auth) sso.RegisterAuthRoutes(auth) } // 公共参数 params := r.Group("/params", middleware.AuthMiddleware()) { param.RegisterParamRoutes(params) } ai := r.Group("/ai", middleware.AuthMiddleware()) { chat.RegisterChatRoutes(ai) } api := r.Group("/k8s/cluster/:cluster", middleware.AuthMiddleware()) { // cluster cluster_status.RegisterClusterRoutes(api) // CRD status dynamic.RegisterCRDRoutes(api) // CRD action dynamic.RegisterActionRoutes(api) dynamic.RegisterMetadataRoutes(api) // Container 信息 dynamic.RegisterContainerRoutes(api) // 节点亲和性 dynamic.RegisterNodeAffinityRoutes(api) // Pod亲和性 dynamic.RegisterPodAffinityRoutes(api) // Pod反亲和性 dynamic.RegisterPodAntiAffinityRoutes(api) // 容忍度 dynamic.RegisterTolerationRoutes(api) // Pod关联资源 dynamic.RegisterPodLinkRoutes(api) // k8s pod pod.RegisterLabelRoutes(api) pod.RegisterLogRoutes(api) pod.RegisterXtermRoutes(api) // pod 文件浏览上传下载 pod.RegisterPodFileRoutes(api) // Pod 资源使用情况 pod.RegisterResourceRoutes(api) // Pod 端口转发 pod.RegisterPortRoutes(api) // k8s deploy deploy.RegisterActionRoutes(api) // p8s svc svc.RegisterActionRoutes(api) // k8s node node.RegisterActionRoutes(api) // 资源情况 node.RegisterResourceRoutes(api) // 节点污点 node.RegisterTaintRoutes(api) // label等基础信息 node.RegisterMetadataRoutes(api) node.RegisterShellRoutes(api) // k8s ns ns.RegisterRoutes(api) // yaml dynamic.RegisterYamlRoutes(api) // k8s sts sts.RegisterRoutes(api) // k8s ds ds.RegisterRoutes(api) // k8s rs rs.RegisterRoutes(api) // k8s configmap cm.RegisterRoutes(api) // k8s cronjob cronjob.RegisterRoutes(api) // k8s storage_class storageclass.RegisterRoutes(api) // k8s ingress_class ingressclass.RegisterRoutes(api) // k8s gateway_class gatewayapi.RegisterRoutes(api) // doc doc.RegisterRoutes(api) k8sgpt.RegisterRoutes(api) // helm release helm.RegisterHelmReleaseRoutes(api) } mgm := r.Group("/mgm", middleware.AuthMiddleware()) { template.RegisterTemplateRoutes(mgm) // user profile 用户自助操作 profile.RegisterProfileRoutes(mgm) // API密钥管理 apikey.RegisterAPIKeysRoutes(mgm) // MCP密钥管理 mcpkey.RegisterMCPKeysRoutes(mgm) // log log.RegisterLogRoutes(mgm) // 集群连接 cluster.RegisterUserClusterRoutes(mgm) // helm chart helm.RegisterHelmChartRoutes(mgm) } admin := r.Group("/admin", middleware.PlatformAuthMiddleware()) { // condition config.RegisterConditionRoutes(admin) // sso config.RegisterSSOConfigRoutes(admin) // ldap config.RegisterLdapConfigRoutes(admin) // 平台参数配置 config.RegisterConfigRoutes(admin) // 大模型列表管理 config.RegisterAIModelConfigRoutes(admin) // 集群巡检定时任务 inspection.RegisterAdminScheduleRoutes(admin) // 集群巡检记录 inspection.RegisterAdminRecordRoutes(admin) // 集群巡检脚本lua脚本管理 inspection.RegisterAdminLuaScriptRoutes(admin) // 集群巡检webhook管理 inspection.RegisterAdminWebhookRoutes(admin) // MCP配置 mcp.RegisterMCPServerRoutes(admin) mcp.RegisterMCPToolRoutes(admin) // 集群授权相关 user.RegisterClusterPermissionRoutes(admin) // 用户管理相关 user.RegisterAdminUserRoutes(admin) // 用户组管理相关 user.RegisterAdminUserGroupRoutes(admin) // 管理集群、纳管\解除纳管\扫描 cluster.RegisterAdminClusterRoutes(admin) // helm Repo 操作 helm.RegisterHelmRepoRoutes(admin) // 菜单自定义 menu.RegisterAdminMenuRoutes(admin) } showBootInfo(Version, cfg.Port) err := r.Run(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) if err != nil { klog.Fatalf("Error %v", err) } } func showBootInfo(version string, port int) { // 获取本机所有 IP 地址 ips, err := utils.GetLocalIPs() if err != nil { klog.Fatalf("获取本机 IP 失败: %v", err) os.Exit(1) } // 打印 Vite 风格的启动信息 color.Green("k8m %s 启动成功", version) fmt.Printf("%s ", color.GreenString("➜")) fmt.Printf("%s ", color.New(color.Bold).Sprint("Local:")) fmt.Printf("%s\n", color.MagentaString("http://localhost:%d/", port)) for _, ip := range ips { fmt.Printf("%s ", color.GreenString("➜")) fmt.Printf("%s ", color.New(color.Bold).Sprint("Network:")) fmt.Printf("%s\n", color.MagentaString("http://%s:%d/", ip, port)) } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/weibaohui/k8m'

If you have feedback or need assistance with the MCP directory API, please join our Discord server