kubernetes platform后端开发-项目初始
kubernetes platform后端开发-项目初始
一、项目介绍
项目简介:Kubernetes Platform 是一个基于 Go 语言开发的 Kubernetes 集群管理平台,利用 Kubernetes 官方提供的 client-go 库进行构建。该平台旨在简化 Kubernetes 集群的日常操作和管理工作,提供一个友好的用户界面,使得用户无需直接与 kubectl 或 Kubernetes API 交互,即可执行各种集群管理任务。
核心特征:
- 集群概览:提供集群的实时状态显示,包括节点、Pods、服务等关键信息。
- 资源管理:允许用户创建、更新、删除和查看各种 Kubernetes 资源,例如部署、服务、配置映射等。
- 日志查看:提供集群日志的检索和查看功能,帮助用户快速定位问题。
- 监控与警告:集成监控工具,展示集群性能指标,并在出现潜在问题时提供警告通知。
- 权限控制:支持 Kubernetes 的 RBAC,确保用户根据其角色访问和管理相应的资源。(未完成)
- 多集群支持:可以同时管理和切换多个 Kubernetes 集群,适用于跨区域或多云环境。
- 插件化架构:方便扩展新功能,用户可以根据需求定制和扩展平台。
技术栈:
- Go语言:使用 Go 语言进行开发,确保了代码的高性能和高并发处理能力。
- client-go:Kubernetes 官方的 Go 客户端库,用于与 Kubernetes API 服务器进行交互。
- 前端框架:Vue3、ElementUIPlus。
- 数据库:Mysql
- 容器化与编排:(如Docker和Kubernetes,用于部署和运行管理平台)
部署环境
- Golang3.6+
- Mysql8.0
mysql数据导入:db/create.sql
默认密码:admin/123456
二、项目目录
- apps:业务处理层
- config:加载配置文件
- db:初始化数据库的脚本
- docs:项目文档
- etc:项目需要的配置
- exception:异常处理
- ioc:使用ioc注册解决对象依赖问题
- middle:中间件
- response:响应统一处理
- router:后端路由
- test:单元测试
- utils:自实现类
三、ioc注册容器
ioc/iocStore.go
package ioc
import (
"fmt"
)
type IocContainer struct {
store map[string]IocObject
}
func (c *IocContainer) Init() error {
fmt.Println(c.store)
for _, obj := range c.store {
if err := obj.Init(); err != nil {
return err
}
}
return nil
}
func (c *IocContainer) Register(obj IocObject) {
fmt.Println(obj.Name())
c.store[obj.Name()] = obj
}
func (c *IocContainer) GetObj(name string) IocObject {
fmt.Println(c.store)
return c.store[name]
}
ioc/interface.go
package ioc
type IocObject interface {
Init() error
Name() string
}
ioc/controller.go
package ioc
func Controller() *IocContainer {
return controllerContainer
}
var controllerContainer = &IocContainer{
store: map[string]IocObject{},
}
ioc/api.go
package ioc
func ApiHandler() *IocContainer {
return ApiHandlerContainer
}
var ApiHandlerContainer = &IocContainer{
store: map[string]IocObject{},
}
四、异常处理
exception/exception.go
package exception
import (
"fmt"
"net/http"
)
//
// APIException
// @Description: 业务自定义异常
//
type APIException struct {
Code int `json:"code"`
Message string `json:"message"`
Data any `json:"data"`
HttpCode int `json:"http_code"`
}
/*
* Error
* @Description: 实现error接口
* @receiver e
* @return string
*/
func (e *APIException) Error() string {
return e.Message
}
func NewApiException(code int, format string, a ...any) *APIException {
return &APIException{
Code: code,
Message: fmt.Sprintf(format, a...),
HttpCode: http.StatusOK,
}
}
exception/business.go
package exception
/*
* NewJsonMarshalFailed
* @Description: Json反序列化失败异常,异常码500
* @param format
* @param a
* @return *APIException
*/
func NewJsonMarshalFailed(format string, a ...any) *APIException {
return NewApiException(600, format, a...)
}
/*
* NewUpdatePodsFailed
* @Description: 更新pod信息失败,异常码501
* @param format
* @param a
* @return *APIException
*/
func NewUpdatePodsFailed(format string, a ...any) *APIException {
return NewApiException(501, format, a...)
}
/*
* NewGetContainersFailed
* @Description: 获取容器信息失败,异常码502
* @param format
* @param a
* @return *APIException
*/
func NewGetContainersFailed(format string, a ...any) *APIException {
return NewApiException(502, format, a...)
}
/*
* NewGetPodLogsFailed
* @Description: 获取pod日志失败,异常码503
* @param format
* @param a
* @return *APIException
*/
func NewGetPodLogsFailed(format string, a ...any) *APIException {
return NewApiException(503, format, a...)
}
/*
* NewGetPodListFailed
* @Description: 获取pod列表失败,异常码504
* @param format
* @param a
* @return *APIException
*/
func NewGetPodListFailed(format string, a ...any) *APIException {
return NewApiException(504, format, a...)
}
/*
* NewGetPaginateFailed
* @Description: 获取分页数据失败,异常码505
* @param format
* @param a
* @return *APIException
*/
func NewGetPaginateFailed(format string, a ...any) *APIException {
return NewApiException(505, format, a...)
}
/*
* NewDescribePodFailed
* @Description: 获取pod详细信息失败,异常码506
* @param format
* @param a
* @return *APIException
*/
func NewDescribePodFailed(format string, a ...any) *APIException {
return NewApiException(506, format, a...)
}
/*
* NewDeletePodFailed
* @Description: 删除pod失败,异常码507
* @param format
* @param a
* @return *APIException
*/
func NewDeletePodFailed(format string, a ...any) *APIException {
return NewApiException(507, format, a...)
}
func NewGetNamespacePodsCountFailed(format string, a ...any) *APIException {
return NewApiException(508, format, a...)
}
func CreateDeploymentListFailed(format string, a ...any) *APIException {
return NewApiException(499, format, a...)
}
func GetDeploymentListFailed(format string, a ...any) *APIException {
return NewApiException(509, format, a...)
}
func DescribeDeploymentFailed(format string, a ...any) *APIException {
return NewApiException(510, format, a...)
}
func GetDeploymentScaleFailed(format string, a ...any) *APIException {
return NewApiException(511, format, a...)
}
func UpdateDeploymentScaleFailed(format string, a ...any) *APIException {
return NewApiException(512, format, a...)
}
func DeleteDeploymentFailed(format string, a ...any) *APIException {
return NewApiException(513, format, a...)
}
func UpdateDeploymentFailed(format string, a ...any) *APIException {
return NewApiException(514, format, a...)
}
func JsonUmarshalFailed(format string, a ...any) *APIException {
return NewApiException(515, format, a...)
}
func GetDaemonSetListFailed(format string, a ...any) *APIException {
return NewApiException(516, format, a...)
}
func DescribeDaemonSetFailed(format string, a ...any) *APIException {
return NewApiException(517, format, a...)
}
func DeleteDaemonSetFailed(format string, a ...any) *APIException {
return NewApiException(518, format, a...)
}
func UpdateDaemonSetFailed(format string, a ...any) *APIException {
return NewApiException(519, format, a...)
}
func CreateDaemonSetFailed(format string, a ...any) *APIException {
return NewApiException(520, format, a...)
}
func CreateStatefulSetFailed(format string, a ...any) *APIException {
return NewApiException(521, format, a...)
}
func GetStatefulSetListFailed(format string, a ...any) *APIException {
return NewApiException(522, format, a...)
}
func DescribeStatefulSetFailed(format string, a ...any) *APIException {
return NewApiException(523, format, a...)
}
func DeleteStatefulSetFailed(format string, a ...any) *APIException {
return NewApiException(524, format, a...)
}
func UpdateStatefulSetFailed(format string, a ...any) *APIException {
return NewApiException(525, format, a...)
}
func GetNodeListFailed(format string, a ...any) *APIException {
return NewApiException(526, format, a...)
}
func DescribeNodeListFailed(format string, a ...any) *APIException {
return NewApiException(527, format, a...)
}
func InvalidParameter(format string, a ...any) *APIException {
return NewApiException(528, format, a...)
}
func GetNamespaceFailed(format string, a ...any) *APIException {
return NewApiException(529, format, a...)
}
func DescribeNamespaceFailed(format string, a ...any) *APIException {
return NewApiException(530, format, a...)
}
func DeleteNamespaceFailed(format string, a ...any) *APIException {
return NewApiException(531, format, a...)
}
func CreateNamespaceFailed(format string, a ...any) *APIException {
return NewApiException(532, format, a...)
}
func CreatePVFailed(format string, a ...any) *APIException {
return NewApiException(533, format, a...)
}
func DeletePVFailed(format string, a ...any) *APIException {
return NewApiException(534, format, a...)
}
func GetPVListFailed(format string, a ...any) *APIException {
return NewApiException(535, format, a...)
}
func DescribePVFailed(format string, a ...any) *APIException {
return NewApiException(536, format, a...)
}
func DescribeSVCFailed(format string, a ...any) *APIException {
return NewApiException(537, format, a...)
}
func GetSVCListFailed(format string, a ...any) *APIException {
return NewApiException(538, format, a...)
}
func DeleteSVCFailed(format string, a ...any) *APIException {
return NewApiException(539, format, a...)
}
func CreateSVCFailed(format string, a ...any) *APIException {
return NewApiException(540, format, a...)
}
func UpdateSVCFailed(format string, a ...any) *APIException {
return NewApiException(541, format, a...)
}
func DescribeIngressFailed(format string, a ...any) *APIException {
return NewApiException(542, format, a...)
}
func GetIngressListFailed(format string, a ...any) *APIException {
return NewApiException(543, format, a...)
}
func DeleteIngressFailed(format string, a ...any) *APIException {
return NewApiException(544, format, a...)
}
func CreateIngressFailed(format string, a ...any) *APIException {
return NewApiException(545, format, a...)
}
func UpdateIngressFailed(format string, a ...any) *APIException {
return NewApiException(546, format, a...)
}
func GetConfigmapListFailed(format string, a ...any) *APIException {
return NewApiException(547, format, a...)
}
func DescribeConfigmapListFailed(format string, a ...any) *APIException {
return NewApiException(548, format, a...)
}
func UpdateConfigmapFailed(format string, a ...any) *APIException {
return NewApiException(549, format, a...)
}
func DeleteConfigmapFailed(format string, a ...any) *APIException {
return NewApiException(550, format, a...)
}
func CreateConfigmapFailed(format string, a ...any) *APIException {
return NewApiException(551, format, a...)
}
func GetSecretListFailed(format string, a ...any) *APIException {
return NewApiException(552, format, a...)
}
func DescribeSecretListFailed(format string, a ...any) *APIException {
return NewApiException(553, format, a...)
}
func UpdateSecretFailed(format string, a ...any) *APIException {
return NewApiException(554, format, a...)
}
func DeleteSecretFailed(format string, a ...any) *APIException {
return NewApiException(555, format, a...)
}
func CreateSecretFailed(format string, a ...any) *APIException {
return NewApiException(556, format, a...)
}
func GetPVCListFailed(format string, a ...any) *APIException {
return NewApiException(557, format, a...)
}
func DescribePVCFailed(format string, a ...any) *APIException {
return NewApiException(558, format, a...)
}
func UpdatePVCFailed(format string, a ...any) *APIException {
return NewApiException(559, format, a...)
}
func DeletePVCFailed(format string, a ...any) *APIException {
return NewApiException(560, format, a...)
}
func CreatePVCFailed(format string, a ...any) *APIException {
return NewApiException(561, format, a...)
}
func CreateWorkFlowFailed(format string, a ...any) *APIException {
return NewApiException(562, format, a...)
}
func DeleteWorkFlowFailed(format string, a ...any) *APIException {
return NewApiException(563, format, a...)
}
func ValidateFailed(format string, a ...any) *APIException {
return NewApiException(564, format, a...)
}
func CreateUserFailed(format string, a ...any) *APIException {
return NewApiException(565, format, a...)
}
func DescribeUserFailed(format string, a ...any) *APIException {
return NewApiException(566, format, a...)
}
func DeleteUserFailed(format string, a ...any) *APIException {
return NewApiException(567, format, a...)
}
func UpdateUserFailed(format string, a ...any) *APIException {
return NewApiException(568, format, a...)
}
func GetUserListFailed(format string, a ...any) *APIException {
return NewApiException(569, format, a...)
}
func GetUserGroupListFailed(format string, a ...any) *APIException {
return NewApiException(570, format, a...)
}
func DescribeUserGroupListFailed(format string, a ...any) *APIException {
return NewApiException(570, format, a...)
}
func DeleteUserGroupFailed(format string, a ...any) *APIException {
return NewApiException(571, format, a...)
}
func FindPermissionsFailed(format string, a ...any) *APIException {
return NewApiException(572, format, a...)
}
func DeleteUserToGroupFailed(format string, a ...any) *APIException {
return NewApiException(573, format, a...)
}
func DescribeUserToGroupFailed(format string, a ...any) *APIException {
return NewApiException(574, format, a...)
}
func SignTokenFailed(format string, a ...any) *APIException {
return NewApiException(575, format, a...)
}
func TokenValidationFailed(format string, a ...any) *APIException {
return NewApiException(576, format, a...)
}
func CheckPasswordFailed(format string, a ...any) *APIException {
return NewApiException(577, format, a...)
}
五、加载config文件,获取client-set实例
apps/k8sclient/client.go
package k8sclient
import (
"fmt"
"k8s-platform/config"
"k8s-platform/ioc"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"os"
)
//
// k8sClient
// @Description: k8sclient结构体包含了kubernetes.Clientset,这是与k8s API通信的主要方式
//
type K8sClient struct {
ClientSet *kubernetes.Clientset
}
func init() {
ioc.Controller().Register(&K8sClient{})
}
/*
* NewK8sClient
* @Description: 构造函数返回
* @return *k8sClient
*/
func NewK8sClient() *K8sClient {
return &K8sClient{}
}
/*
* Init
* @Description: Init方法初始化k8sclient 实例,它会设置客户端与kubetnetes集群通信所需的全部配置
* @receiver c
*/
func (c *K8sClient) Init() error {
homeDir, _ := os.UserHomeDir() // 获取当前用户的 home 目录
// 使用clientcmd 构建配置。涉及到读取kubeconfig文件并处理覆盖和默认值
restConf, err := clientcmd.BuildConfigFromFlags("", homeDir+"/"+config.KUBE_CONFIG)
if err != nil {
//log.Fatal(err)
return err
}
// 通过之前构建的配置创建Clientset,它提供了对API的访问
clientset, err := kubernetes.NewForConfig(restConf)
if err != nil {
//log.Panic(err)
return err
}
c.ClientSet = clientset
aa := ioc.Controller().GetObj(config.IOC_KUBECLIENT)
fmt.Println(aa)
return nil
}
func (c *K8sClient) Name() string {
return config.IOC_KUBECLIENT
}
六、路由配置
package router
import (
"github.com/gin-gonic/gin"
"k8s-platform/apps/k8sclient/http"
http2 "k8s-platform/apps/user/http"
http3 "k8s-platform/apps/workflow/http"
"k8s-platform/config"
"k8s-platform/ioc"
"k8s-platform/middle"
)
//
// GinRouter
// @Description: 初始化Gin
//
type GinRouter struct {
}
func NewRouter() *GinRouter {
return &GinRouter{}
}
func init() {
ioc.ApiHandler().Register(&GinRouter{})
}
func (r *GinRouter) Init() error {
return nil
}
func (r *GinRouter) Name() string {
return config.APIHANDLER_IOCNAME
}
/*
* InitApiHandler
* @Description: API Handler函数
* @receiver r
* @param router
*/
func (r *GinRouter) InitApiHandler(router *gin.Engine) {
router.Use(middle.Cors())
api := router.Group("/api/v1/kubernetes")
api.Use(middle.JWTMiddleware())
{
pods := api.Group("/pods")
{
pods.GET("/", http.PodHttpHandler.GetPodListHandler)
pods.GET("/detail", http.PodHttpHandler.DescribePod)
pods.DELETE("/", http.PodHttpHandler.DeletePod)
pods.GET("/container", http.PodHttpHandler.GetContainerInfo)
pods.GET("/logs", http.PodHttpHandler.GetPodLogs)
pods.GET("/numnp", http.PodHttpHandler.GetNamespacePodsCount)
pods.GET("/deployForPod", http.PodHttpHandler.GetPodsListByDeployment)
pods.GET("/daemonsetForPod", http.PodHttpHandler.GetPodsListByDaemonset)
pods.GET("/statefulForPod", http.PodHttpHandler.GetPodsListByStatefulset)
pods.PUT("/", http.PodHttpHandler.UpdatePod)
}
deployments := api.Group("/deployments")
{
deployments.GET("/", http.DeploymentHttpHandler.GetDeploymentList)
deployments.GET("/detail", http.DeploymentHttpHandler.DescribeDeployment)
deployments.POST("/scale", http.DeploymentHttpHandler.UpdateDeploymentScale)
deployments.DELETE("/", http.DeploymentHttpHandler.DeleteDeployment)
deployments.POST("/restart", http.DeploymentHttpHandler.RestartDeployment)
deployments.PUT("/", http.DeploymentHttpHandler.UpdateDeployment)
deployments.GET("/numdp", http.DeploymentHttpHandler.GetNamespaceDeploymentCount)
deployments.POST("/", http.DeploymentHttpHandler.CreateDeployment)
}
daemonsets := api.Group("/daemonsets")
{
daemonsets.GET("/", http.DaemonsetHttpHandler.GetDaemonSetList)
daemonsets.DELETE("/", http.DaemonsetHttpHandler.DeleteDaemonSet)
daemonsets.PUT("/", http.DaemonsetHttpHandler.UpdateDaemonSet)
daemonsets.GET("/detail", http.DaemonsetHttpHandler.DescribeDaemonSet)
daemonsets.POST("/", http.DaemonsetHttpHandler.CreateDaemonSet)
}
statefulsets := api.Group("/statefulsets")
{
statefulsets.GET("/", http.StatefulSetHttpHandler.GetStatefulSetList)
statefulsets.GET("/detail", http.StatefulSetHttpHandler.DescribeStatefulSet)
statefulsets.PUT("/", http.StatefulSetHttpHandler.UpdateStatefulSet)
statefulsets.DELETE("/", http.StatefulSetHttpHandler.DeleteStatefulset)
statefulsets.POST("/", http.StatefulSetHttpHandler.CreateStatefulset)
}
nodes := api.Group("/nodes")
{
nodes.GET("/", http.NodeHttpHandler.GetNodeList)
nodes.GET("/detail", http.NodeHttpHandler.DescribeNode)
}
namespaces := api.Group("/namespaces")
{
namespaces.GET("/", http.NamespaceHttpHandler.GetNamespaceList)
namespaces.DELETE("/:name", http.NamespaceHttpHandler.DeleteNamespace)
namespaces.POST("/", http.NamespaceHttpHandler.CreateNamespace)
namespaces.GET("/detail", http.NamespaceHttpHandler.DescribeNamespace)
namespaces.PUT("/", http.NamespaceHttpHandler.UpdateNamespace)
}
persistentvolumes := api.Group("/pv")
{
persistentvolumes.GET("/", http.PVHttpHandler.GetPvListHandler)
persistentvolumes.GET("/detail", http.PVHttpHandler.DescribePV)
persistentvolumes.DELETE("/", http.PVHttpHandler.DeletePersistentVolume)
}
services := api.Group("/services")
{
services.GET("/", http.ServiceHttpHandler.GetServiceListHandler)
services.POST("/", http.ServiceHttpHandler.CreateService)
services.DELETE("/", http.ServiceHttpHandler.DeleteService)
services.PUT("/", http.ServiceHttpHandler.UpdateService)
services.GET("/detail", http.ServiceHttpHandler.DescribeService)
}
ingress := api.Group("/ingress")
{
ingress.GET("/", http.IngressHttpHandler.GetIngressListHandler)
ingress.GET("/detail", http.IngressHttpHandler.DescribeIngress)
ingress.POST("/", http.IngressHttpHandler.CreateIngress)
ingress.DELETE("/", http.IngressHttpHandler.DeleteIngress)
ingress.PUT("/", http.IngressHttpHandler.UpdateIngress)
}
configmap := api.Group("/configmap")
{
configmap.GET("/", http.ConfigmapHttpHandler.GetConfigmapList)
configmap.GET("/detail", http.ConfigmapHttpHandler.DescribeConfigmap)
configmap.POST("/", http.ConfigmapHttpHandler.CreateConfigmap)
configmap.DELETE("/", http.ConfigmapHttpHandler.DeleteConfigmap)
configmap.PUT("/", http.ConfigmapHttpHandler.UpdateConfigmap)
}
secret := api.Group("/secret")
{
secret.GET("/", http.SecretHttpHandler.GetSecretList)
secret.GET("/detail", http.SecretHttpHandler.DescribeSecret)
secret.POST("/", http.SecretHttpHandler.CreateSecret)
secret.DELETE("/", http.SecretHttpHandler.DeleteSecret)
secret.PUT("/", http.SecretHttpHandler.UpdateSecret)
}
pvc := api.Group("/pvc")
{
pvc.GET("/", http.PVCHttpHandler.GetPvcList)
pvc.GET("/detail", http.PVCHttpHandler.DescribePvc)
pvc.POST("/", http.PVCHttpHandler.CreatePvc)
pvc.DELETE("/", http.PVCHttpHandler.DeletePvc)
pvc.PUT("/", http.PVCHttpHandler.UpdatePvc)
}
}
workflow := router.Group("/api/v1/workflow")
workflow.Use(middle.JWTMiddleware())
{
workflow.GET("/", http3.NewWorkflowHttpHandler().GetWorkflowList)
workflow.POST("/", http3.NewWorkflowHttpHandler().CreateWorkflow)
workflow.DELETE("/:id", http3.NewWorkflowHttpHandler().DeleteWorkflow)
}
user := router.Group("/api/v1/users")
user.Use(middle.JWTMiddleware())
{
user.GET("/", http2.NewUserHttpHandler().GetUserList)
user.GET("/:id", http2.NewUserHttpHandler().DescribeUser)
user.DELETE("/", http2.NewUserHttpHandler().DeleteUser)
user.POST("/", http2.NewUserHttpHandler().CreateUser)
user.PUT("/:id", http2.NewUserHttpHandler().UpdateUser)
user.GET("/groups/:id", http2.NewUserHttpHandler().GetUserHaveGroup)
user.GET("/permissions/:id", http2.NewUserHttpHandler().GetUserPermissions)
user.POST("/association", http2.NewUserHttpHandler().AddUserToGroup)
}
group := router.Group("/api/v1/groups")
group.Use(middle.JWTMiddleware())
{
group.GET("/", http2.NewUserHttpHandler().GetUserGroupList)
group.GET("/:id", http2.NewUserHttpHandler().DescribeUserGroup)
group.DELETE("/:id", http2.NewUserHttpHandler().DeleteUserGroup)
group.POST("/", http2.NewUserHttpHandler().CreateUserGroup)
group.PUT("/:id", http2.NewUserHttpHandler().UpdateUserGroup)
group.PUT("/permissions/:id", http2.NewUserHttpHandler().SetGroupPermissions)
}
login := router.Group("/api/v1/login")
{
login.POST("/", http2.NewUserHttpHandler().Login)
}
router.GET("/", r.Index)
}
func (r *GinRouter) Index(c *gin.Context) {
c.JSON(200, gin.H{
"code": 200,
"message": "success",
})
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 J.のblog!
评论