简介

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

一.k8s读取k8s事件

1.1.controllers控制器代码

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

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

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中

	//event
	beego.Router("/event/v1/List", &controllers.EventController{}, "*:List")

三.前端代码

5.1.列表部分html代码

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

<!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下

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下

// 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
}

五.效果图

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐