解决 Prometheus 不能获取 Kubernetes 集群上 Windows 节点的 Metrics
背景
接上一篇 快速搭建 Windows Kubernetes , 我们发现原来在 Windows Kubernetes 会有一些与在 Linux 上使用不一样的体验,俗称坑,例如 hostAliases。对于我们希望真的把 Windows 放入生产,感觉除了基本的 Pod、Volume、Service 、Log 以外,我们还需要监控。一般来讲我们会用 Prometheus 来做监控,然后通过 Grafana 来展示,但是 Prometheus 的 Node Exporter 是为 *nix 设计的,所以在 Windows 上我们的自己想办法了。在 Prometheus Node Exporter 里推荐使用 WMI exporter ,感兴趣的童鞋可以去试试,本文主要还是想从一个原始的角度去分析处理,来理解怎么去写一个 Prometheus 的采集程序。
前提
- 一套 Windows Kuberentes
- 一个 Prometheus 环境
步骤
- 首先得找到 Kubelet 在 Windows 上暴露出来得数据格式, 因为 cadivsor 并不支持 Windows,  社区有位同志写了一个相对简单的实现来支持; 他这个的实现还是保持 Linux 上的一样,是从 <Node_IP>:10255/stats/summary上 expose metrics, metrics-server 与kubectl top的数据也是来源于此,大致如下:
{
  "node": {
   "nodeName": "35598k8s9001",
   "startTime": "2018-08-26T07:25:08Z",
   "cpu": {
    "time": "2018-09-10T01:44:52Z",
    "usageCoreNanoSeconds": 8532520000000
   },
   "memory": {
    "time": "2018-09-10T01:44:52Z",
    "availableBytes": 14297423872,
    "usageBytes": 1978798080,
    "workingSetBytes": 734490624,
    "rssBytes": 0,
    "pageFaults": 0,
    "majorPageFaults": 0
   },
   "fs": {
    "time": "2018-09-10T01:44:52Z",
    "availableBytes": 15829303296,
    "capacityBytes": 32212250624,
    "usedBytes": 16382947328
   },
   "runtime": {
    "imageFs": {
     "time": "2018-09-10T01:44:53Z",
     "availableBytes": 15829303296,
     "capacityBytes": 32212250624,
     "usedBytes": 16382947328,
     "inodesUsed": 0
    }
   }
  },
  "pods": [
   {
    "podRef": {
     "name": "stdlogserverwin-5fbcc5648d-ztqsq",
     "namespace": "default",
     "uid": "f461a0b4-ab36-11e8-93c4-0017fa0362de"
    },
    "startTime": "2018-08-29T02:55:15Z",
    "containers": [
     {
      "name": "stdlogserverwin",
      "startTime": "2018-08-29T02:56:24Z",
      "cpu": {
       "time": "2018-09-10T01:44:54Z",
       "usageCoreNanoSeconds": 749578125000
      },
      "memory": {
       "time": "2018-09-10T01:44:54Z",
       "workingSetBytes": 83255296
      },
      "rootfs": {
       "time": "2018-09-10T01:44:54Z",
       "availableBytes": 15829303296,
       "capacityBytes": 32212250624,
       "usedBytes": 0
      },
      "logs": {
       "time": "2018-09-10T01:44:53Z",
       "availableBytes": 15829303296,
       "capacityBytes": 32212250624,
       "usedBytes": 16382947328,
       "inodesUsed": 0
      },
      "userDefinedMetrics": null
     }
    ],
    "cpu": {
     "time": "2018-08-29T02:56:24Z",
     "usageNanoCores": 0,
     "usageCoreNanoSeconds": 749578125000
    },
    "memory": {
     "time": "2018-09-10T01:44:54Z",
     "availableBytes": 0,
     "usageBytes": 0,
     "workingSetBytes": 83255296,
     "rssBytes": 0,
     "pageFaults": 0,
     "majorPageFaults": 0
    },
    "volume": [
     {
      "time": "2018-08-29T02:55:16Z",
      "availableBytes": 17378648064,
      "capacityBytes": 32212250624,
      "usedBytes": 14833602560,
      "inodesFree": 0,
      "inodes": 0,
      "inodesUsed": 0,
      "name": "default-token-wv5fc"
     }
    ],
    "ephemeral-storage": {
     "time": "2018-09-10T01:44:54Z",
     "availableBytes": 15829303296,
     "capacityBytes": 32212250624,
     "usedBytes": 16382947328
    }
   }
  ]
}
- 从上面可以看到,它包含了本机和 pod 的一些 metrics, 相对 cadvisor 能提供的少了一些,但是基本监控是没问题的。接下来我们需要写一个小程序把数据转换成 Prometheus 能解析的数据。接下来用 python 写个小栗子, 先声明下我们要 expose 的 stats 对象
class Node:
    def __init__(self, name, cpu, memory):
        self.name = name
        self.cpu = cpu
        self.memory = memory
class Pod:
    def __init__(self, name, namespace,cpu, memory):
        self.name = name
        self.namespace = namespace
        self.cpu = cpu
        self.memory = memory
class Stats:
    def __init__(self, node, pods):
        self.node = node
        self.pods = pods
- 使用 Prometheus 的 python-client 来写一个 polling 的程序,去转换 kubelet stats 数据。
from urllib.request import urlopen
from stats import Node
from stats import Pod
from stats import Stats
import json
import asyncio
import prometheus_client as prom
import logging
import random
def getMetrics(url):
    #获取数据集
    response = urlopen(url)
    string = response.read().decode('utf-8')
    json_obj = json.loads(string)
    #用之前定义好的 stats 的对象来做 mapping
    node = Node('','','')
    node.name = json_obj['node']['nodeName']
    node.cpu = json_obj['node']['cpu']['usageCoreNanoSeconds']
    node.memory = json_obj['node']['memory']['usageBytes']
    pods_array = json_obj['pods']
    pods_list = []
    for item in pods_array:
        pod = Pod('','','','')
        pod.name = item['podRef']['name']
        pod.namespace = item['podRef']['namespace']
        pod.cpu = item['cpu']['usageCoreNanoSeconds']
        pod.memory = item['memory']['workingSetBytes']
        pods_list.append(pod)
    stats = Stats('','')
    stats.node = node
    stats.pods = pods_list
    return stats
#写个简单的日志输出格式
format = "%(asctime)s - %(levelname)s [%(name)s] %(threadName)s %(message)s"
logging.basicConfig(level=logging.INFO, format=format)
#声明我们需要导出的 metrics 及对应的  label 供未来查询使用
g1 = prom.Gauge('node_cpu_usageCoreNanoSeconds', 'CPU useage of the node', labelnames=['node_name'])
g2 = prom.Gauge('node_mem_usageBytes', 'Memory useage of the node', labelnames=['node_name'])
g3 = prom.Gauge('pod_cpu_usageCoreNanoSeconds', 'Memory useage of the node', labelnames=['pod_name','pod_namespace'])
g4 = prom.Gauge('pod_mem_usageBytes', 'Memory useage of the node', labelnames=['pod_name','pod_namespace'])
async def expose_stats(url):
    while True:
        stats = getMetrics(url)
        #以打印 node 本身的监控信息为例
        logging.info("nodename: {} value {}".format(stats.node.name, stats.node.cpu))
        # 为当前要 poll 的 metrics 赋值
        g1.labels(node_name=stats.node.name).set(stats.node.cpu)
        g2.labels(node_name=stats.node.name).set(stats.node.memory)
        pods_array = stats.pods
        for item in pods_array:
            g3.labels(pod_name=item.name,pod_namespace=item.namespace).set(item.memory)
            g4.labels(pod_name=item.name,pod_namespace=item.namespace).set(item.cpu)
        await asyncio.sleep(1)
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    # 启动一个 http server 来做 polling
    prom.start_http_server(8000)
    t0_value = 50
    #可以在每一台 Windows 机器上都启动一个这样的程序,也可以远程部署脚本来做 exposing
    url = 'http://localhost:10255/stats/summary'
    tasks = [loop.create_task(expose_stats(url))]
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        loop.close()
- 写完以后就可以启动这个程序了,访问他的 8000 端口就能看到相关的数据

- 接下来需要在 prometheus 里加入配置,增加一个收集对象,如下例:
- job_name: python_app
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /
  scheme: http
  static_configs:
  - targets:
    - localhost:8000
- 这样在 Prometheus 的页面上能查询到相关的信息了

提问												
											解决 Prometheus 不能获取 Kubernetes 集群上 Windows 节点的 Metrics的更多相关文章
	
								- Prometheus 监控外部 Kubernetes 集群
		转载自:https://www.qikqiak.com/post/monitor-external-k8s-on-prometheus/ 在实际环境中很多企业是将 Prometheus 单独部署在集群 ... 
- 解决项目迁移至Kubernetes集群中的代理问题
		解决项目迁移至Kubernetes集群中的代理问题 随着Kubernetes技术的日益成熟,越来越多的企业选择用Kubernetes集群来管理项目.新项目还好,可以选择合适的集群规模从零开始构建项目: ... 
- kubernetes 集群添加node节点
		kubernetes 集群添加node节点 注意,我们并不需要把新增的node ip加入到证书里重新生成!!! 下面我们以添加node03为例 一.添加集群里个节点的hostname并设置好对应主机名 ... 
- Rancher2.x 一键式部署 Prometheus + Grafana 监控 Kubernetes 集群
		目录 1.Prometheus & Grafana 介绍 2.环境.软件准备 3.Rancher 2.x 应用商店 4.一键式部署 Prometheus 5.验证 Prometheus + G ... 
- 基于TLS证书手动部署kubernetes集群(上)
		一.简介 Kubernetes是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernetes也叫K8S. K8S是Google内部一个叫Borg的容器集群管理系统衍生 ... 
- (转)基于TLS证书手动部署kubernetes集群(上)
		转:https://www.cnblogs.com/wdliu/archive/2018/06/06/9147346.html 一.简介 Kubernetes是Google在2014年6月开源的一个容 ... 
- 在kubernetes集群上用helm安装Datadog(Monitoring)
		Datadog is a monitoring service that gathers monitoring data from your containers within your Azure  ... 
- prometheus operator(Kubernetes 集群监控)
		一.Prometheus Operator 介绍 Prometheus Operator 是 CoreOS 开发的基于 Prometheus 的 Kubernetes 监控方案,也可能是目前功能最全面 ... 
- Kubernetes集群向指定节点上创建容器
		如果需要限制Pod到指定的Node上运行,则可以给Node打标签并给Pod配置NodeSelector. 给节点添加标签 首先查看节点信息 [root@k8s-master ~]# kubectl g ... 
随机推荐
	
									- Linux技术学习路线图
			
			
- WPF路由
			举例:窗口-用户控件-布局控件-…-按钮 按钮的点击事件:先由按钮的Click相应,然后….,然后布局控件,然后用户控件,然后窗口类似异常,直到“处理完成”(实际上一般按钮自己处理即可) 路由事件   ... 
- 微信小程序把玩(九)scroll-view组件
			原文:微信小程序把玩(九)scroll-view组件 scroll-view为滚动视图,分为水平滚动和垂直滚动.注意滚动视图垂直滚动时一定要设置高度否则的话scroll-view不会生效.滚动视图常用 ... 
- 微信小程序把玩(十)swiper组件
			原文:微信小程序把玩(十)swiper组件 Android写过轮播图的痛楚只有写过的知道,相对还是比较麻烦的,并没有一个轮播图组件,有个ViewPage也需要自己定制,IOS则多用UIScroller ... 
- Java Date Calendar DateFormat Details
			From https://www.ntu.edu.sg/home/ehchua/programming/java/DateTimeCalendar.html Date and Time - Creat ... 
- 21 步助你成为成功的 Web 开发者(激情不是被动的:它是一种对行动起来的追求)
			随着 Web 开发产业的爆发式发展,许多人会问这样的问题:我如何才能成为一名 Web 开发者?我认为这是一个错误的提问.问题应该是:我如何才能成为一名成功的 Web 开发者? 能提出这样的问题很重要, ... 
- QT5.6,5.7,5.8的新特征以及展望(Qt5.7首次正式支持Qt3D,以前都是预览版)
			https://wiki.qt.io/New_Features_in_Qt_5.6 (跨平台High-DPI,改进WebEngine到45,支持WIN 10,Canvas3D,3D) https:// ... 
- 用C实现OOP面向对象编程(1)
			如摘要所说,C语言不支持OOP(面向对象的编程).并这不意味着我们就不能对C进行面向对象的开发,只是过程要复杂许多.原来以C++的许多工作,在C语言中需我们手动去完成. 博主将与大家一起研究一下如下用 ... 
- RtlAdjustPrivilege进程提权,权限ID对照表
			SeCreateTokenPrivilege            0x2 SeAssignPrimaryTokenPrivilege     0x3 SeLockMemoryPrivilege    ... 
- 快速开发平台  WebBuilder 8 发布
			快速开发平台  WebBuilder 8 发布 了解:http://www.putdb.com,官网:http://www.geejing.com 什么是WebBuilder? WebBuilder是 ... 
转载自:https://www.qikqiak.com/post/monitor-external-k8s-on-prometheus/ 在实际环境中很多企业是将 Prometheus 单独部署在集群 ...
解决项目迁移至Kubernetes集群中的代理问题 随着Kubernetes技术的日益成熟,越来越多的企业选择用Kubernetes集群来管理项目.新项目还好,可以选择合适的集群规模从零开始构建项目: ...
kubernetes 集群添加node节点 注意,我们并不需要把新增的node ip加入到证书里重新生成!!! 下面我们以添加node03为例 一.添加集群里个节点的hostname并设置好对应主机名 ...
目录 1.Prometheus & Grafana 介绍 2.环境.软件准备 3.Rancher 2.x 应用商店 4.一键式部署 Prometheus 5.验证 Prometheus + G ...
一.简介 Kubernetes是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernetes也叫K8S. K8S是Google内部一个叫Borg的容器集群管理系统衍生 ...
转:https://www.cnblogs.com/wdliu/archive/2018/06/06/9147346.html 一.简介 Kubernetes是Google在2014年6月开源的一个容 ...
Datadog is a monitoring service that gathers monitoring data from your containers within your Azure ...
一.Prometheus Operator 介绍 Prometheus Operator 是 CoreOS 开发的基于 Prometheus 的 Kubernetes 监控方案,也可能是目前功能最全面 ...
如果需要限制Pod到指定的Node上运行,则可以给Node打标签并给Pod配置NodeSelector. 给节点添加标签 首先查看节点信息 [root@k8s-master ~]# kubectl g ...
举例:窗口-用户控件-布局控件-…-按钮 按钮的点击事件:先由按钮的Click相应,然后….,然后布局控件,然后用户控件,然后窗口类似异常,直到“处理完成”(实际上一般按钮自己处理即可) 路由事件 ...
原文:微信小程序把玩(九)scroll-view组件 scroll-view为滚动视图,分为水平滚动和垂直滚动.注意滚动视图垂直滚动时一定要设置高度否则的话scroll-view不会生效.滚动视图常用 ...
原文:微信小程序把玩(十)swiper组件 Android写过轮播图的痛楚只有写过的知道,相对还是比较麻烦的,并没有一个轮播图组件,有个ViewPage也需要自己定制,IOS则多用UIScroller ...
From https://www.ntu.edu.sg/home/ehchua/programming/java/DateTimeCalendar.html Date and Time - Creat ...
随着 Web 开发产业的爆发式发展,许多人会问这样的问题:我如何才能成为一名 Web 开发者?我认为这是一个错误的提问.问题应该是:我如何才能成为一名成功的 Web 开发者? 能提出这样的问题很重要, ...
https://wiki.qt.io/New_Features_in_Qt_5.6 (跨平台High-DPI,改进WebEngine到45,支持WIN 10,Canvas3D,3D) https:// ...
如摘要所说,C语言不支持OOP(面向对象的编程).并这不意味着我们就不能对C进行面向对象的开发,只是过程要复杂许多.原来以C++的许多工作,在C语言中需我们手动去完成. 博主将与大家一起研究一下如下用 ...
SeCreateTokenPrivilege 0x2 SeAssignPrimaryTokenPrivilege 0x3 SeLockMemoryPrivilege ...
快速开发平台 WebBuilder 8 发布 了解:http://www.putdb.com,官网:http://www.geejing.com 什么是WebBuilder? WebBuilder是 ...
