当前位置: 首页 > news >正文

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

本节重点介绍 :

  • 引入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 configconfig, err := rest.InClusterConfig()if err != nil {logger.Errorf("[create_k8s_InClusterConfig_err][err:%v]", err)return nil}// creates the clientsetclientset, 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 stringaddr := p.Status.Addressesif 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.PodIPcomponent := 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() {// 注册metricsnewMetrics()ctx := context.Background()// 开启获取 k8s对象的协程go getK8sObjTicker(ctx)// 开启prometheus metric pathhttp.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.mrgr.cn/news/36815.html

相关文章:

  • 小红书,努力成为小红书
  • UCS与Unicode:二虎相争,必有一伤?
  • 数字化AI直播革命:无人直播新纪元,真AI赋能未来!
  • 如何在 Android 中用 Kotlin 将 dp 转换为 px
  • Unity网络开发记录(一):实现最简单的unity客户端和服务器通信
  • Spring Boot框架在甘肃非遗文化网站设计中的运用
  • DCGAN生成人脸图片
  • (已解决)torch.load的时候发生错误ModuleNotFoundError: No module named ‘models‘
  • 负载箱在各领域的作用
  • 12.系统架构分析师应该懂的项目管理知识
  • 刷题学习日记 (1) - SWPUCTF
  • MAXON燃烧备件适用于哪些工业领域和燃烧系统
  • Windows系统下批量重命名文件的两种实现方法
  • 什么是大语言模型,一句话解释
  • 软件测试标准流程(思维导图版)
  • K8s Calico替换为Cilium,以及安装Cilium过程(鲁莽版)
  • vscode【实用插件】Markdown Preview Enhanced 预览 .md 文件
  • HarmonyOS NEXT 全面升级:华为引领智能生态的未来
  • su 命令:一键切换用户身份、提高su命令安全性的建议
  • 《数据结构与算法之美》学习笔记五之队列