文章目录
简介
本章节主要讲解通过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
}