19.1 使用k8s的sdk编写一个项目获取pod和node信息

news2024/9/27 19:26:21

本节重点介绍 :

  • 引入k8s sdk获取k8s 的node和pod信息
    • 定义相关metrics
    • 初始化k8s-client
    • 使用k8s-client get node
    • 使用k8s-client get pod
    • 打点

k8s中关注四大块指标总结

  • 之前在k8s中关注4块指标有过总结
指标类型采集源应用举例发现类型grafana截图
容器基础资源指标kubelet 内置cadvisor metrics接口查看容器cpu、mem利用率等k8s_sd node级别直接访问node_ip容器基础资源
k8s对象资源指标kube-stats-metrics (简称ksm)具体可以看
看pod状态如pod waiting状态的原因
数个数如:查看node pod按namespace分布情况
通过coredns访问域名k8s对象资源指标
k8s服务组件指标服务组件 metrics接口查看apiserver 、scheduler、etc、coredns请求延迟等k8s_sd endpoint级别k8s服务组件指标
部署在pod中业务埋点指标pod 的metrics接口依据业务指标场景k8s_sd pod级别,访问pod ip的metricspath

使用golang引入sdk编写一个项目跑在k8s中

需求分析

  • 编写一个go的项目,引用k8s的sdk 获取节点信息,获取pod信息
  • 将获取到的信息通过prometheus sdk打点打出来
  • 编写dockerfile 将该项目打成镜像
  • 编写k8s 的yaml运行改项目
  • prometheus采集该项目的pod指标

新建项目 ink8s-pod-metrics

  • go 1.16以上,初始化项目
go mod init ink8s-pod-metrics

编写go代码

1. 定义相关metrics

const (
	namespace = "ink8s_pod_metrics"
	getNode   = "get_node"
	getPod    = "get_pod"
)

var (
    // 将每个node的信息打印出来
	k8sNodeDetail = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: prometheus.BuildFQName(namespace, getNode, "detail"),
		Help: "k8s node detail each",
	}, []string{"ip", "hostname", "containerRuntimeVersion", "kubeletVersion"})

    // 计算获取节点的耗时
	getNodeDuration = prometheus.NewGauge(prometheus.GaugeOpts{
		Name: prometheus.BuildFQName(namespace, getNode, "last_duration_seconds"),
		Help: "get node last duration seconds",
	})
     // 将每个控制平面的pod信息打印出来
	k8sPodDetail = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: prometheus.BuildFQName(namespace, getPod, "control_plane_pod_detail"),
		Help: "k8s pod detail of control plane",
	}, []string{"ip", "pod_name", "component"})
    // 计算获取pod的耗时
	getPodDuration = prometheus.NewGauge(prometheus.GaugeOpts{
		Name: prometheus.BuildFQName(namespace, getPod, "last_duration_seconds"),
		Help: "get pod last duration seconds",
	})
)

  • metrics讲解
    • k8sNodeDetail 将每个node的信息打印出来
    • getNodeDuration 计算获取节点的耗时
    • k8sPodDetail 将每个控制平面的pod信息打印出来
    • getPodDuration 计算获取pod的耗时
  • prometheus.BuildFQName(namespace, getNode, "detail") 代表使用共同前缀,namespace + subsystem

2. 注册metrics

func newMetrics() {
	prometheus.DefaultRegisterer.MustRegister(k8sNodeDetail)
	prometheus.DefaultRegisterer.MustRegister(k8sPodDetail)
	prometheus.DefaultRegisterer.MustRegister(getNodeDuration)
	prometheus.DefaultRegisterer.MustRegister(getPodDuration)
}

3. 初始化k8s-client

  • 使用包 “k8s.io/client-go/kubernetes”
  • 使用包 “k8s.io/client-go/rest”
  • 配合后面的serviceaccount +clusterrole+clusterrolebinding
  • 封装一个getK8sClient 方法

func getK8sClient() *kubernetes.Clientset {
	// creates the in-cluster config
	config, err := rest.InClusterConfig()
	if err != nil {
		logger.Errorf("[create_k8s_InClusterConfig_err][err:%v]", err)
		return nil
	}
	// creates the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		logger.Errorf("[create_the_clientset_error][err:%v]", err)
		return nil
	}
	return clientset
}

4. 使用k8s-client get node

  • clientset.CoreV1().Nodes().List代表 get node
  • 遍历nodes
    • 获取ip地址 p.Status.Addresses 中的类型为 apiv1.NodeInternalIP 就是内网ip
    • containerRuntimeVersion和kubeletVersion信息在 p.Status.NodeInfo中
  • 在结尾的时候打印个日志,记录下节点数和耗时,并把耗时打个metrics上报
  • 完整代码如下
func doGetNode() {
	start := time.Now()

	clientset := getK8sClient()
	if clientset == nil {
		return
	}

	nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		logger.Errorf("list_kube-system_pod_error:%v", err)
		return
	}

	if len(nodes.Items) == 0 {
		return
	}
	for _, p := range nodes.Items {
		var ip string
		addr := p.Status.Addresses
		if len(addr) == 0 {
			continue
		}

		for _, a := range addr {
			if a.Type == apiv1.NodeInternalIP {
				ip = a.Address
			}
		}

		k8sNodeDetail.With(prometheus.Labels{
			"ip":                      ip,
			"hostname":                p.Name,
			"containerRuntimeVersion": p.Status.NodeInfo.ContainerRuntimeVersion,
			"kubeletVersion":          p.Status.NodeInfo.KubeletVersion,
		}).Set(1)
	}
	timeTook := time.Since(start).Seconds()
	getNodeDuration.Set(timeTook)
	logger.Infof("server_node_ips_result][num_node:%v][time_took_seconds:%v]", len(nodes.Items), timeTook)

}

5. 使用k8s-client get pod

  • clientset.CoreV1().Pods("kube-system").List 代表获取kube-system namespace下面的pods

  • 遍历pods

    • 控制平面中的pod 都会有 tie=control-plane的标签
    • 打点即可
  • 完整代码如下

func doGetPod() {
	start := time.Now()
	clientset := getK8sClient()
	if clientset == nil {
		return
	}

	pods, err := clientset.CoreV1().Pods("kube-system").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		logger.Errorf("list_kube-system_pod_error:%v", err)
		return
	}

	if len(pods.Items) == 0 {
		return
	}
	for _, p := range pods.Items {
		logger.Infof("[pod.label:%v]", p.Labels)
		if p.Labels["tier"] == "control-plane" {
			ip := p.Status.PodIP
			component := p.Labels["component"]
			k8sPodDetail.With(prometheus.Labels{
				"ip":        ip,
				"pod_name":  p.Name,
				"component": component,
			}).Set(1)

		}
	}

	timeTook := time.Since(start).Seconds()
	getPodDuration.Set(timeTook)
	logger.Infof("server_pod_ips_result][num_pod:%v][time_took_seconds:%v]", len(pods.Items), timeTook)

}

6. 编写运行的ticker函数

  • 每隔10秒就执行一下getnode 和getpod上报数据
  • 外部的ctx被cancel会导致for退出
func getK8sObjTicker(ctx context.Context) {
	ticker := time.NewTicker(time.Second * 10)
	logger.Infof("GetK8sObjTicker start....")

	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			go doGetNode()
			go doGetPod()
		case <-ctx.Done():
			return
		}
	}

}

7. 编写main函数

  • newMetrics 注册metrics
  • go getK8sObjTicker(ctx) 开启获取 k8s对象的协程
  • http.Handle("/metrics", promhttp.Handler()) 开启prometheus metric path
func main() {
	// 注册metrics
	newMetrics()
	ctx := context.Background()
	// 开启获取 k8s对象的协程
	go getK8sObjTicker(ctx)
	// 开启prometheus metric path
	http.Handle("/metrics", promhttp.Handler())
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		logger.Errorf("failed to start prometheus metrics web :%v", err)
	}
}

本节重点总结 :

  • 引入k8s sdk获取k8s 的node和pod信息
    • 定义相关metrics
    • 初始化k8s-client
    • 使用k8s-client get node
    • 使用k8s-client get pod
    • 打点

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

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

相关文章

如何把pdf拆分成一页一页?推荐4个简单方便的拆分方法(内含详细教程)

如何把pdf拆分成一页一页&#xff1f;对于现在的职场来说&#xff0c;想要编辑pdf格式文件还是蛮简单的。PDF文档早就成为了我们日常办公中信息传递与存储的核心载体&#xff0c;因此对于编辑pdf的需求是越来越多了。 关于如何编辑pdf文件&#xff0c;市面上提供了很多方法和软…

七大机器学习常用库一次讲清楚(TensorFlow|Scikit-Learn|NumPy|Keras|PyTorch|LightGBM||NLTK)

机器学习的研究和学习必须使用Python开发库&#xff0c;面对很多个机器学习的Python库或者框架&#xff0c;我们是不是傻傻的分不清&#xff0c;这个那个到底是做什么&#xff0c;什么时候用这个&#xff0c;什么时候用那个&#xff0c;他们各自的优势劣势都有哪些&#xff0c;…

smb文件夹共享设置

UOS统信三种不同场景的文件夹共享,分别是:1、UOS系统间的文件共享;2、Windows7系统访问UOS共享的文件;3、UOS系统访问Windows7共享的文件 文章目录 第二种场景:Windows7系统访问UOS共享的文件步骤一:设置共享密码步骤二:输入共享IP地址步骤三:输入网络密码步骤四:共享…

RabbitMQ高级特性-发送方确认

对于发送方发送消息到RabbitMQ的可靠性机制 引入&#xff1a;在持久化的消息正确存⼊RabbitMQ之后,还需要有⼀段时间(虽然很短,但是不可忽视)才能存⼊磁盘中.RabbitMQ并不会为每条消息都进⾏同步存盘(调⽤内核的fsync⽅法)的处理, 可能仅仅保存到操作系统缓存之中⽽不是物理磁…

Vue3 + element-plus el-table二次封装组件新增虚拟滚动功能

1、此功能已集成到TTable组件 和TSelectTable 2、最终效果&#xff08;基于element-plus 的 el-table组件&#xff09; 3、TTable或TSelectTable组件使用&#xff08;只需要在标签中设置useVirtual即可&#xff09; 4、源码&#xff08;可以提取当做hooks方式来使用–具体看组…

工作笔记【四】

对于这种&#xff0c;样式一样&#xff0c;但是图片和字体颜色不一样&#xff0c;动态渲染。 代码&#xff1a; <template><view class"page"><view class"rows" v-for"item in data"><view class"v0"><v…

云桌面+数字人:开启直播新纪元

随着科技的飞速发展&#xff0c;直播行业也在不断变革。云桌面和数字人直播作为新兴力量&#xff0c;正逐渐崭露头角&#xff0c;受到了广泛关注。 云桌面技术的出现&#xff0c;为直播带来了全新的可能性。它不再依赖传统的本地硬件设备&#xff0c;而是通过云计算提供弹性可…

Abaqus:一款强大的非线性分析软件

Abaqus是一款由达索系统公司开发的工程仿真软件&#xff0c;它提供了广泛的解决方案来解决各种复杂的工程问题。从2016版本到2018版本&#xff0c;Abaqus安装包中包含了多种辅助工具&#xff0c;如Fe-safe疲劳分析软件、Tosca结构优化软件以及Isight多学科优化平台等&#xff0…

长效静态IP代理详解:稳定网络访问的保障

在这个信息爆炸的时代&#xff0c;网络安全和隐私保护变得尤为重要。无论是个人用户还是企业&#xff0c;都希望在网络上能够畅行无阻而不被追踪。而长效静态IP代理&#xff0c;正是这个隐形守护者&#xff0c;让你在网络世界中如鱼得水。本文将深入探讨长效静态IP代理的各个方…

python爬虫:将知乎专栏文章转为pdf

欢迎关注本人的知乎主页~ 实现思路 用户输入专栏ID&#xff1a; 代码首先提示用户输入一个知乎专栏的ID&#xff0c;默认值为 c_1747690982282477569。输入的ID用于构建API请求的URL。 发送HTTP请求&#xff1a; 使用 requests.get() 向知乎API发送GET请求&#xff0c;获取指定…

C:数据在内存中的存储

目录 一、整数在内存中的存储 二、大小端字节序 2.1 大小端字节序的介绍 2.2 为什么有大小端之分&#xff08;了解即可&#xff09; 2.3 判断大小端的代码实现 三、浮点数的数据存储 3.1 浮点数的存储 3.2 浮点数存储的过程 3.2.1 对于有效数字M 3.2.1 对于指数E 3.3…

硕博论文写作如何完成一篇符合学术诚信的优秀论文

撰写硕博论文是每个研究生必打的一场硬仗&#xff0c;而学术诚信也是作为撰写论文的重要考验&#xff0c;那么&#xff0c;我们如何撰写一篇符合学术诚信的硕博论文呢&#xff1f; 一、选好题 一个好的题目是写作的第一步&#xff0c;也是决定论文质量的关键。一个好的题目应…

OJ在线评测系统 将代码沙箱开放为API

代码沙箱开放API 这一步非常简单 就是提供公共方法 引入代码沙箱的具体实现 /*** 执行代码** param executeCodeRequest* return*/PostMapping("/executeCode")ExecuteCodeResponse executeCode(RequestBody ExecuteCodeRequest executeCodeRequest, HttpServletRe…

kibana开启访问登录认证

编辑es配置文件&#xff0c;添加以下内容开启es认证 vim /etc/elasticsearch/elasticsearch.yml http.cors.enabled: true http.cors.allow-origin: "*" http.cors.allow-headers: Authorization xpack.security.enabled: true xpack.security.transport.ssl.enable…

小米 13 Ultra机型工程固件 资源预览与刷写说明 步骤解析

小米 13 Ultra机型---机型代码为ishtar 。工程固件可以辅助修复格机或者全檫除分区后的基带修复。可以用于修复TEE损坏。以及一些分区的底层修复。此款固件也可以为更换UFS后的底包。 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2💝💝💝-----此…

外包干了1个多月,技术明显退步了。。。。。

回望过去&#xff0c;我是一名普通的本科生&#xff0c;2019年有幸通过校园招聘踏入了广州一家软件公司的大门&#xff0c;成为了一名功能测试工程师。岁月如梭&#xff0c;转眼间&#xff0c;我已在这个岗位上默默耕耘了近四年。起初&#xff0c;我对这份工作充满了热情与期待…

学习之什么是迭代器

什么是迭代器 迭代器的作用&#xff1a;访问容器中的元素 首先要了解什么是Iterablelterable(可迭代的) 字符串、列表、元组、字典都是lterable&#xff0c;都可以放到for循环语句中遍历 lterable类型的定义中一定有一个_iter_方法iter 方法必须返回一个lterator(迭代器) 可以…

如何进行USB外设管控?三款USB接口管控软件推荐

随着USB设备的普及&#xff0c;USB外设的管理和控制成为企业信息安全的重要环节。 不当的USB使用可能导致数据泄露、恶意软件传播等风险。 因此&#xff0c;进行有效的USB外设管控对于维护企业信息安全至关重要。 小编在本文将为您介绍如何进行USB外设管控&#xff0c;并推荐…

ASCII Unicode UTF-8 字符集 字符编码

ASCII Unicode UTF-8 字符集 字符编码 基本概念字符字符集字符编码 字符集和字符编码ASCII 字符集Unicode 字符集UTF-8 附录 基本概念 字符集为每个字符分配了一个唯一的编号&#xff0c;通过这个编号就能找到对应的字符。在编码过程中我们经常会使用字符&#xff0c;而使用字…

9.5 Linux_I/O_静态库与动态库

库 什么是库&#xff1a; 库是一个二进制文件&#xff0c;包含的代码可用被程序调用。常见的库有标准C库、数学库、线程库。 调用库的方式有两种&#xff1a; 使用库的源码&#xff0c;下载后编译直接安装库的二进制包 在Linux下&#xff0c;库存放在/lib 和 /usr/lib 目录…