【云原生开发】namespace管理的后端开发设计与实现
✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:云原生开发
景天的主页:景天科技苑
文章目录
- namespace管理的后端开发设计与实现
- 1、设计理念
- 2、对增删改查的逻辑进行实现
- 3、创建命名空间
- 4、删除命名空间
- 5、查询命名空间列表
- 6、查询命名空间详情
- 7、更新namespace
namespace管理的后端开发设计与实现
1、设计理念
名称空间的增删改查,逻辑和集群的差不多,我们直接将集群的复制代码过来,改改
启动程序,通过postman先测试下接口
接口可以跑通
2、对增删改查的逻辑进行实现
如果对集群中的namespace进行管理,和上一章我们做的集群管理还是有区别的。
- 首先要知道对哪个集群中的哪个namespace进行管理,我们在管理集群的时候,我们需要接收clusterid的参数,管理namespace也同样需要clusterid
- kubeconfig的获取,之前我们把集群的信息都放到secret中,因此我们需要根据clusterid查出来是哪个secret,然后通过secret的data字段,得到kubeconfig,然后通过kubeconfig实例化出一个clientset。然后通过clientset就可以对集群的资源进行操作了。
- 但是,我们每次接收到clusterid的时候,都要经过第二步的整个流程,这个步骤是个需要重复使用的步骤,如果我们把kubeconfig存放在一个map[string]string变量中,{clusterId:xxx, name: xxxx, namespace:xxx}
我们拿到clusterid之后,直接就可以拿到kubeconfig文件了。 - 创建clientset
- 操作namespace
所以,经过上述分析,我们在config.go中创建个ClusterKubeconfig变量
我们希望程序启动时,就初始化该变量
//程序启动时,就初始化初始化ClusterKubeconfig
config.ClusterKubeconfig = make(map[string]string)
// 查询当前已经存在集群配置
listOptions := metav1.ListOptions{LabelSelector: config.ClusterConfigSecretLabelKey + "=" + config.ClusterConfigSecretLabelValue,
}
secretList, _ := config.InClusterClientSet.CoreV1().Secrets(config.MetadataNamespace).List(context.TODO(), listOptions)
for _, secret := range secretList.Items {// clusterIdclusterId := secret.Namekubeconfig := secret.Data["kubeconfig"] //得到的是字节,需要转换成字符串// clusterid作为key,kubeconfig作为value,存到config.ClusterKubeconfig之中config.ClusterKubeconfig[clusterId] = string(kubeconfig)
}
// 打印一个debug
//fmt.Println("当前集群配置:", config.ClusterKubeconfig)
logs.Debug(map[string]interface{}{"当前已存在的集群": config.ClusterKubeconfig}, "展示已存在的集群配置")
然后在添加,更新,删除集群时,都要针对这个变量做相应的操作
添加,更新集群
删除集群
3、创建命名空间
我们想象一下,如果想要前端操作创建一个命名空间,需要传递给后端什么数据呢?
是不是类似这样 {clusterId:xxx, name: xxxx, namespace:xxx…}
因此,我们需要创建个结构体来接收前端传来的数据,不管我们操作namespace、pod、deployment、daemonset等等,貌似都需要这些数据。
所以说,我们可以定义一个最基础的信息basicInfo来存放一些公用字段。这些公共信息可以在很多控制器中使用。
我们将这些公共信息与方法定义在controllers.go中
// Package controllers 控制器层,实现路由的逻辑处理
package controllersimport ("errors""github.com/gin-gonic/gin""jingtian/krm-backend/config""jingtian/krm-backend/utils/logs""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)// 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"`DeleteList []string `json:"deleteList"`
}// BasicInit 这个函数用来返回通用的clientset,集群信息和error
func BasicInit(c *gin.Context, item interface{}) (clientset *kubernetes.Clientset, basicInfo BasicInfo, err error) {basicInfo = BasicInfo{}basicInfo.Item = item// 首先获取请求的类型,根据不同的请求类型来使用不同的方式绑定数据requestMethod := c.Request.Methodif 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)}if basicInfo.Namespace == "" {basicInfo.Namespace = "default"}// 获取kubeconfigkubeconfig := 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
}
postman请求创建namespace
创建成功
4、删除命名空间
删除命名空间的危险系数是非常高的,要是在生产中,稍不留意删除了K8S系统自带的一些命名空间,将会造成无法挽回的损失。
因此我们删除namespace一定要谨慎,我们在开发时,也可以做一些规避,避免用户不小心删除掉关键命名空间。
我们做一些删除保护,当用户要删除kube-system或者krm时,禁止执行该操作,防止对集群造成不必要的风险。
删除namespace的时候,后端需要接收前端传来的clusterid和name。
delete.go
package namespaceimport ("context""github.com/gin-gonic/gin""jingtian/krm-backend/config""jingtian/krm-backend/controllers""jingtian/krm-backend/utils/logs"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)// Delete 删除命名空间
func Delete(c *gin.Context) {//删除namespace是非常危险的操作,一定要谨慎logs.Debug(nil, "删除namespace")clientset, basicInfo, err := controllers.BasicInit(c, nil)returnData := config.NewReturnData()if err != nil {returnData.Msg = err.Error()returnData.Status = 400c.JSON(200, returnData)return}//规避删除kube-system系统命名空间if basicInfo.Name == "kube-system" || basicInfo.Name == "krm" {returnData.Msg = "禁止删除系统命名空间kube-system,元数据命名空间krm"returnData.Status = 400c.JSON(200, returnData)logs.Error(nil, "系统命名空间kube-system不允许删除")return}//执行删除操作err = clientset.CoreV1().Namespaces().Delete(context.TODO(), basicInfo.Name, metav1.DeleteOptions{})if err != nil {msg := "删除Namespace失败: " + err.Error()returnData.Msg = msgreturnData.Status = 400logs.Error(map[string]interface{}{"message": msg}, basicInfo.Name+" 删除失败")} else {returnData.Msg = "删除成功"logs.Info(map[string]interface{}{"message": "namespace " + basicInfo.Name + " 删除成功"}, "删除成功")}c.JSON(200, returnData)
}
postman发送删除请求,删除成功
当用户要删除krm命名空间,提示用户不能删除
5、查询命名空间列表
查询命名空间列表,也是需要先拿到clientset
package namespaceimport ("context""github.com/gin-gonic/gin""jingtian/krm-backend/config""jingtian/krm-backend/controllers""jingtian/krm-backend/utils/logs"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""net/http"
)func List(c *gin.Context) {logs.Debug(nil, "列出namespace列表")clientset, _, err := controllers.BasicInit(c, nil)returnData := config.NewReturnData()if err != nil {returnData.Msg = err.Error()returnData.Status = 400c.JSON(http.StatusOK, returnData)return}//执行查询操作namespaceList, err := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})if err != nil {msg := "查询Namespace失败: " + err.Error()returnData.Msg = msgreturnData.Status = 400} else {returnData.Msg = "查询成功"returnData.Data["items"] = namespaceList.Items//如果只想查询命名空间的名字,可以如下循环获得//var nameList []string//for _, namespace := range namespaceList.Items {// namestr := namespace.Name// nameList = append(nameList, namestr)//}//returnData.Data["items"] = nameList}c.JSON(200, returnData)
}
查询的时候,需要传参clusterId,查询哪个集群的命名空间
6、查询命名空间详情
package namespaceimport ("context""github.com/gin-gonic/gin""jingtian/krm-backend/config""jingtian/krm-backend/controllers""jingtian/krm-backend/utils/logs"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""net/http"
)func Get(c *gin.Context) {logs.Debug(nil, "获取namespace详情")clientset, basicInfo, err := controllers.BasicInit(c, nil)returnData := config.NewReturnData()if err != nil {returnData.Msg = err.Error()returnData.Status = 400c.JSON(http.StatusOK, returnData)return}namespace, err := clientset.CoreV1().Namespaces().Get(context.TODO(), basicInfo.Name, metav1.GetOptions{})if err != nil {msg := "获取Namespace详情失败: " + err.Error()returnData.Msg = msgreturnData.Status = 400} else {returnData.Msg = "获取成功"returnData.Data["item"] = namespace}c.JSON(200, returnData)
}
postman请求,获取一个不存在的namespace
获取一个存在的namespace
7、更新namespace
更新命名空间一般是更新labels或者annotations,其他字段一般也不需要更新
后端接收一个namespace实例,做下update操作即可。
更新namespace和create namespace差不多
我们在BasicInfo中,定义一个变量Item用来接收前端传来的用于更新namespace的json串
这里为什么用空接口类型呢?因为后续我们更新deployment,pod,statefulset等都可以用到该字段,所以不能写死
package namespaceimport ("context""github.com/gin-gonic/gin""jingtian/krm-backend/config""jingtian/krm-backend/controllers""jingtian/krm-backend/utils/logs"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)func Update(c *gin.Context) {logs.Debug(nil, "更新namespace")//先定义一个namespace变量var ns corev1.Namespace//创建clientset对象,将namespace指针传进去clientset, _, err := controllers.BasicInit(c, &ns)returnData := config.NewReturnData()if err != nil {returnData.Msg = err.Error()returnData.Status = 400c.JSON(200, returnData)return}//执行更新操作//更新直接用basicinfo中的Item是不行的,因为它是interface类型的,_, err = clientset.CoreV1().Namespaces().Update(context.TODO(), &ns, metav1.UpdateOptions{})if err != nil {msg := "更新Namespace失败: " + err.Error()returnData.Msg = msgreturnData.Status = 400} else {returnData.Msg = "更新成功"}c.JSON(200, returnData)}
发送更新的请求,将需要更新的namespace字段放入到item中传进去
添加一些标签,和annotations
"item": {"metadata": {"name":"jingtian","labels": {"kubernetes.io/metadata.name": "jingtian","ceshi":"ceshilabel"},"annotations":{"kubernetes.io/metadata.name": "true"}}
}
k8s集群查看更新成功
更新的时候,与其他几个在增删查方法不同的地方在于,需要将更新的资源传递给basicInfo,然后接收前端传参给item。再执行更新操作。
相关文章:
【云原生开发】namespace管理的后端开发设计与实现
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
威联通Docker Compose搭建NAS媒体库资源工具NAS Tools
文章目录 一、环境配置1-1 需要的配件1-2 环境安装及配置注意:获取PUID/PGID1-3 目录位置准备总结,这里我们要做5件事备注:Docker无法下载解决办法二、登录配件,进行配件连接和配置2-1 jackett设置2-2 qBittorrent设置!!!设置文件下载地址2-3 jellyfin设置2-4 NASTools设…...
【JAVA基础】MAVEN的安装及idea的引用说明
本篇文章主要讲解,maven的安装及集成在idea中进行构建项目的详细操作教程。 日期:2024年11月11日 作者:任聪聪 所需材料: 1、idea 2024版本及以上 2、maven 3.9.9安装包 3、一个空java springBoot项目,可以使用阿里云…...
【go从零单排】Rate Limiting限流
🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在 Go 中,速率限制(Rate Limiting)是一种控制…...
解析Eureka的架构
1. 引言 1.1 Eureka的定义与背景 Eureka是由Netflix开发的一个RESTful服务,用于服务发现。它是微服务架构中的一个核心组件,主要用于管理服务的注册和发现。Eureka允许服务提供者注册自己的服务信息,同时也允许服务消费者查询可用的服务&am…...
AI变现,做数字游民
在数字化时代,AI技术的迅猛发展不仅改变了各行各业的生产方式,还为普通人提供了前所未有的变现机会。本文将探讨如何利用AI技术实现变现,成为一名数字游民,享受自由职业带来的便利与乐趣。 一、AI技术的变现潜力 AI技术以其强大…...
linux-vlan
# VLAN # 1.topo # 2.创建命名空间 ip netns add ns1 ip netns add ns2 ip netns add ns3 # 3.创建veth设备 ip link add ns1-veth0 type veth peer name ns21-veth0 ip link add ns3-veth0 type veth peer name ns23-veth0 # 4.veth设备放入命名空间,启动接口 ip link set n…...
前端跨域~简述
前言 :绿蚁新醅酒,红泥小火炉 第一:前端跨域(粗谈概念) 1. 疑惑 当前端请求后端接口不通,浏览器控制台出现类似信息,则需要解决跨域 Access to XMLHttpRequest at ‘http://47.100.214.160:10…...
GIN:逼近WL-test的GNN架构
Introduction 在 图卷积网络GCN 中我们已经知道图神经网络在结点分类等任务上的作用,但GIN(图同构神经网络)给出了一个对于图嵌入(graph embedding)更强的公式。 GIN,图同构神经网络,致力于解…...
NIST密码学未来展望:Naughty Step 上的 SHA-1、3DES 和 SHA-224
1. 引言 NIST 几十年来一直致力于推动密码学标准的发展,2024年10月,其发布了Transitioning the Use of Cryptographic Algorithms and Key Lengths 草案: 概述了 SHA-1(为160位哈希算法) 将在不久的将来退役…...
go 集成gorm 数据库操作
一、什么是gorm GORM 是一个用于 Go 语言的 ORM(对象关系映射)库,它提供了一种简单而强大的方式来与数据库进行交互。GORM 支持多种数据库,包括 MySQL、PostgreSQL、SQLite、SQL Server 等,并且提供了丰富的功能&…...
进程 线程 和go协程的区别
进程和线程是操作系统中两个重要的执行单元,理解它们的区别对于编程和系统设计非常重要。以下是它们的主要区别: ### 进程(Process) 定义:进程是一个正在执行的程序的实例,具有独立的地址空间。 资源&…...
STM32获取SHT3X温湿度芯片数据
目录 一、概述 二、单次数据采集模式的测量 1、配置说明 2、代码实现方式 三、周期性数据采集模式的测量 1、配置说明 2、代码实现方式 四、完整代码下载链接 一、概述 SHT3X是Sensirion公司推出的一款高精度、完全校准的温湿度传感器,基于CMOSens技术。它提…...
卸载miniconda3
1. 找到miniconda目录,删除。 rm -rf miniconda3/ 2. 编辑bashrc sudo vim .bashrc setup路径改回anaconda3的,注释掉“>>> conda initialize >>>”和"<<< conda initialize <<<"之间的miniconda的语…...
游戏中的设计模式及杂项
概述 如果要做以下游戏功能会用到哪些设计模式。比如创建一个人物角色,这个角色可以装备刀,然后角色可以用刀砍怪物,造成流血。 对于这个游戏功能,可以使用以下设计模式: 工厂模式(Factory Pattern&#x…...
Docker网络和overlay的基础讲解
本人发现了两篇写的不错的文章:Docker网络 - docker network详解-CSDN博客,Docker 容器跨主机通信 overlay_docker overlay 网络-CSDN博客 因为这两篇文章中含有大量的例子,新手看起来毫不费力。于是我偷了个小懒,在本篇文章中没有…...
分布式数据库:深入探讨架构、挑战与未来趋势
引言 在数字化时代,数据已成为企业的核心资产。随着数据量的爆炸性增长和业务需求的多样化,传统的集中式数据库已难以满足现代应用对于高可用性、可扩展性和性能的需求。分布式数据库以其独特的优势,如数据的高可用性、容错性和可扩展性&…...
基于Springboot+Vue的仓库管理系统 (含源码数据库)
1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…...
基于立体连接与开源链动 2+1 模式的新商业路径探索
摘要:本文深入剖析了立体连接的内涵,包括其核心关键词、连接路径与主体,同时详细阐述了开源链动 2 1 模式、AI 智能名片和 S2B2C 商城小程序源码的特点与功能。在此基础上,深入研究这些要素的融合方式及其在商业实践中的应用&…...
开启鸿蒙开发之旅:核心组件及其各项属性介绍——布局容器组件
写在前面 组件的结构 rkTS通过装饰器 Component 和 Entry 装饰 struct 关键字声明的数据结构,构成一个自定义组件。 自定义组件中提供了一个 build 函数,开发者需在该函数内以链式调用的方式进行基本的 UI 描述 今天我们要学习的就是写在build 函数里的系…...
RabbitMQ 全面解析:语法与其他消息中间件的对比分析
1. 引言 在分布式系统和微服务架构中,消息中间件扮演着重要的角色。它们能够解耦服务、平衡负载、提高系统的可扩展性和可靠性。RabbitMQ 是其中广受欢迎的一种。本文将从 RabbitMQ 的基础概念、语法介绍、以及与其他消息中间件的对比角度,全面剖析其在…...
Three.js 搭建3D隧道监测
Three.js 搭建3D隧道监测 Three.js 基础元素场景scene相机carema网络模型Mesh光源light渲染器renderer控制器controls 实现3d隧道监测基础实现道路实现隧道实现多个摄像头点击模型进行属性操作实现点击模型发光效果 性能监视器stats引入使用 总结完整代码 我们将通过three.js技…...
「IDE」集成开发环境专栏目录大纲
✨博客主页何曾参静谧的博客📌文章专栏「IDE」集成开发环境📚全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定…...
MySQL-初识数据库
目录 一、数据库基础概念 1、SQL 2、数据(Data) 3、数据库(DB) 4、数据库管理系统DBMS 5、数据库系统DBS 6、关系模型(Relational Model) 7、E-R图 8、常见的数据库 9、数据库基本操作 一、数据库…...
初始 html
html 文件结构 html 标签是整个 html 文件的根标签(最顶层标签) head 标签中写页面的属性. body 标签中写的是页面上显示的内容 title 标签中写的是页面的标题 <html><head><title>这是一个标题</title></head><body></body> <…...
前端 call、bind、apply的实际使用
目录 一、call 1、继承的子类可以使用父类的方法 2、可以接收任意参数 二、call、apply、bind比较 1、案例一 2、案例二 三、总结 这个三个方法都是改变函数的this指向的方法。 一、call 代码: const obj{uname:"pink"}function fn(){console.log…...
非关系型数据库NoSQL的类型与优缺点对比
NoSQL数据库根据数据模型和应用场景主要分为四种类型:键值型、列族型、文档型和图形型。以下是对每种类型的详细描述,包括其应用场景、优缺点的比较: 1. 键值型数据库 (Key-Value Store) 典型代表 RedisMemcachedAmazon DynamoDB 应用场景…...
面试击穿mysql
Mysql三大范式: 第一范式(1NF): 不符合第一范式的典型情况是在一个字段中存放多种不同类型的详细信息。例如,在商品表中,若将商品名称、价格和类型都存储在同一个字段中,会带来诸多弊端。首先,在…...
PyQt5超详细教程终篇
PyQt5超详细教程 前言 接: [【Python篇】PyQt5 超详细教程——由入门到精通(序篇)](【Python篇】PyQt5 超详细教程——由入门到精通(序篇)-CSDN博客) 建议把代码复制到pycahrm等IDE上面看实际效果,方便理…...
Android OpenGL ES详解——纹理:纹理过滤GL_NEAREST和GL_LINEAR的区别
目录 一、概念 1、纹理过滤 2、邻近过滤 3、线性过滤 二、邻近过滤和线性过滤的区别 三、源码下载 一、概念 1、纹理过滤 当纹理被应用到三维物体上时,随着物体表面的形状和相机视角的变化,会导致纹理在渲染过程中出现一些问题,如锯齿…...
网站建设涉及和描述的一些问题/自媒体培训
题目传送门 大致题意: 输入测试用例个数T,输入点的个数n(n为偶数),再分别输入n个不同的点的坐标,要求输出四个整数x1,y1,x2,y2,表示有一条经过点(x1,y1),(x2,y2)的直线将该二维平面内的点分成点…...
架设网站是自己架设服务器还是租服务器/关键字挖掘
向上滑动阅读电脑学习是一个“绿色、实用、免费”平台,我们致力于帮助更多用户掌握电脑知识、手机技巧、互联网知识,并推荐电脑和手机等各种优质工具,发布各种实用软件及安装教程。常见问题及解决方案本公众号提供了数以万计的实用工具和教程…...
学校二级网站建设自查情况/拼多多关键词怎么优化
学习的主要是从文件读取数据、异常处理基本语法本节课学习如何使用Python向文本文件中写入数据、异常处理的深入补充将上课demo中的谈话内容(conversations)按角色(role)的不同,分别存入两个文本文件中 man [] #分别定…...
怎么做网站地图导航/网站 seo
其实很简单,最近可能需要对postgresql进行监控,所以接触了很多相关的监控命令和工具,这边文章主要是记录下工作过程,怕之后会忘记。转载注明出处:http://blog.csdn.net/lengzijian/article/details/8133471我想要的功能…...
微信二维码网站制作/重庆百度推广开户
1cmd查看 ipconfig -all 2电脑设置查看...
公司网站建设需要多少钱/进入百度
“ 本文业务角度分享了风控业务中构建关系特征的一些实践经验,包括数据源分析,关系网络和特征的构建,特征性能的评估以及线上方案的落实。”作者:求是汪在路上来源:知乎专栏 风控模型算法。编辑:happyGirl风…...