【云原生开发】k8s后台管理系统开发接口优化方案

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑

🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。

🏆《博客》:Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏: 云原生开发
景天的主页: 景天科技苑

文章目录

  • 接口优化
    • [1. 首先先安装下kubeutils](#1. 首先先安装下kubeutils)
    • [2. 使用接口改造controllers.go](#2. 使用接口改造controllers.go)
    • [3. 创建pod功能实现](#3. 创建pod功能实现)
    • [4. 查询pod列表功能实现](#4. 查询pod列表功能实现)
    • [5. 获取pod详情功能实现](#5. 获取pod详情功能实现)
    • [6. 更新pod功能](#6. 更新pod功能)
    • [7. 删除单个pod和批量删除pod功能](#7. 删除单个pod和批量删除pod功能)

接口优化

观察前面我们开发的代码,我们发现,每种资源都有类似的增删改查逻辑,如果我们把这些类似的逻辑,做成统一的接口,就不用每种资源都需要写重复的代码了。

该怎么设计呢?

我们基于命名空间的struct,写增删改查方法,然后让各类资源去调用

我们使用一个接口工具来优化代码

接口工具地址:https://github.com/littlefun91/kubeutils

功能使用方法

1. 首先先安装下kubeutils

bash 复制代码
go get -u github.com/littlefun91/kubeutils

2. 使用接口改造controllers.go

创建各种资源,都可以使用这里面通用的增删改查方法

go 复制代码
// Package controllers 控制器层,实现路由的逻辑处理
package controllers

import (
    "errors"
    "github.com/gin-gonic/gin"
    "github.com/littlefun91/kubeutils/kubeutils"
    "jingtian/krm-backend/config"
    "jingtian/krm-backend/utils/logs"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "net/http"
)

// BasicInfo 定义全局的数据结构
type BasicInfo struct {
    //使用form标签指定参数名,以便正确地绑定参数 get请求使用功能form标签
    ClusterId  string      `json:"clusterId" form:"clusterId"`
    Namespace  string      `json:"namespace" form:"namespace"`
    Name       string      `json:"name" form:"name"`
    Item       interface{} `json:"item"`       //用来接收前端传来的更新资源的json串
    DeleteList []string    `json:"deleteList"` //用来接收前端传来的删除资源的json串,可以删一个,也可以删多个
}

type Info struct {
    BasicInfo
    ReturnData    config.ReturnData
    LabelSelector string `json:"labelSelector" form:"labelSelector"`
    FieldSelector string `json:"fieldSelector" form:"fieldSelector"`
    // 判断是否是强制删除
    Force bool `json:"force" form:"force"`
}

// NewInfo 定义一个函数,用来返回kubeconfig
func NewInfo(c *gin.Context, info *Info, returnDataMsg string) (kubeconfig string) {
    // 首先获取请求的类型
    requestMethod := c.Request.Method
    var err error
    // var returnData config.ReturnData
    info.ReturnData.Msg = returnDataMsg
    info.ReturnData.Status = 200
    if requestMethod == "GET" {
        err = c.ShouldBindQuery(&info)
    } else if requestMethod == "POST" {
        err = c.ShouldBindJSON(&info)
    } else {
        err = errors.New("不支持的请求类型")
    }
    logs.Debug(map[string]interface{}{"info": info}, "数据绑定结果")
    if err != nil {
        msg := "请求出错: " + err.Error()
        info.ReturnData.Msg = msg
        info.ReturnData.Status = 400
        logs.Error(nil, msg)
        c.JSON(http.StatusOK, info.ReturnData)
        return
    }
    // 获取kubeconfig
    kubeconfig = config.ClusterKubeconfig[info.ClusterId]

    //我们的接口工具只需要接收个kubeconfig文件就可以实现增删改查了
    return kubeconfig
}

// Create Info中的增删改查方法,重写kubeutils中的增删改查方法
func (i *Info) Create(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
    //Create里面传参是namespace
    err := kubeUtilsInterface.Create(i.Namespace)
    if err != nil {
        msg := "创建失败: " + err.Error()
        i.ReturnData.Msg = msg
        i.ReturnData.Status = 400
        logs.Error(nil, msg)
    }
    c.JSON(200, i.ReturnData)
}

func (i *Info) Update(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
    err := kubeUtilsInterface.Update(i.Namespace)
    if err != nil {
        msg := "更新失败: " + err.Error()
        i.ReturnData.Msg = msg
        i.ReturnData.Status = 400
        logs.Error(nil, msg)
    }
    r.JSON(200, i.ReturnData)
}
func (i *Info) List(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
    items, err := kubeUtilsInterface.List(i.Namespace, i.LabelSelector, i.FieldSelector)
    if err != nil {
        msg := "查询失败: " + err.Error()
        i.ReturnData.Msg = msg
        i.ReturnData.Status = 400
        logs.Error(nil, msg)
    } else {
        i.ReturnData.Data = make(map[string]interface{})
        i.ReturnData.Data["items"] = items
    }
    c.JSON(200, i.ReturnData)
}

func (i *Info) Get(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
    item, err := kubeUtilsInterface.Get(i.Namespace, i.Name)
    if err != nil {
        msg := "查询失败: " + err.Error()
        i.ReturnData.Msg = msg
        i.ReturnData.Status = 400
        logs.Error(nil, msg)
    } else {
        i.ReturnData.Data = make(map[string]interface{})
        i.ReturnData.Data["item"] = item
    }
    c.JSON(200, i.ReturnData)
}

func (i *Info) Delete(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
    var gracePeriodSeconds int64
    if i.Force {
        // 强制删除
        var s int64 = 0
        gracePeriodSeconds = s
    }
    err := kubeUtilsInterface.Delete(i.Namespace, i.Name, &gracePeriodSeconds)
    if err != nil {
        msg := "删除失败: " + err.Error()
        i.ReturnData.Msg = msg
        i.ReturnData.Status = 400
        logs.Error(nil, msg)
    }
    c.JSON(200, i.ReturnData)
}

func (i *Info) DeleteList(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
    var gracePeriodSeconds int64
    if i.Force {
        // 强制删除
        var s int64 = 0
        gracePeriodSeconds = s
    }
    err := kubeUtilsInterface.DeleteList(i.Namespace, i.BasicInfo.DeleteList, &gracePeriodSeconds)
    if err != nil {
        msg := "删除失败: " + err.Error()
        i.ReturnData.Msg = msg
        i.ReturnData.Status = 400
        logs.Error(nil, msg)
    }
    c.JSON(200, i.ReturnData)
}

// BasicInit 这个函数用来返回通用的clientset,集群信息和error
func BasicInit(c *gin.Context, item interface{}) (clientset *kubernetes.Clientset, basicInfo BasicInfo, err error) {
    basicInfo = BasicInfo{}
    //根据传参,来确定Item的类型,可以接收任意的资源
    basicInfo.Item = item
    // 首先获取请求的类型,根据不同的请求类型来使用不同的方式绑定数据
    requestMethod := c.Request.Method
    if requestMethod == "GET" {
        err = c.ShouldBindQuery(&basicInfo)
    } else if requestMethod == "POST" {
        err = c.ShouldBindJSON(&basicInfo)
    } else {
        err = errors.New("不支持的请求类型")
    }
    logs.Debug(map[string]interface{}{"basicInfo": basicInfo}, "数据绑定结果")
    if err != nil {
        msg := "请求出错: " + err.Error()
        return nil, basicInfo, errors.New(msg)
    }
    //如果前端不传namespace,就用默认的命名空间
    if basicInfo.Namespace == "" {
        basicInfo.Namespace = "default"
    }
    // 获取kubeconfig
    kubeconfig := config.ClusterKubeconfig[basicInfo.ClusterId]
    restConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(kubeconfig))
    if err != nil {
        msg := "解析kubeconfig错误: " + err.Error()
        return nil, basicInfo, errors.New(msg)
    }
    //创建客户端
    clientset, err = kubernetes.NewForConfig(restConfig)
    if err != nil {
        msg := "创建clientset失败: " + err.Error()
        return nil, basicInfo, errors.New(msg)
    }
    return clientset, basicInfo, nil
}

3. 创建pod功能实现

pod/creaet.go

go 复制代码
package pod

import (
    "github.com/gin-gonic/gin"
    "github.com/littlefun91/kubeutils/kubeutils"
    "jingtian/krm-backend/controllers"
    "jingtian/krm-backend/utils/logs"
    corev1 "k8s.io/api/core/v1"
)

// Create 创建namespace函数
func Create(c *gin.Context) {
    logs.Debug(nil, "创建pod")
    var pod corev1.Pod
    var info controllers.Info
    info.Item = &pod
    kubeconfig := controllers.NewInfo(c, &info, "pod创建成功")

    //改为接口形式的创建
    var kubeUtilser kubeutils.KubeUtilser
    instance := kubeutils.NewPod(kubeconfig, &pod)
    // 把实例复制给kubeUtilser
    kubeUtilser = instance
    // 使用kubeUtilser创建资源
    info.Create(c, kubeUtilser)
}

执行创建请求

yaml 复制代码
{
    "clusterId":"cluster01",
    "namespace":"jingtian",
    "item": {
        "apiVersion": "v1",
        "kind": "Pod",
        "metadata": {
            "labels": {
                "app": "web6"
            },
            "name": "web6"
        },
        "spec": {
            "containers": [
                {
                    "env": [
                        {
                            "name": "GIN_MODE",
                            "value": "release"
                        },
                        {
                            "name": "LOG_LEVEL",
                            "value": "info"
                        }
                    ],
                    "image": "web:v4",
                    "imagePullPolicy": "IfNotPresent",
                    "name": "myweb",
                    "ports": [
                        {
                            "containerPort": 8080,
                            "protocol": "TCP"
                        }
                    ]

                }
            ]
        }
    }
}

k8s集群查看,pod创建成功

4. 查询pod列表功能实现

go 复制代码
package pod

import (
    "github.com/gin-gonic/gin"
    "github.com/littlefun91/kubeutils/kubeutils"
    "jingtian/krm-backend/controllers"
    "jingtian/krm-backend/utils/logs"
)

func List(c *gin.Context) {
    logs.Debug(nil, "列出pod列表")
    //声明结构体,用结构体的方法创建资源
    var info controllers.Info
    //newInfo里面传默认的returndata.msg
    kubeconfig := controllers.NewInfo(c, &info, "pod查询成功")

    var kubeUtilser kubeutils.KubeUtilser
    instance := kubeutils.NewPod(kubeconfig, nil)
    // 把实例复制给kubeUtilser
    kubeUtilser = instance
    // 使用kubeUtilser查询资源
    info.List(c, kubeUtilser)

}

查询成功

5. 获取pod详情功能实现

go 复制代码
 package pod

import (
    "github.com/gin-gonic/gin"
    "github.com/littlefun91/kubeutils/kubeutils"
    "jingtian/krm-backend/controllers"
    "jingtian/krm-backend/utils/logs"
)

func Get(c *gin.Context) {
    logs.Debug(nil, "获取pod详情")
    //声明结构体,用结构体的方法创建资源
    var info controllers.Info
    //newInfo里面传默认的returndata.msg
    kubeconfig := controllers.NewInfo(c, &info, "pod查询详情成功")

    var kubeUtilser kubeutils.KubeUtilser
    instance := kubeutils.NewPod(kubeconfig, nil)
    // 把实例复制给kubeUtilser
    kubeUtilser = instance
    // 使用kubeUtilser查询资源
    info.Get(c, kubeUtilser)

}

postman请求

6. 更新pod功能

一般,工作中我们也很少去更新pod。暂时不支持更新pod操作,响应给前端。

go 复制代码
package pod

import (
    "github.com/gin-gonic/gin"
    "jingtian/krm-backend/config"
    "jingtian/krm-backend/utils/logs"
)

func Update(c *gin.Context) {
    logs.Debug(nil, "更新pod")
    var returnData config.ReturnData
    returnData.Msg = "Pod暂不支持更新操作"
    returnData.Status = 200
    c.JSON(200, returnData)
}

7. 删除单个pod和批量删除pod功能

go 复制代码
package pod

import (
    "github.com/gin-gonic/gin"
    "github.com/littlefun91/kubeutils/kubeutils"
    "jingtian/krm-backend/controllers"
    "jingtian/krm-backend/utils/logs"
)

// Delete 删除命名空间
func Delete(c *gin.Context) {
    logs.Debug(nil, "删除单个pod")
    //声明结构体,用结构体的方法创建资源
    var info controllers.Info
    //newInfo里面传默认的returndata.msg
    kubeconfig := controllers.NewInfo(c, &info, "pod删除成功")

    var kubeUtilser kubeutils.KubeUtilser
    instance := kubeutils.NewPod(kubeconfig, nil)
    // 把实例复制给kubeUtilser
    kubeUtilser = instance
    // 使用kubeUtilser查询资源
    info.Delete(c, kubeUtilser)

}

// DeleteList 批量删除
func DeleteList(c *gin.Context) {
    logs.Debug(nil, "批量删除pod")
    //声明结构体,用结构体的方法创建资源
    var info controllers.Info
    //newInfo里面传默认的returndata.msg
    kubeconfig := controllers.NewInfo(c, &info, "pod批量删除成功")

    var kubeUtilser kubeutils.KubeUtilser
    instance := kubeutils.NewPod(kubeconfig, nil)
    // 把实例复制给kubeUtilser
    kubeUtilser = instance
    // 使用kubeUtilser查询资源
    info.DeleteList(c, kubeUtilser)

}

看下目前jingtian命名空间下的pod

postman执行删除单个pod

集群查看,删除单个pod成功

批量删除pod

集群查看,批量删除pod成功

相关推荐
Karoku0665 小时前
【k8s集群应用】kubeadm1.20高可用部署(3master)
运维·docker·云原生·容器·kubernetes
探索云原生10 小时前
在 K8S 中创建 Pod 是如何使用到 GPU 的: nvidia device plugin 源码分析
ai·云原生·kubernetes·go·gpu
启明真纳10 小时前
elasticache备份
运维·elasticsearch·云原生·kubernetes
hkNaruto13 小时前
【P2P】【Go】采用go语言实现udp hole punching 打洞 传输速度测试 ping测试
golang·udp·p2p
入 梦皆星河13 小时前
go中常用的处理json的库
golang
会飞的土拨鼠呀14 小时前
chart文件结构
运维·云原生·kubernetes
海绵波波10715 小时前
Gin-vue-admin(2):项目初始化
vue.js·golang·gin
每天写点bug16 小时前
【go每日一题】:并发任务调度器
开发语言·后端·golang
一个不秃头的 程序员16 小时前
代码加入SFTP Go ---(小白篇5)
开发语言·后端·golang
基哥的奋斗历程16 小时前
初识Go语言
开发语言·后端·golang