go语言-k8s宿主信息采集运维脚本

背景

由于工作需要,需要采集k8s集群中的宿主相关信息,包括cpu,memory,lvm,标签等信息。通常作为SRE会主选shell或python脚本来实现。但最近我们团队主流开发语言已经切换到golang.所以本次尝试用go语言来写写运维脚本。

实现流程图

代码实现

package main

import (
	"errors"
	"fmt"
	"github.com/gocarina/gocsv"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
)

// K8SNode 描述宿主节点
type K8SNode struct {
	IP           string `csv:"ip"`
	CPUSize      string `csv:"cpu_size"`
	MemorySize   string `csv:"memory_size"`
	LVMSize      string `csv:"lvm_size"`
	VMINum       int    `csv:"vmi_num"` // 虚拟机个数
	ProjectLabel string `csv:"project_label"`
}

// NodeDescribeOutput 执行kubectl describe node 指定ip后面的输出内容
func NodeDescribeOutput(ip string) (string, error) {
	cmd := "kubectl  describe node " + ip
	log.Printf("execut command: %s\n", cmd)
	output, err := ExecCmd(cmd)
	if err != nil {
		log.Println("err:", err)
		return "", err
	}
	return output, nil
}

// CpuSize 获取节点cpu
func CPUSize(describeInfo string) (string, error) {

	describeInfoList := strings.Split(describeInfo, "\n")
	for _, line := range describeInfoList {
		if strings.Contains(line, "cpu:") {
			cpusizelist := strings.Split(line, ":")
			//log.Printf("cpusize: %s", cpusizelist[1])
			size := strings.Replace(cpusizelist[1], " ", "", -1)
			return size, nil
		}
	}
	return "", errors.New("not found cpu size.")
}

// MemorySize 获取节点内存大小
func MemorySize(describeInfo string) (string, error) {

	describeInfoList := strings.Split(describeInfo, "\n")
	for _, line := range describeInfoList {
		if strings.Contains(line, "memory:") {
			memorysizelist := strings.Split(line, ":")
			size := strings.Replace(memorysizelist[1], " ", "", -1)
			return size, nil
		}
	}
	return "", errors.New("not found memory size.")
}

// LVMSize 获取节点本地磁盘大小
func LVMSize(describeInfo string) (string, error) {

	describeInfoList := strings.Split(describeInfo, "\n")
	for _, line := range describeInfoList {
		if strings.Contains(line, "lvm:") {
			sizelist := strings.Split(line, ":")
			size := strings.Replace(sizelist[1], " ", "", -1)
			return size, nil
		}
	}
	return "", errors.New("not found memory size.")
}

// VMINum 统计节点已经允许vmi的数量(vmi表示在k8s+kubevirt中KVM对应的对象)
func VMINum(describeInfo string) (int, error) {

	describeInfoList := strings.Split(describeInfo, "\n")
	var count int
	for _, line := range describeInfoList {
		if strings.Contains(line, "irt-launcher-") {
			count++
		}
	}
	return count, nil
}

// ProjectLabel 获取节点项目标签[我们业务定义project表示宿主用于哪一个项目]
func ProjectLabel(describeInfo string) (string, error) {

	describeInfoList := strings.Split(describeInfo, "\n")
	for _, line := range describeInfoList {
		if strings.Contains(line, "project=") {
			//log.Printf("cpusize: %s", cpusizelist[1])
			label := strings.Replace(line, " ", "", -1)
			label = strings.Replace(label, "project=", "", -1)
			label = strings.Replace(label, "\n", "", -1)
			return label, nil
		}
	}
	return "", errors.New("not found project label.")
}

// ExecCmd 对exec.Command()的封装
func ExecCmd(cmdstr string) (string, error) {

	cmd := exec.Command("bash", "-c", cmdstr)
	res, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(res), nil

}

// GetIPList 获取集群中节点对应的IP列表
func GetIPList() []string {

	cmd := "kubectl get  node |grep -E \"[0-9]\" |awk '{print $1}'"
	log.Printf("execut command: %s\n", cmd)
	output, err := ExecCmd(cmd)
	if err != nil {
		log.Println("err:", err)
		var nilIPList []string
		return nilIPList
	}
	return strings.Split(string(output), "\n")
}

// 将结构体切片转换为csv文件
func WriteToCsv(filename string, nodes []*K8SNode) {
	// 创建csv文件
	os.Chdir("/tmp")
	nodesFile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
	if err != nil {
		panic(err)
	}
	defer nodesFile.Close()

	// 将结构体切片转换为csv文件
	if err := gocsv.Marshal(&nodes, nodesFile); err != nil { // Load clients from file
		panic(err)
	}
}

// uploadToFilesever 将文件通过scp命令传到文件服务器
func uploadToFilesever(filename string) error {
	cmd := "scp " + filename + " 172.17.123.89:/home/segops/app/nginx/data/tmp/"
	log.Printf("execut command: %s\n", cmd)
	_, err := ExecCmd(cmd)
	if err != nil {
		log.Println("err:", err)
		return err
	}
	return nil
}

func main() {

	// Nodes 保存节点的切片
	var Nodes = []*K8SNode{}
	// count 用于统计节点数量
	var count int

	ipList := GetIPList()
	// 依次处理每一个宿主节点IP
	for _, ip := range ipList {
		//fmt.Println(ip)
		if ip == "" {
			continue
		}
		count++
		var oneNode = &K8SNode{}
		oneNode.IP = ip

		describeNodeOutput, err := NodeDescribeOutput(ip)
		if err != nil {
			log.Printf("%s NodeDescribeOutput error.\n", ip)
		}

		cpusize, err := CPUSize(describeNodeOutput)
		if err == nil {
			oneNode.CPUSize = cpusize
		} else {
			oneNode.CPUSize = ""
		}

		memsize, err := MemorySize(describeNodeOutput)
		if err == nil {
			oneNode.MemorySize = memsize
		} else {
			oneNode.MemorySize = ""
		}

		lvmsize, err := LVMSize(describeNodeOutput)
		if err == nil {
			oneNode.LVMSize = lvmsize
		} else {
			oneNode.LVMSize = ""
		}

		vminum, err := VMINum(describeNodeOutput)
		if err == nil {
			oneNode.VMINum = vminum
		} else {
			oneNode.VMINum = -1
		}

		projectlabel, err := ProjectLabel(describeNodeOutput)
		if err == nil {
			oneNode.ProjectLabel = projectlabel
		} else {
			oneNode.ProjectLabel = ""
		}
		fmt.Printf("%v\n", oneNode)
		//log.Println(ProjectLabel(describeNodeOutput))

		// 将一个K8SNode对象加入切片
		Nodes = append(Nodes, oneNode)
	}
	//fmt.Println("nodemap=%v", nodeMap)
	fmt.Printf("===========================================================================================\n")
	fmt.Printf("=========================================统计结果===========================================\n")
	fmt.Printf("===========================================================================================\n")
	fmt.Printf("ip\t\tcpu\t\tmemory\t\tlvmsize\t\tvminum\t\tprojectlabel\n")
	for _, node := range Nodes {
		fmt.Printf("%s\t%s\t\t%s\t%s\t\t%d\t\t%s\n", node.IP, node.CPUSize, node.MemorySize, node.LVMSize, node.VMINum, node.ProjectLabel)
	}
	fmt.Println()
	fmt.Printf("node num is %d\n", count)

	fmt.Println()
	fmt.Println("write to csv file:")
	currentTime := time.Now().Format("20060102150405")
	hostname, _ := os.Hostname()
	csvfilename := hostname + "_" + "nodesinfo" + "_" + currentTime + ".csv"

	// 写入csv文件
	WriteToCsv(csvfilename, Nodes)

	// 上传到文件服务器
	err := uploadToFilesever(csvfilename)
	if err != nil {
		fmt.Println("upload csv file error.")
		return
	}

	// 定义下载文件的路径
	downloadPath := "http://172.17.123.89:8080/tmp/" + csvfilename

	fmt.Println()
	fmt.Println("csv file can download from: ", downloadPath)
	fmt.Println()
}

实现结果

​
17:35:14  ===========================================================================================
17:35:14  =========================================统计结果===========================================
17:35:14  ===========================================================================================
17:35:14  ip		cpu		memory		lvmsize		vminum		projectlabel
17:35:14  172.24.52.11	96		394687572Ki	4862Gi		7		personal-dev
17:35:14  172.24.52.12	96		394687572Ki	4862Gi		8		personal-dev
17:35:14  172.24.52.13	96		394682812Ki	4862Gi		2		personal-dev
17:35:14  172.24.52.14	96		394687572Ki	4862Gi		5		personal-dev
17:35:14  172.24.52.141	96		394687572Ki	4862Gi		1		tools
17:35:14  172.24.52.142	96		394687572Ki	4862Gi		0		personal-dev-unuse
17:35:14  172.24.52.143	96		394687572Ki	4862Gi		0		personal-dev-unuse
17:35:14  172.24.53.79	80		394679084Ki	3225Gi		0		unuse
17:35:14  172.24.53.93	72		131267356Ki	11431Gi		0		unuse
17:35:14  172.24.53.94	72		131267356Ki	11431Gi		0		unuse
17:35:14  
17:35:14  node num is 122
17:35:14  
17:35:14  write to csv file:
17:35:14  2024/03/07 17:35:14 execut command: scp hyd01-seg-admin01_nodesinfo_20240307173514.csv 172.17.123.89:/home/segops/app/nginx/data/tmp/
17:35:15  
17:35:15  csv file can download from:  http://172.17.123.89:8080/tmp/hyd01-seg-admin01_nodesinfo_20240307173514.csv

​

 

总结

用go脚本写了约300行,并不简洁。所以在工作实际中,如果写一些逻辑简单的脚本建议首选用shell或python。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[笔记]Crash Course Computer Science

二进制 byte 在电脑中的单位换算: kilobyte 千字节 megabyte 兆字节 gigabyte 千兆字节 1kb210bit 1024byte 1000b 1Mb 220bit 1024kb 1Gb 230bit 1TB1000GB 1GB十亿字节1000MB10^6KB Gb 和 GB 一般而言GB用于文件,Gb用于通信。B代表Byte&…

类与对象(三)--static成员、友元

文章目录 1.static成员1.1概念🎧面试题✒️1.2static的特性🎧1.3思考🎧 2.友元2.1什么是友元?🎧2.2两种友元关系:🎧 1.static成员 1.1概念🎧 🔎 static关键字用于声明类…

SpringCloudAlibaba微服务之Nacos架构及基础概念梳理

SpringCloudAlibaba微服务之Nacos架构及基础概念梳理 文章目录 SpringCloudAlibaba微服务之Nacos架构及基础概念梳理1. 官网介绍1. 简介2. Naocs是什么3. Nacos 地图4. Nacos 生态图 2. Nacos 架构1. 基本架构及概念1. 服务 (Service)2. 服务注册中心 (Service Registry)3. 服务…

第四届信息通信与软件工程国际会议(ICICSE 2024)即将召开!

2024年第四届信息通信与软件工程国际会议(ICICSE 2024)将于2024年5月10-12日在中国北京举办。本次会议由北京工业大学、IEEE以及Comsoc 联合主办。随着当今社会信息化的高速发展,电子信息技术的应用更是随处可见。其中,信息通信与…

K倍区间(蓝桥杯)

文章目录 K倍区间题目描述前缀和数学优化代码部分解释 K倍区间 题目描述 给定一个长度为 N的数列,A1,A2,…AN,如果其中一段连续的子序列 Ai,Ai1,…Aj 之和是 K的倍数,我们就称这个区间 [i,j]是 K倍区间。 你能求出数列中总共有多少个 K倍区…

Zabbix(四)

Zabbix Proxy zabbix作为一个分布式监控系统(分布式监控解决方案),支持通过代理(proxy)收集zabbix agent的监控数据,然后由zabbix proxy再把数据发送给zabbix server,也就是zabbix proxy 可以代替zabbix server收集监控数据,然后…

Mybatis-Spring | Mybatis与Spring的“整合“

目录 : 一、配置环境1. 整合环境需导入的JAR :Spring框架所需JARMybatis框架所需JARMyBatis与Spring整合的中间JAR数据库驱动JAR包数据源所需JAR包 (下面的例子中 : 用的不是这个数据源) 2. 编写“配置文件” 和 “.properties文件” ( 只是概述&#xf…

电磁铁通电后测不到磁场是什么原因

电磁铁 电磁铁没有磁力的一般原因有多种,以下是一些常见原因: 1. 电源问题:电磁铁没有连接好电源或电源电压不足,无法产生足够强的磁场。电磁铁所需要的电流和电压应符合制造商的规定。另外的话,电源接头也需要注意接…

SAP 消息编号 M8147

月末执行物料分类账的时候,出现以下报错 解决方法:OBYC-PRM

Linux运维:实现光盘开机自动挂载、配置本地yum源教程

Linux运维:实现光盘开机自动挂载、配置本地yum源教程 一、光盘开机自动挂载1、检查光驱设备2、创建挂载点3、编辑/etc/fstab文件4、测试挂载 二、配置本地yum源(挂载光盘或ISO文件)1、挂载ISO文件2、创建YUM仓库配置文件3、清理YUM缓存并测试 💖The Begi…

萌新小白对于ctf学习的笔记--CTF中的RCE

概念 RCE(Remote code execution)远程代码执行漏洞,RCE又分命令执行和代码执行。 RCE-远程代码执行:远程执行PHP代码RCE-远程命令执行:远程执行Linux或者Windows等系统命令。 常见函数有: PHP:eval(),a…

解决syslog服务器启动问题

Syslog 监控和管理对于每个组织来说都很重要,可以减少系统停机时间、提高网络性能并加强企业的安全策略。而在网络系统管理中,syslog服务用于收集、存储和管理系统和设备的日志信息。 然而,有时候我们可能会遇到syslog服务器无法启动的问题&…

mysql中 COALESCE和CASE WHEN的使用以及创建或替换视图

create or replace view 自理能力评估视图 as SELECT ehr_zlnlpg.ID AS ID, ehr_zlnlpg.GRID AS GRID, ehr_zlnlpg.TJID AS TJID, ehr_grjbxx.Name AS 姓名, ehr_grjbxx.Sex AS 性别, ehr_grjbxx.Cardnum AS 身份证号, ehr_zlnlpg.SCORESUM AS 总…

[每周一更]-第90期:认识Intel的CPU

市面上的CPU分类主要分有两大阵营,一个是Intel、AMD为首的复杂指令集CPU,另一个是以IBM、ARM为首的精简指令集CPU。 两个不同品牌的CPU,其产品的架构也不相同,例如,Intel、AMD的CPU是X86架构的,而IBM公司的…

基于java+springboot+vue实现的校园悬赏任务平台(文末源码+Lw)23-277

摘 要 使用旧方法对校园悬赏任务平台的信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在校园悬赏任务平台的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。这次开发的…

STM32 | Proteus 8.6安装步骤(图文并茂)

01 Proteus 8.6 简介 Proteus 8.6 是一款功能强大的电子设计自动化软件,广泛用于电路设计、仿真和PCB布局。它为电子工程师和学生提供了一个全面的工具集,用于设计和验证各种电路和电子设备。Proteus 8.6 包括了以下几个主要特性: 1. 电路设…

云计算 3月8号 (WEB服务及Apache 服务的搭建与配置——基于域名 端口 Ip多方式访问)

1、WEB服务简介 # 目前最主流的三个Web服务器是Apache、Nginx、 IIS。 - WEB服务器一般指网站服务器,可以向浏览器等Web客户端提供网站的访问,让全世界浏览。 - WEB服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务。 …

【lua】lua内存优化记录

这边有一个Unity项目用的tolua, 游戏运行后手机上lua内存占用 基本要到 189M, 之前峰值有200多。 优化点1 加快gc频度: 用uwa抓取的lua内存, 和unity的mono很像,内存会先涨 然后突然gc一下,降下来。 这样…

S4---FPGA-K7板级原理图硬件实战

视频链接 FPGA-K7板级系统硬件实战01_哔哩哔哩_bilibili FPGA-K7板级原理图硬件实战 基于XC7K325TFFG900的FPGA硬件实战框图 基于XILINX 的KINTEX-7 芯片XC7K325FPGA的硬件平台,FPGA 开发板挂载了4 片512MB 的高速DDR3 SDRAM 芯片,另外板上带有一个SODIM…

RabbitMQ的Windows版安装教程

文章目录 前言一、Windows安装RabbitMQ总结 前言 曾经写过一篇关于RabbitMQ的Ubuntu安装教程(http://t.csdnimg.cn/5CYfC),当时使用的是Docker将RabbitMQ安装到虚拟机上,但是有很多小伙伴问Windows上如何进行安装RabbitMQ&#x…
最新文章