【k8s多集群管理平台开发实践】十一、client-go实现读取k8s的事件信息

文章目录

简介

本章节主要讲解通过client-go实现读取k8s事件信息,并通过layui实现界面操作,其中包含控制器这部分的代码,模型这部分代码,以及前端的html代码。

一.k8s读取k8s事件

1.1.controllers控制器代码

通过传递集群id、命名空间、资源类型来进行过滤,并调用模型代码中EventList函数来读取事件

golang 复制代码
func (this *EventController) List() {
	clusterId := this.GetString("clusterId")
	namespace := this.GetString("nameSpace")
	kind := this.GetString("kind") //类型包括:Pod/Namespace/Ingress/Service/Node/Configmap/Deployment/Stateful/Job/Cronjob/Secret可参考阿里云k8s事件中心类型
	
	objName := this.GetString("objName")
	limitd, _ := this.GetInt64("limit")
	List, err := m.EventList(clusterId, namespace, kind, objName, limitd)
	msg := "success"
	code := 0
	count := len(List)
	if err != nil {
		log.Println(err)
		msg = err.Error()
		code = -1
	}
	this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &List}
	this.ServeJSON()
}
1.2.models模型代码

先定义一个结构体Events,然后定义一个结构体数组var bbb = make([]Events, 0),并循环读取Items中的数据并赋值到结构体,然后再追加到数组中bbb

golang 复制代码
type Events struct {
	EventType  string `json:"eventType"` //事件类型 warnning
	Kind       string `json:"kind"`      //对象类型 pod or deployment
	ObjName    string `json:"objName"`   //对象:pod的名称
	Message    string `json:"message"`   //信息
	Reason     string `json:"reason"`    //原因、内容
	CreateTime string `json:"createTime"`
}

func EventList(kubeconfig, namespace, kind, objName string, limitd int64) ([]Events, error) {
	clientset := common.ClientSet(kubeconfig)
	var err error
	var events *corev1.EventList

	var listOptions = metav1.ListOptions{}
	if limitd > 0 {
		listOptions = metav1.ListOptions{
			Limit: limitd,
		}
	}

    //根据传递的类型进行过滤事件
	if kind != "" && objName != "" {
		listOptions = metav1.ListOptions{
			FieldSelector: fmt.Sprintf("involvedObject.name=%s", objName),
			TypeMeta:      metav1.TypeMeta{Kind: fmt.Sprintf("%s", kind)},
		}
		events, err = clientset.CoreV1().Events(namespace).List(context.TODO(), listOptions)
	} else if kind != "" && objName == "" {
		listOptions = metav1.ListOptions{
			TypeMeta: metav1.TypeMeta{Kind: fmt.Sprintf("%s", kind)},
		}
		events, err = clientset.CoreV1().Events(namespace).List(context.TODO(), listOptions)
	} else {
		events, err = clientset.CoreV1().Events(namespace).List(context.TODO(), listOptions)
	}
	
	if err != nil {
		log.Printf("list deployment error, err:%v\n", err)
	}
    //将事件按照时间进行倒序输出
	lessFunc := func(i, j int) bool {
		return events.Items[j].CreationTimestamp.Before(&events.Items[i].CreationTimestamp)
	}
	sort.SliceStable(events.Items, lessFunc)

	var bbb = make([]Events, 0)
	for _, item := range events.Items {
        //用于过滤和搜索
		if objName != "" && kind == "" {
			if !strings.Contains(item.InvolvedObject.Name, objName) {
				continue
			}
		}

		Items := &Events{
			EventType:  item.Type,
			Kind:       item.InvolvedObject.Kind,
			ObjName:    item.InvolvedObject.Name,
			Message:    item.Message,
			Reason:     item.Reason,
			CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		}
		bbb = append(bbb, *Items)
		//log.Println(item)
	}

	return bbb, err
}

二.路由设置

2.1.路由设置

将以下代码放到routers/route.go中

golang 复制代码
	//event
	beego.Router("/event/v1/List", &controllers.EventController{}, "*:List")

三.前端代码

5.1.列表部分html代码

3.1 eventList.html,放到views/front/page/xkube下

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>configmap列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="/lib/layui-v2.6.3/css/layui.css" media="all">
    <link rel="stylesheet" href="/css/public.css" media="all">
    <script type="text/javascript" src="/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script>
    <script src="/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
    <script src="/js/xkube.js?v=1" charset="utf-8"></script>
    <script src="/js/lay-config.js?v=1.0.4" charset="utf-8"></script>

<style type="text/css">
  .layui-table-cell {
    height: auto;
    line-height: 22px !important;
    text-overflow: inherit;
    overflow: visible;
    white-space: normal;
  }
  .layui-table-cell .layui-table-tool-panel li {
    word-break: break-word;
  }
</style>
</head>
<body>
<div class="layuimini-container">
    <div class="layuimini-main">
        <fieldset class="table-search-fieldset">
            <legend>搜索信息</legend>
            <div style="margin: 10px 10px 10px 10px">
                <form class="layui-form layui-form-pane" action="">
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">事件类型</label>
                            <div class="layui-input-inline">
                              <select name="kind">
          	              			<option value="warnning" selected="">warnning</option>
              		            </select>
                            </div>
                        </div>

                        <div class="layui-inline">
                            <label class="layui-form-label">对象</label>
                            <div class="layui-input-inline">
                              <select name="kind">
          	              			<option value="deployment" selected="">deployment</option>
          	              			<option value="daemonset">daemonset</option>
          	              			<option value="pod">pod</option>
          	              			<option value="job">job</option>                                                                
          	              			<option value="cronjob">cronjob</option>
              		            </select>
                            </div>
                        </div>

                        <div class="layui-inline">
                            <label class="layui-form-label">命名空间</label>
                            <div class="layui-input-inline">
                              <select name="nameSpace" id="nameSpace">
          	              			<option value="default" selected="">default</option>
          	              			<option value="">所有空间</option>
              		            </select>
                            </div>
                        </div>

                        <div class="layui-inline">
                            <button type="submit" class="layui-btn"  lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
                        </div>

                    </div>
                </form>
            </div>
        </fieldset>
        <table class="layui-table" id="currentTableId" lay-filter="currentTableFilter"></table>
    </div>
</div>
</body>
<script>
var clusterId = getQueryString("clusterId");
if (clusterId == null) {
	clusterId = getCookie("clusterId")
}
    layui.use(['form', 'table','miniTab'], function () {
        var $ = layui.jquery,
            form = layui.form,
            table = layui.table;
            miniTab = layui.miniTab,
            miniTab.listen();

        table.render({
            elem: '#currentTableId',
            url: '/event/v1/List?clusterId='+clusterId,
            toolbar: '#toolbarDemo',
            //initSort: {field:'createTime', type:'desc'},
            defaultToolbar: ['filter', 'exports', 'print', {
                title: '提示',
                layEvent: 'LAYTABLE_TIPS',
                icon: 'layui-icon-tips'
            }],
            parseData: function(res) { //实现加载全部数据后再分页
            	if(this.page.curr) {
            		result=res.data.slice(this.limit*(this.page.curr-1),this.limit*this.page.curr);
            	}else{
            	  result=res.data.slice(0,this.limit);
              }
              return {
              	"code": res.code,
              	"msg":'',
              	"count":res.count,
              	"data":result
              };
            },
            cols: [[
                //{type: "checkbox", width: 50},
                {field: 'eventType', width: 130,title: '类型', sort: true},
                {field: 'kind', width: 150,title: '对象', sort: true},
                {field: 'objName', width: 180,title: '名称', sort: true},                                
                {field: 'message',title: '消息', sort: true},
                {field: 'reason', title: '原因',width: 200, sort: true},
                {field: 'createTime', width:180, title: '创建时间'}
            ]],
            //size:'lg',
            limits: [25, 50, 100],
            limit: 25,
            page: true
        });
    });
</script>

</body>
</html>

四.完整代码

4.1.控制器event.go的完整代码

4.1 event.go,放到contrillers下

golang 复制代码
package controllers

import (
	//"encoding/json"
	"log"
	m "myk8s/models"

	beego "github.com/beego/beego/v2/server/web"
)

type EventController struct {
	beego.Controller
}

func (this *EventController) List() {
	clusterId := this.GetString("clusterId")
	namespace := this.GetString("nameSpace")
	kind := this.GetString("kind") //Pod/Namespace/Ingress/Service/Node/Configmap/Deployment/Stateful/Job/Cronjob/Secret可参考阿里云k8s事件中心类型
	objName := this.GetString("objName")
	limitd, _ := this.GetInt64("limit")
	List, err := m.EventList(clusterId, namespace, kind, objName, limitd)
	msg := "success"
	code := 0
	count := len(List)
	if err != nil {
		log.Println(err)
		msg = err.Error()
		code = -1
	}
	this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &List}
	//this.Data["json"] = &datas
	this.ServeJSON()
}
4.2.模型eventModel.go的完整代码

4.2 eventModel.go,放到models下

golang 复制代码
// eventModel.go
package models

import (
	"context"
	"fmt"

	//"time"
	"log"
	"myk8s/common"
	"sort"
	"strings"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Events struct {
	EventType  string `json:"eventType"` //事件类型 warnning
	Kind       string `json:"kind"`      //对象类型 pod or deployment
	ObjName    string `json:"objName"`   //对象:pod的名称
	Message    string `json:"message"`   //信息
	Reason     string `json:"reason"`    //原因、内容
	CreateTime string `json:"createTime"`
}

func EventList(kubeconfig, namespace, kind, objName string, limitd int64) ([]Events, error) {
	clientset := common.ClientSet(kubeconfig)
	var err error
	var events *corev1.EventList

	var listOptions = metav1.ListOptions{}
	if limitd > 0 {
		listOptions = metav1.ListOptions{
			Limit: limitd,
		}
	}

	if kind != "" && objName != "" {
		listOptions = metav1.ListOptions{
			FieldSelector: fmt.Sprintf("involvedObject.name=%s", objName),
			TypeMeta:      metav1.TypeMeta{Kind: fmt.Sprintf("%s", kind)},
		}
		events, err = clientset.CoreV1().Events(namespace).List(context.TODO(), listOptions)
	} else if kind != "" && objName == "" {
		listOptions = metav1.ListOptions{
			TypeMeta: metav1.TypeMeta{Kind: fmt.Sprintf("%s", kind)},
		}
		events, err = clientset.CoreV1().Events(namespace).List(context.TODO(), listOptions)
	} else {
		events, err = clientset.CoreV1().Events(namespace).List(context.TODO(), listOptions)
	}
	if err != nil {
		log.Printf("list deployment error, err:%v\n", err)
	}

	lessFunc := func(i, j int) bool {
		return events.Items[j].CreationTimestamp.Before(&events.Items[i].CreationTimestamp)
	}
	sort.SliceStable(events.Items, lessFunc)

	var bbb = make([]Events, 0)
	for _, item := range events.Items {

		if objName != "" && kind == "" {
			if !strings.Contains(item.InvolvedObject.Name, objName) {
				continue
			}
		}

		Items := &Events{
			EventType:  item.Type,
			Kind:       item.InvolvedObject.Kind,
			ObjName:    item.InvolvedObject.Name,
			Message:    item.Message,
			Reason:     item.Reason,
			CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		}
		bbb = append(bbb, *Items)
		//log.Println(item)
	}

	return bbb, err
}

五.效果图

相关推荐
月屯17 小时前
平台消息推送(go)
数据库·后端·golang·cocoa·iphone·gin
oneslide18 小时前
Kubernetes V1.24+ & Docker运行时 grafana容器指标显示异常
docker·kubernetes·grafana
终端行者18 小时前
k8s各种场景下排错思路以及命令 k8s常见问题故障处理思路
云原生·容器·kubernetes
百锦再1 天前
第11章 泛型、trait与生命周期
android·网络·人工智能·python·golang·rust·go
hweiyu001 天前
Go Fiber 简介
开发语言·后端·golang
victory04311 天前
K8S NFS 静态配置和动态配置 StorageClass
云原生·容器·kubernetes
运维 小白1 天前
k8s 部署NFS和动态供应器
云原生·容器·kubernetes
周杰伦_Jay1 天前
【智能体(Agent)技术深度解析】从架构到实现细节,核心是实现“感知环境→处理信息→决策行动→影响环境”的闭环
人工智能·机器学习·微服务·架构·golang·数据挖掘
hweiyu001 天前
Docker(K8S)容器架构教程(视频教程)
docker·架构·kubernetes
天使街23号1 天前
go-dongle v1.2.0 发布,新增 SM2 非对称椭圆曲线加密算法支持
开发语言·后端·golang