【GO】 K8s 管理系统项目[API部分--Pod]

news2025/2/25 11:30:03

K8s 管理系统项目[API部分–Pod]

前端: Vue+element plus
后端: go+gin

1. 功能设计

请添加图片描述

2. 初始化

2.1创建项目

请添加图片描述

2.2 配置goproxy

GOPROXY=https://goproxy.cn

请添加图片描述

2.3 添加格式化工具

请添加图片描述

2.4 安装模块

go get k8s.io/client-go/tools/clientcmd
go get k8s.io/api/core/v1
go get k8s.io/apimachinery/pkg/apis/meta/v1
go get github.com/gin-gonic/gin
go get github.com/wonderivan/logger
go get gorm.io/gorm
go get gorm.io/driver/sqlite
go get gorm.io/driver/mysql

3. 项目目录

3.1 项目目录含义

目录名作用
config定义全局配置,如:监听地址,管理员账号等
controllercontroller层,定义路由规则及接口入参和相应
service服务层,处理接口的业务逻辑
dao数据库操作,包含数据的增删改查
model定义数据库表的字段
db用于初始化数据库连接及配置
middle中间件层,添加全局的逻辑处理,如跨域,jwt验证等
utils工具目录,定义常用工具,如token解析,文件操作等
go.mod定义项目的依赖包以及版本
main.go项目主入口,main函数

3.2 创建目录

D:\golang\k8s-plantform> mkdir controller config service dao db model middle utils
D:\golang\k8s-plantform>tree /f
卷 新加卷 的文件夹 PATH 列表
卷序列号为 7463-6B24
D:.
│  go.mod
│  go.sum
│  main.go
│
├─.idea
│      .gitignore
│      k8s-plantform.iml
│      modules.xml
│      watcherTasks.xml
│      workspace.xml
│
├─config
│      config
│
├─controller
├─dao
├─db
├─middle
├─model
├─service
└─utils

4. 定义路由

4.1 Gin初始化

4.1.1初始化路由

controller/router.go

// 初始化router类型的对象,首字母大写,用于跨包调用
var Router router

// 声明一个router的结构体
type router struct{}

func (r *router) InitApiRouter(router *gin.Engine) {
	router.GET("/", Index)
}

func Index(ctx *gin.Context) {
	ctx.JSON(200, gin.H{
		"code": 200,
		"msg":  "In index",
	})
}

4.1.2 定义监听的常量

config/config.go

package config

const (
	ListenAddr = "0.0.0.0:9090"
)

4.1.3 gin初始化

main.go

func main() {
	// 初始化gin
	r := gin.Default()
	controller.Router.InitApiRouter(r)
	// gin 程序启动
	//r.Run(config.ListenAdd)
	r.Run(config.ListenAddr)
}

启动服务后可以正常访问到url

root@harbor-1:~# curl 192.168.31.1:9090
{"code":200,"msg":"In index"}

4.2 初始化k8s Client

4.2.1 初始化K8s client

service/init.go

import (
	"k8s-plantform/config"
	"github.com/wonderivan/logger"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

// 用于初始化k8s client
var K8s k8s

type k8s struct {
	ClientSet *kubernetes.Clientset
}

// 初始化k8s
func (k *k8s) Init() {
	// 将kuberconfig文件转换成rest.config对象
	conf, err := clientcmd.BuildConfigFromFlags("", config.KubeConfig)
	if err != nil {
		panic("获取K8s配置失败:" + err.Error())
	} else {
		logger.Info("获取K8s配置 成功!")
	}
	// 根据rest.config对象,new一个clientset出来
	clientset, err := kubernetes.NewForConfig(conf)
	if err != nil {
		panic("创建K8s client失败:" + err.Error())
	} else {
		logger.Info("创建K8s client 成功!")
	}
	k.ClientSet = clientset
}

4.2.2 定义KubeConfig常量

config/config.go

const (
	ListenAddr = "0.0.0.0:9090"
	KubeConfig = "D:\\golang\\k8s-plantform\\config\\config"
)

4.2.3 main中初始化

main.go

func main() {
	// 初始化k8s client
	service.K8s.Init()	// <<-----这行  可以使用service.K8s.clientset 进行跨包调用
	// 初始化gin
	r := gin.Default()
	controller.Router.InitApiRouter(r)
	// gin 程序启动
	//r.Run(config.ListenAdd)
	fmt.Println("http://192.168.31.1:9090/")
	r.Run(config.ListenAddr)
}

重启服务没有报错就是成功

5. API

请添加图片描述

  1. Model层: 实体层>> 表数据与类的映射关系,这里的类就是strcut
  2. Dao层: 持久层/数据访问层>> 主要与数据库交互,增删改查
  3. Service层: 业务层 >> 控制业务逻辑,主要处理业务模块的功能逻辑
  4. Controller层: 控制层>> 接收请求参数,调用不同的Service层代码来控制业务流程

5.1 数组排序,过滤,分页实现

service/dataselector.go用来处理数组的排序,过滤,分页

5.1.1 定义数据结构

// dataselector 用于排序,过滤,分页的数据类型
type dataSelector struct {
	GenericDataList []DataCell
	DataSelect      *DataSelectQuery
}

// DataCell 接口,用于各种资源List的类型转换,转换后可以使用dataselector的排序,过滤,分页方法
type DataCell interface {
	GetCreation() time.Time
	GetName() string
}

// DataSelectQuery 定义过滤和分页的结构体,过滤:Name 分页:Limit和Page
type DataSelectQuery struct {
	Filter   *FilterQuery
	Paginate *PaginateQuery
}

// FilterQuery 用于查询 过滤:Name
type FilterQuery struct {
	Name string
}

// 分页:Limit和Page Limit是单页的数据条数,Page是第几页
type PaginateQuery struct {
	Page  int
	Limit int
}

5.2 排序

// 实现自定义的排序方法,需要重写Len,Swap,Less方法
// Len用于获取数组的长度
func (d *dataSelector) Len() int {
	return len(d.GenericDataList)
}

// Swap用于数据比较大小后的位置变更
func (d *dataSelector) Swap(i, j int) {
	d.GenericDataList[i], d.GenericDataList[j] = d.GenericDataList[j], d.GenericDataList[i]
}

// Less用于比较大小
func (d *dataSelector) Less(i, j int) bool {
	return d.GenericDataList[i].GetCreation().Before(d.GenericDataList[j].GetCreation())
}

// 重写以上三个方法,用sort.Sort 方法触发排序
func (d *dataSelector) Sort() *dataSelector {
	sort.Sort(d)
	return d
}

5.3 过滤

// Filter方法用于过滤,比较数据Name属性,若包含则返回
func (d *dataSelector) Filter() *dataSelector {
	if d.DataSelect.Filter.Name == "" {
		return d
	}
	filtered := []DataCell{}
	for _, value := range d.GenericDataList {
		// 定义是否匹配的标签变量,默认是匹配的
		matches := true
		objName := value.GetName()
		if !strings.Contains(objName, d.DataSelect.Filter.Name) {
			matches = false
			continue
		}
		if matches {
			filtered = append(filtered, value)
		}
	}
	d.GenericDataList = filtered
	return d
}

5.4 分页

// Paginate 分页,根据Limit和Page的传参,取一定范围内的数据返回
func (d *dataSelector) Paginate() *dataSelector {
	limit := d.DataSelect.Paginate.Limit
	page := d.DataSelect.Paginate.Page
	//验证参数合法,若参数不合法,则返回所有数据
	if limit <= 0 || page <= 0 {
		return d
	}
	//举例:25个元素的数组,limit是10,page是3,startIndex是20,endIndex是30(实际上endIndex是25)
	startIndex := limit * (page - 1)
	endIndex := limit * page

	//处理最后一页,这时候就把endIndex由30改为25了
	if len(d.GenericDataList) < endIndex {
		endIndex = len(d.GenericDataList)
	}
	d.GenericDataList = d.GenericDataList[startIndex:endIndex]
	return d
}

5.5 定义podCell类型

定义podCell类型,实现DataCell接口用于类型转换

// 定义podCell, 重写GetCreation和GetName 方法后,可以进行数据转换
// covev1.Pod --> podCell  --> DataCell
// appsv1.Deployment --> deployCell --> DataCell
type podCell corev1.Pod
// 重写DataCell接口的两个方法
func (p podCell) GetCreation() time.Time {
	return p.CreationTimestamp.Time
}
func (p podCell) GetName() string {
	return p.Name
}

5.2 获取Pod信息

5.2.1 Pod封装转换

service/pod.go

var Pod pod

// 定义列表的返回内容,Items是pod元素列表,Total是元素数量
type PodsResp struct {
	Total int          `json:"total"`
	Items []corev1.Pod `json:"items"`
}
type pod struct{}

// 获取pod列表,支持过滤,排序,分页
func (p *pod) GetPods(filterName, namespace string, limit, page int) (podsResp *PodsResp, err error) {
	//context.TODO()  用于声明一个空的context上下文,用于List方法内设置这个请求超时
	//metav1.ListOptions{} 用于过滤List数据,如label,field等
	podList, err := K8s.ClientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		logger.Info("获取Pod列表失败," + err.Error())
		// 返回给上一层,最终返回给前端,前端捕获到后打印出来
		return nil, errors.New("获取Pod列表失败," + err.Error())
	}
	// 实例化dataselector结构体,组装数据
	selectableData := &dataselector{
		GenericDataList: p.toCells(podList.Items),
		DataSelect: &DataSelectQuery{
			Filter: &FilterQuery{Name: filterName},
			Paginate: &PaginateQuery{
				Limit: limit,
				Page:  page,
			},
		},
	}
	// 先过滤
	filtered := selectableData.Filter()
	// 排序和分页
	data := filtered.Sort().Paginate()
    total := len(data.GenericDataList)
	// 将DataCell类型转成Pod
	pods := p.fromCells(data.GenericDataList)
	return &PodsResp{
		Total: total,
        Items: pods,
	},nil
}

// 类型转换方法corev1.Pod --> DataCell,DataCell-->corev1.Pod
func (p *pod) toCells(pods []corev1.Pod) []DataCell {
	cells := make([]DataCell, len(pods))
	for i := range pods {
		cells[i] = podCell(pods[i])
	}
	return cells
}

func (p *pod) fromCells(cells []DataCell) []corev1.Pod {
	pods := make([]corev1.Pod, len(cells))
	for i := range cells {
		// cells[i].(podCell)是将DataCell类型转换成podCell
		pods[i] = corev1.Pod(cells[i].(podCell))
	}
	return pods
}

5.2.2 获取pod列表

获取pod列表,支持分页,过滤,排序

controller/pod.go

package controller

import (
	"k8s-plantform/service"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/wonderivan/logger"
)

var Pod pod

type pod struct{}

// 获取pod列表,支持分页,过滤,排序
func (p *pod) GetPods(ctx *gin.Context) {
	// 处理入参
	// 匿名结构体用于定义入参,get请求为form格式,其他为json格式
	params := new(struct {
		FilterName string `form:"filter_name"`
		Namespace  string `form:"namespace"`
		Limit      int    `form:"limit"`
		Page       int    `form:"page"`
	})
	// form 格式使用Bind方法,json格式使用ShouldBindJson方法
	if err := ctx.Bind(params); err != nil {
		logger.Error("Bind绑定参数失败," + err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  "Bind绑定参数失败," + err.Error(),
			"data": nil,
		})
		return
	}
	data, err := service.Pod.GetPods(params.FilterName, params.Namespace, params.Limit, params.Page)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "获取Pod列表成功",
		"data": data,
	})
}

5.2.3 配置router

import (
	"github.com/gin-gonic/gin"
)

// 初始化router类型的对象,首字母大写,用于跨包调用
var Router router

// 声明一个router的结构体
type router struct{}

func (r *router) InitApiRouter(router *gin.Engine) {
	router.
		GET("/api/k8s/pods", Pod.GetPods)
}

此时启动服务后可以通过postman获取到所有pod的信息

如果不加参数就是获取到所有pod信息

请添加图片描述

加了参数就可以对namespace,分页等进行过滤

请添加图片描述

可以只过滤某一个pod

请添加图片描述

5.2.4 获取Pod详情

service/pod.go

func (p *pod) GetDetail(podName string, namespace string) (pod *corev1.Pod, err error) {
	pod, err = K8s.ClientSet.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
	if err != nil {
		logger.Error("获取Pod详情失败," + err.Error())
		return nil, errors.New("获取Pod详情失败," + err.Error())
	}
	return pod, nil
}

5.2.5 删除Pod

func (p *pod) DeletePod(podName string, namespace string) (err error) {
	err = K8s.ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), podName, metav1.DeleteOptions{})
	if err != nil {
		logger.Error("删除Pod详情失败," + err.Error())
		return errors.New("删除Pod详情失败," + err.Error())
	}
	return nil
}

5.2.6 更新Pod

func (p *pod) UpdatePod(podName string, namespace, content string) (err error) {
	var pod = &corev1.Pod{}
	// 反序列化为Pod对象
	err = json.Unmarshal([]byte(content), pod)
	if err != nil {
		logger.Error("反序列化失败," + err.Error())
		return errors.New("反序列化失败," + err.Error())
	}
	// 更新pod
	_, err = K8s.ClientSet.CoreV1().Pods(namespace).Update(context.TODO(), pod, metav1.UpdateOptions{})
	if err != nil {
		logger.Error("更新Pod失败," + err.Error())
		return errors.New("更新Pod失败," + err.Error())
	}
	return nil
}

5.2.7 获取Pod中的容器名

func (p *pod) GetPodContainer(podName string, namespace string) (containers []string, err error) {
	pod, err := p.GetPodDetail(podName, namespace)
	if err != nil {
		return nil, err
	}
	for _, container := range pod.Spec.Containers {
		containers = append(containers, container.Name)
	}
	return containers, nil
}

5.2.8 获取容器日志

// 获取Pod内容器日志
func (p *pod) GetPodLog(containerName string, podName string, namespace string) (log string, err error) {
	//设置日志配置,容器名,获取内容的配置
	lineLimit := int64(config.PodLogTailLine)
	option := &corev1.PodLogOptions{
		Container: containerName,
		TailLines: &lineLimit,
	}
	// 获取一个request实例
	req := K8s.ClientSet.CoreV1().Pods(namespace).GetLogs(podName, option)
	// 发起stream连接,获取到Response.body
	podLogs, err := req.Stream(context.TODO())
	if err != nil {
		logger.Error("更新Pod失败," + err.Error())
		return "", errors.New("更新Pod失败," + err.Error())
	}
	defer podLogs.Close()
	// 将Response.body 写入到缓存区,目的为了转换成string类型
	buf := new(bytes.Buffer)
	_, err = io.Copy(buf, podLogs)
	if err != nil {
		logger.Error("复制podLog失败," + err.Error())
		return "", errors.New("复制podLog失败," + err.Error())
	}
	return buf.String(), nil
}

5.2.9 获取每个namespace中pod数量

// 获取每个namespace中pod的数量
func(p *pod) GetPodNumPerNp() (podsNps []*PodsNp, err error) {
	//获取namespace列表
	namespaceList, err := K8s.ClientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		return nil, err
	}
	for _, namespace := range namespaceList.Items {
		//获取pod列表
		podList, err := K8s.ClientSet.CoreV1().Pods(namespace.Name).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			return nil, err
		}
		//组装数据
		podsNp := &PodsNp{
			Namespace: namespace.Name,
			PodNum:    len(podList.Items),
		}
		//添加到podsNps数组中
		podsNps = append(podsNps, podsNp)
	}
	return podsNps, nil
}

5.2.10 获取pod详情

5.2.10.1 获取pod详情

controller/pod.go

// 获取pod详情
func (p *pod) GetPodDetail(ctx *gin.Context) {
	// 处理入参
	// 匿名结构体用于定义入参,get请求为form格式,其他为json格式
	params := new(struct {
		PodName   string `form:"pod_name"`
		Namespace string `form:"namespace"`
	})
	// form 格式使用Bind方法,json格式使用ShouldBindJson方法
	if err := ctx.Bind(params); err != nil {
		logger.Error("Bind绑定参数失败," + err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  "Bind绑定参数失败," + err.Error(),
			"data": nil,
		})
		return
	}
	data, err := service.Pod.GetPodDetail(params.PodName, params.Namespace)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "获取Pod列表成功",
		"data": data,
	})
}

5.2.10.2 路由配置

controller/router.go

type router struct{}

func (r *router) InitApiRouter(router *gin.Engine) {
	router.
		GET("/api/k8s/pods", Pod.GetPods).
		GET("/api/k8s/pods/detail", Pod.GetPodDetail).
		POST("/api/k8s/pods", Pod.DeletePod)
}

5.2.11 关于Pod其他功能

  1. 删除Pod
  2. 更新pod
  3. 获取pod容器
  4. 获取pod中容器日志
  5. 获取每个namespace的pod数量
// 删除Pod
func (p *pod) DeletePod(ctx *gin.Context) {
	// 处理入参
	// 匿名结构体用于定义入参,get请求为form格式,其他为json格式
	params := new(struct {
		PodName   string `json:"pod_name"`
		Namespace string `json:"namespace"`
	})
	// form 格式使用Bind方法,json格式使用ShouldBindJson方法
	if err := ctx.ShouldBindJSON(params); err != nil {
		logger.Error("Bind绑定参数失败," + err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  "Bind绑定参数失败," + err.Error(),
			"data": nil,
		})
		return
	}
	err := service.Pod.DeletePod(params.PodName, params.Namespace)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg": "删除Pod成功",
	})
}

// 更新pod
func (p *pod) UpdatePod(ctx *gin.Context) {
	params := new(struct {
		PodName   string `json:"pod_name"`
		Namespace string `json:"namespace"`
		Content   string `json:"content"`
	})
	//PUT请求,绑定参数方法改为ctx.ShouldBindJSON
	if err := ctx.ShouldBindJSON(params); err != nil {
		logger.Error("Bind请求参数失败, " + err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	err := service.Pod.UpdatePod(params.PodName, params.Namespace, params.Content)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "更新Pod成功",
		"data": nil,
	})
}

// 获取pod容器
func (p *pod) GetPodContainer(ctx *gin.Context) {
	params := new(struct {
		PodName   string `form:"pod_name"`
		Namespace string `form:"namespace"`
	})
	//GET请求,绑定参数方法改为ctx.Bind
	if err := ctx.Bind(params); err != nil {
		logger.Error("Bind请求参数失败, " + err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	data, err := service.Pod.GetPodContainer(params.PodName, params.Namespace)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "获取Pod容器成功",
		"data": data,
	})
}

// 获取pod中容器日志
func (p *pod) GetPodLog(ctx *gin.Context) {
	params := new(struct {
		ContainerName string `form:"container_name"`
		PodName       string `form:"pod_name"`
		Namespace     string `form:"namespace"`
	})
	//GET请求,绑定参数方法改为ctx.Bind
	if err := ctx.Bind(params); err != nil {
		logger.Error("Bind请求参数失败, " + err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	data, err := service.Pod.GetPodLog(params.ContainerName, params.PodName, params.Namespace)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "获取Pod中容器日志成功",
		"data": data,
	})
}

// 获取每个namespace的pod数量
func (p *pod) GetPodNumPerNp(ctx *gin.Context) {
	data, err := service.Pod.GetPodNumPerNp()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "获取每个namespace的pod数量成功",
		"data": data,
	})
}

5.2.12 定义路由

type router struct{}

func (r *router) InitApiRouter(router *gin.Engine) {
	router.
		GET("/api/k8s/pods", Pod.GetPods).
		GET("/api/k8s/pods/detail", Pod.GetPodDetail).
		POST("/api/k8s/pods", Pod.DeletePod).
		DELETE("/api/k8s/pod/del", Pod.DeletePod).
		PUT("/api/k8s/pod/update", Pod.UpdatePod).
		GET("/api/k8s/pod/container", Pod.GetPodContainer).
		GET("/api/k8s/pod/log", Pod.GetPodLog).
		GET("/api/k8s/pod/numnp", Pod.GetPodNumPerNp)
}

5.2.13 测试

依次测试以下端口

		GET("/api/k8s/pods/detail", Pod.GetPodDetail).
		POST("/api/k8s/pods", Pod.DeletePod).
		DELETE("/api/k8s/pod/del", Pod.DeletePod).
		PUT("/api/k8s/pod/update", Pod.UpdatePod).
		GET("/api/k8s/pod/container", Pod.GetPodContainer).
		GET("/api/k8s/pod/log", Pod.GetPodLog).
		GET("/api/k8s/pod/numnp", Pod.GetPodNumPerNp)

5.2.13.1 GetPodDetail

/api/k8s/pods/detail

请添加图片描述

5.2.13.2 DeletePod

/api/k8s/pods

# kubectl get pods
NAME                                        READY   STATUS    RESTARTS         AGE
centos7                                     2/2     Running   0                19d
el-gitlab-event-listener-75497dbb79-kpjmj   2/2     Running   19 (8d ago)      19d
el-s2i-listener-7c78cc48c-tvtpq             2/2     Running   18 (4m25s ago)   19d
sleep-557747455f-mvgbb                      2/2     Running   4 (19d ago)      19d

请添加图片描述

虽然还是3个pod但明显sleep-557747455f-l5hrg deployment是刚创建的.

# kubectl get pods
NAME                                        READY   STATUS    RESTARTS         AGE
centos7                                     2/2     Running   0                19d
el-gitlab-event-listener-75497dbb79-kpjmj   2/2     Running   19 (8d ago)      19d
el-s2i-listener-7c78cc48c-tvtpq             2/2     Running   18 (8m20s ago)   19d
sleep-557747455f-l5hrg                      2/2     Running   0                20s
# kubectl get deployments.apps 
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
el-gitlab-event-listener   1/1     1            1           19d
el-s2i-listener            1/1     1            1           19d
sleep                      1/1     1            1           19d

5.2.13.3 DeletePod

/api/k8s/pod/del

# kubectl get pods
NAME                                        READY   STATUS    RESTARTS         AGE
centos7                                     2/2     Running   0                19d
el-gitlab-event-listener-75497dbb79-kpjmj   2/2     Running   19 (8d ago)      19d
el-s2i-listener-7c78cc48c-tvtpq             2/2     Running   18 (8m20s ago)   19d
sleep-557747455f-l5hrg                      2/2     Running   0                20s

请添加图片描述

这里明显可以看到centos7这个pod被删除了

# kubectl get pods
NAME                                        READY   STATUS        RESTARTS       AGE
centos7                                     2/2     Terminating   0              19d
el-gitlab-event-listener-75497dbb79-kpjmj   2/2     Running       19 (8d ago)    19d
el-s2i-listener-7c78cc48c-tvtpq             2/2     Running       18 (12m ago)   19d
sleep-557747455f-6zcpj                      2/2     Running       0              82s
# kubectl get pods
NAME                                        READY   STATUS    RESTARTS       AGE
el-gitlab-event-listener-75497dbb79-kpjmj   2/2     Running   19 (8d ago)    19d
el-s2i-listener-7c78cc48c-tvtpq             2/2     Running   18 (13m ago)   19d
sleep-557747455f-6zcpj                      2/2     Running   0              108s

5.2.13.4 UpdatePod

/api/k8s/pod/update

先去获得一段json

请添加图片描述

将内容复制处理来略做改动

请添加图片描述

再次请求就可以看到这个新追加的test label

请添加图片描述

5.2.13.5 GetPodContainer

/api/k8s/pod/container

# kubectl describe pods  spring-boot-helloworld-5f77c6ff9f-k8z6v -n hello 
Name:         spring-boot-helloworld-5f77c6ff9f-k8z6v
Namespace:    hello
Priority:     0
Node:         192.168.31.111/192.168.31.111
Start Time:   Wed, 23 Nov 2022 11:00:31 +0800
Labels:       app=spring-boot-helloworld
              pod-template-hash=5f77c6ff9f
Annotations:  <none>
Status:       Running
IP:           172.100.109.74
IPs:
  IP:           172.100.109.74
Controlled By:  ReplicaSet/spring-boot-helloworld-5f77c6ff9f
Containers:
  spring-boot-helloworld:
    Container ID:   docker://1f692a565ff4c94cb811bfb5b3ac9c624841f3527bb703d269566f73f11a365f
    Image:          kurtqiu1979/spring:v0.9-20221118-081546
    Image ID:       docker-pullable://kurtqiu1979/spring@sha256:03b555ee834e27d03743ce221af839e6b81ff868bb23526c6d94501921354549
    Port:           80/TCP

得到的信息和命令行是相符的

请添加图片描述

5.2.13.6 GetPodLog

/api/k8s/pod/log

请添加图片描述

5.2.13.7 GetPodNumPerNp(命名空间pod数量)

/api/k8s/pod/numnp

这个不需要传参,直接返回所有命名空间pod的数量

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/92121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 docker buildx 构建跨平台 Go 镜像

目录 前提 docker buildx 启用 Buildx builder 实例 构建驱动 buildx 的跨平台构建策略 一次构建多个架构 Go 镜像实践 源代码和 Dockerfile 执行跨平台构建 验证构建结果 如何交叉编译 Golang 的 CGO 项目 准备交叉编译环境和依赖 交叉编译 CGO 示例 总结 参考链接…

供水设备远程监控客户案例

一、客户介绍 客户积累多年的技术研发和工程运维经验&#xff0c;对传统的恒压供水工程所面临的维护难、维修难、运维效率低和能耗管控弱等诸多问题有深刻的体会&#xff0c;经过广泛调研&#xff0c;客户最终选择使用蓝蜂物联网的云平台和边缘计算产品对恒压供水设备和工程进行…

数据处理指令(一)—— 搬移指令MOV、MVN

数据处理指令指的是和数学运算、逻辑运算相关的指令&#xff0c;比如加减乘、与或非、赋值比较等 目录 1、MOV —— 直接搬移 (1) MOV 指令格式 (2) MOV生成指令的策略&#xff08;MOV的优点&#xff09; (3) MOV 只能搬移“立即数”的原因&#xff08;MOV的缺点&#x…

问卷设计一:问卷题目哪些有类型和注意要点?

问卷法常被人们应用于社会调查中&#xff0c;它能反馈出最真实的社会信息。所以&#xff0c;很多企业为了最大程度地了解市场&#xff0c;也经常使用问卷调查法进行研究。不过&#xff0c;想要发挥出问卷法的最大用处&#xff0c;前提是要将问卷设计规范并且可量化。 想要设计…

用ArkTs在鸿蒙系统上画一个世界杯海报

偶然看到了CSDN关于世界杯的征文活动&#xff1a; 用代码画一个足球&#xff1f; 哈哈很有意思&#xff01; 想了想&#xff0c;画一个自定义View&#xff08;足球&#xff09;&#xff0c;当然是使用Canvas了&#xff0c;但除了Canvas还有没有其它方法呢&#xff1f;那是必须…

c语言算数转换 操作符

【题目名称】下面代码的结果是&#xff1a;( b)#include <stdio.h> int main() {int a, b, c;a 5;c a;b c, c, a, a;//逗号表达式从左向右以此计算 表达式结果是最后一个表达式b a c; //a9 先算加后算加等printf("a %d b %d c %d\n:", a, b, c);retu…

【软件测试】工作瓶颈?测试的出路在哪?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 3年软件测试经验&am…

【内网安全-隧道技术】SMB、ICMP、DNS隧道、SSH协议

目录 一、基础知识 二、隧道技术 1、简介&#xff1a; 2、SMB隧道 3、ICMP隧道 4、DNS隧道 5、SSH协议 6、控制上线-插件 一、基础知识 【内网安全-基础】基础知识、信息收集、工具https://blog.csdn.net/qq_53079406/article/details/128292587?spm1001.2014.3001.55…

Seata 术语

爬虫组件分析目录概述需求&#xff1a;设计思路实现思路分析1.TC (Transaction Coordinator) - 事务协调者2.TM (Transaction Manager) - 事务管理器3.RM参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&…

[附源码]Nodejs计算机毕业设计基于的防疫隔离服务系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

ruoyi-vue 集成electron详细步骤

刚使用ruoyi-vue开始集成electron的可以直接去这个地址下载源码 ruoyi-vue-electron: 使用ruoyi-vue集成electron 集成步骤&#xff1a; 1、在ruoyi-vue项目中安装electron相关插件 //进入ruoyi-ui 按顺序执行安装以下4个插件yarn add electron yarn add electron-devtools-…

5、英飞凌-AURIX-TC3X7: PWM实验之使用 GTM -TOM 实现

目录5、英飞凌-AURIX-TC3X7&#xff1a; PWM实验之使用 GTM -TOM 实现1、GTM -TOM简介2、TOM框图3、TOM全局通道控制--TGC0, TGC14、实验简介4.1、实验目的4.2、TC3X7 GTM 简介4.3、具体配置流程5、具体实现5.1、Cpu0_Main.c5.2、TOM_PWM.C5.3、TOM_PWM.h5、英飞凌-AURIX-TC3X7…

StyleGAN系列

1. Progressive Growing of GANs for Improved Quality, Stability, and Variation (PGGAN) 作者&#xff1a; Tero Karras Timo Aila Samuli Laine Jaakko Lehtinen 基于一个理论&#xff0c;高分辨率的图像相对于较小分辨率的图像&#xff0c;是更难train的&#xff0c;…

List<T>, IQueryable, IEnumerable 关系和区别

最近在修项目的历史代码&#xff0c;发现搞混了很多拓展方法&#xff0c;写一篇博客澄清一下。 概念需要&#xff1a;iqueryable不应该和ienumerable比而应该和ilist比&#xff0c;ienumerable是这两者的父接口。 问题&#xff1a;IQueryable, IEnumerable的&#xff1f; &…

Linux vi/vim

vi/vim 的使用 基本上 vi/vim 共分为三种模式&#xff0c;分别是命令模式&#xff08;Command mode&#xff09;&#xff0c;输入模式&#xff08;Insert mode&#xff09;和底线命令模式&#xff08;Last line mode&#xff09;。 这三种模式的作用分别是&#xff1a; 命令模…

数据分析可视化-FineReport 图表排序接口

1. 概述 1.1 应用场景 图表数据展示的顺序是由图表绑定的数据顺序决定的&#xff0c;一般建议在 SQL 中排好序再用图表实现。 但总有些场景不支持提前在 SQL 中排好序&#xff0c;或需要图表实现动态排序&#xff0c;此时可参考本文方法使用排序接口实现。 1.2 功能简介 Fi…

文本转语音免费 微软Azure官网

使用跨 140 种语言和变体的 400 种神经网络语音吸引全球受众。使用极具表现力和类似人类的声音&#xff0c;使文本阅读器和已启用语音的助理等方案栩栩如生。神经网络文本转语音支持多种朗读风格&#xff0c;包括新闻广播、客户服务、呼喊、耳语以及高兴、悲伤等情感。 地址 文…

数据结构---二叉堆

二叉堆二叉堆自我调整插入节点&#xff08;上浮&#xff09;删除节点(下沉)构建二叉堆(所有非叶子节点依次“下沉”)二叉堆本质上是一种完全二叉树&#xff0c;它分为两个类型。最大堆最小堆 最大堆的任何一个父节点的值&#xff0c;都大于或等于它左、右孩子\节点的值 最小堆…

【实测】windows安装部署go实录(超详细)

之前我的课程中&#xff0c;关于go语言的安装是主要展示了mac的&#xff0c;windows的就一笔带过了。 结果被我说着了&#xff08;可能在第一步直接被劝退&#xff09;&#xff0c;好多用windows的小伙伴部署go语言环境各种问题各种坑&#xff0c;网上教程看了个一知半解。没办…

网络工程毕业设计 SSM药品管理系统(源码+论文)

文章目录1 项目简介2 实现效果2.1 界面展示3 设计方案3.1 概述3.2 系统流程3.2.1 添加信息流程3.2.2 操作流程3.2.3删除信息流程3.3 系统结构设计4 项目获取1 项目简介 Hi&#xff0c;各位同学好呀&#xff0c;这里是M学姐&#xff01; 今天向大家分享一个今年(2022)最新完成…