当前位置: 首页 > news >正文

【云原生开发】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进行管理,和上一章我们做的集群管理还是有区别的。

  1. 首先要知道对哪个集群中的哪个namespace进行管理,我们在管理集群的时候,我们需要接收clusterid的参数,管理namespace也同样需要clusterid
  2. kubeconfig的获取,之前我们把集群的信息都放到secret中,因此我们需要根据clusterid查出来是哪个secret,然后通过secret的data字段,得到kubeconfig,然后通过kubeconfig实例化出一个clientset。然后通过clientset就可以对集群的资源进行操作了。
  3. 但是,我们每次接收到clusterid的时候,都要经过第二步的整个流程,这个步骤是个需要重复使用的步骤,如果我们把kubeconfig存放在一个map[string]string变量中,{clusterId:xxx, name: xxxx, namespace:xxx}
    我们拿到clusterid之后,直接就可以拿到kubeconfig文件了。
  4. 创建clientset
  5. 操作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位哈希算法) 将在不久的将来退役&#xf…...

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目录&#xff0c;删除。 rm -rf miniconda3/ 2. 编辑bashrc sudo vim .bashrc setup路径改回anaconda3的&#xff0c;注释掉“>>> conda initialize >>>”和"<<< conda initialize <<<"之间的miniconda的语…...

游戏中的设计模式及杂项

概述 如果要做以下游戏功能会用到哪些设计模式。比如创建一个人物角色&#xff0c;这个角色可以装备刀&#xff0c;然后角色可以用刀砍怪物&#xff0c;造成流血。 对于这个游戏功能&#xff0c;可以使用以下设计模式&#xff1a; 工厂模式&#xff08;Factory Pattern&#x…...

Docker网络和overlay的基础讲解

本人发现了两篇写的不错的文章&#xff1a;Docker网络 - docker network详解-CSDN博客&#xff0c;Docker 容器跨主机通信 overlay_docker overlay 网络-CSDN博客 因为这两篇文章中含有大量的例子&#xff0c;新手看起来毫不费力。于是我偷了个小懒&#xff0c;在本篇文章中没有…...

分布式数据库:深入探讨架构、挑战与未来趋势

引言 在数字化时代&#xff0c;数据已成为企业的核心资产。随着数据量的爆炸性增长和业务需求的多样化&#xff0c;传统的集中式数据库已难以满足现代应用对于高可用性、可扩展性和性能的需求。分布式数据库以其独特的优势&#xff0c;如数据的高可用性、容错性和可扩展性&…...

基于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 模式的新商业路径探索

摘要&#xff1a;本文深入剖析了立体连接的内涵&#xff0c;包括其核心关键词、连接路径与主体&#xff0c;同时详细阐述了开源链动 2 1 模式、AI 智能名片和 S2B2C 商城小程序源码的特点与功能。在此基础上&#xff0c;深入研究这些要素的融合方式及其在商业实践中的应用&…...

开启鸿蒙开发之旅:核心组件及其各项属性介绍——布局容器组件

写在前面 组件的结构 rkTS通过装饰器 Component 和 Entry 装饰 struct 关键字声明的数据结构&#xff0c;构成一个自定义组件。 自定义组件中提供了一个 build 函数&#xff0c;开发者需在该函数内以链式调用的方式进行基本的 UI 描述 今天我们要学习的就是写在build 函数里的系…...

终极QMC解码器实战指南:3分钟快速解锁QQ音乐加密文件

终极QMC解码器实战指南&#xff1a;3分钟快速解锁QQ音乐加密文件 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 你是否曾经下载了QQ音乐平台的歌曲&#xff0c;却发现文件…...

微信单向好友检测实战:3步智能发现谁悄悄删除了你

微信单向好友检测实战&#xff1a;3步智能发现谁悄悄删除了你 【免费下载链接】WechatRealFriends 微信好友关系一键检测&#xff0c;基于微信ipad协议&#xff0c;看看有没有朋友偷偷删掉或者拉黑你 项目地址: https://gitcode.com/gh_mirrors/we/WechatRealFriends 你…...

终极指南:3分钟免费配置PotPlayer百度翻译插件,实现实时字幕翻译

终极指南&#xff1a;3分钟免费配置PotPlayer百度翻译插件&#xff0c;实现实时字幕翻译 【免费下载链接】PotPlayer_Subtitle_Translate_Baidu PotPlayer 字幕在线翻译插件 - 百度平台 项目地址: https://gitcode.com/gh_mirrors/po/PotPlayer_Subtitle_Translate_Baidu …...

VINS-Mono跑EUROC数据集实战:如何解读Rviz可视化结果与评估轨迹精度?

VINS-Mono EUROC数据集实战&#xff1a;Rviz可视化与轨迹精度评估全解析 当你第一次在Rviz中看到VINS-Mono处理EUROC数据集生成的复杂点云和轨迹时&#xff0c;那种既兴奋又困惑的感觉我完全理解。作为一款开源的视觉惯性里程计(VIO)系统&#xff0c;VINS-Mono在无人机、移动机…...

把“贪吃蛇”做成塔防Boss,这个Unity模板是怎么设计的?附完整变现思路

在 Unity Asset Store 上&#xff0c;大多数塔防模板都遵循一个经典逻辑&#xff1a;敌人走路径&#xff0c;玩家建塔防守。 但今天这个插件 Snake Army Defense - Complete Mobile Game Template&#xff0c;做了一件很有意思的事——它把传统塔防玩法“反过来了”。 敌人不…...

观察使用Token Plan套餐后月度AI调用成本的变化趋势

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 观察使用Token Plan套餐后月度AI调用成本的变化趋势 1. 项目背景与成本挑战 作为一个小型技术团队的负责人&#xff0c;我负责维护…...

ASL1架构规范语言:Arm处理器设计的核心工具

1. ASL1架构规范语言概述ASL1&#xff08;Architecture Specification Language&#xff09;是Arm公司专为处理器架构设计开发的领域特定语言&#xff08;DSL&#xff09;&#xff0c;主要用于精确描述Arm架构参考手册中的指令集行为。这种语言在2025年发布的A-profile架构参考…...

SVG 滤镜:全面解析与高效应用

SVG 滤镜&#xff1a;全面解析与高效应用 引言 SVG&#xff08;可缩放矢量图形&#xff09;作为一种广泛使用的图形格式&#xff0c;因其具有高度的可缩放性和跨平台性而备受青睐。SVG 滤镜作为 SVG 的一项强大功能&#xff0c;能够实现丰富的图形效果&#xff0c;提升图形的表…...

保险科技前端开源方案Insura:动态表单与保费试算核心实现

1. 项目概述&#xff1a;一个面向保险行业的开源前端解决方案最近在梳理一些开源项目时&#xff0c;发现了一个挺有意思的仓库&#xff1a;Rashed-ux920/insura。从名字上拆解&#xff0c;“insura”显然是“Insurance”&#xff08;保险&#xff09;的缩写&#xff0c;而作者“…...

RT-Thread开发实战(8)— 基于SPI驱动TFTLCD实现动态数据可视化

1. 从零开始玩转SPI驱动TFTLCD 第一次用RT-Thread驱动TFTLCD屏幕时&#xff0c;我盯着那堆密密麻麻的引脚直发懵。后来才发现&#xff0c;只要搞明白SPI通信和屏幕驱动芯片的关系&#xff0c;这事儿其实比想象中简单多了。我们这次要对付的是ST7789V2这款驱动芯片&#xff0c;它…...