使用 pyVmomi 采集 vSphere 监控指标
前言
VMware 在中小型的企业/单位里几乎是标配了。毕竟规模不大的情况下,性价比还是相当好的。对于 VMware 平台上各项指标,我们当然也要去做监控了。
我们使用了 去连接 vCenter ,获取 ESXi 主机,datastore,VM 等性能指标,并推送给 Open-Falcon
需求
我们需要监控的内容包含:
这些数据其实 vCenter 里全部都有,我们在 vCenter 内都能看得到。但是如果我们希望能够统一监控的平台,要把这些监控数据从 vCenter 里取出来,怎么做呢?
是 VMware vSphere API 的一个 python sdk,我们可以利用它来与 vCenter 交互,获取我们需要的信息.
使用 pyVmomi 连接 vCenter
pyVmomi 说老实话,蛮复杂的。好在 VMware 官方提供了一大堆 example—— 可以参考。
安装 也非常容易, 就好了。
首先我们来连接一下 vCenter,与 example 不同的是,我们使用 来连接 vCenter,这样不会由于证书原因报错。
#!/usr/bin/env python
#coding=utf-8
import atexit
from pyVmomi import vim, vmodl
from pyVim.connect import SmartConnectNoSSL, Disconnect
def run(host,user,pwd,port):
try:
si = SmartConnectNoSSL(host=host, user=user, pwd=pwd, port=port)
atexit.register(Disconnect, si)
content = si.RetrieveContent()
print "Hellow World!"
except vmodl.MethodFault as error:
print "Caught vmodl fault : " + error.msg
return False, error.msg
return True, "ok"
if __name__ == "__main__":
host = "vcenter.host"
user = "administrator@vpshere.local"
pwd = "password"
port = 443
print run(host,user,pwd,port)
Hello World !
Hellow World!
(True, 'ok')
获取 Datastore 信息
在连接上 之后,我们就可以开始获取各项指标了。我们从 下的根目录逐级开始遍历,他的第一个 就是我们的
print content.rootFolder.childEntity
(ManagedObject) [
'vim.Datacenter:datacenter-2'
]
下面的 属性,即存储的相关信息
for datacenter in content.rootFolder.childEntity:
print "datacenter =",datacenter.name
print datacenter.datastore
datastores = datacenter.datastore
for ds in datastores:
print ds.summary
我们可以通过 ,获取 的名字,在组织数据上报的时候,可以作为 打在 上,可以区分 来自哪个 。
的容量,类型等数据,则都在 之中
datacenter = Datacenter
(ManagedObject) [
'vim.Datastore:datastore-52',
'vim.Datastore:datastore-63',
'vim.Datastore:datastore-53',
'vim.Datastore:datastore-64',
'vim.Datastore:datastore-10'
]
(vim.Datastore.Summary) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
datastore = 'vim.Datastore:datastore-52',
name = 'datastore1',
url = 'ds:///vmfs/volumes/56c67e14-26d12426-719b-e02f6dbbf15a/',
capacity = 1189705940992L,
freeSpace = 1025420296192L,
uncommitted = 1005186974305L,
accessible = true,
multipleHostAccess = false,
type = 'VMFS',
maintenanceMode = 'normal'
}
(vim.Datastore.Summary) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
datastore = 'vim.Datastore:datastore-63',
name = 'datastore1 (1)',
url = 'ds:///vmfs/volumes/56c6891b-a7873bd4-c83e-e86549552d90/',
capacity = 1189705940992L,
freeSpace = 1188680433664L,
uncommitted = ,
accessible = true,
multipleHostAccess = false,
type = 'VMFS',
maintenanceMode = 'normal'
}
(vim.Datastore.Summary) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
datastore = 'vim.Datastore:datastore-53',
name = 'datastore2',
url = 'ds:///vmfs/volumes/56c6a783-08a37b38-cd79-e02f6dbbf15a/',
capacity = 1197490569216L,
freeSpace = 302907392000L,
uncommitted = 589L,
accessible = true,
multipleHostAccess = false,
type = 'VMFS',
maintenanceMode = 'normal'
}
(vim.Datastore.Summary) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
datastore = 'vim.Datastore:datastore-64',
name = 'datastore2 (1)',
url = 'ds:///vmfs/volumes/56c6a879-8b734ca2-dddd-e86549552d90/',
capacity = 1197490569216L,
freeSpace = 24554504192L,
uncommitted = 487L,
accessible = true,
multipleHostAccess = false,
type = 'VMFS',
maintenanceMode = 'normal'
}
(vim.Datastore.Summary) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
datastore = 'vim.Datastore:datastore-10',
name = 'datastore1 (32)',
url = 'ds:///vmfs/volumes/59c3b795-2762392c-3cb9-3440b5d64c30/',
capacity = 590021132288L,
freeSpace = 232418967552L,
uncommitted = 2355216338L,
accessible = true,
multipleHostAccess = false,
type = 'VMFS',
maintenanceMode = 'normal'
}
获取 ESXi 信息
, 即我们 集群中的主机信息,他在 的结构是这样的:
Datacenter.hostFolder -> Folder
hostFolder.childEntity -> list(Folder or ClusterComputeResource or ComputeResource)
ClusterComputeResource.host -> list(HostSystem)
ComputeResource.host -> list(HostSystem)
即我们建立的文件夹, 是主机集群,如果没有建立集群, 下直接建立主机的话,则是
的 是一个 ,里面可能是 , 或
和 下的 也是一个 ,里面是主机的列表。
这里我们面临一个问题,因为 下面还可能嵌套 ,所以我们得写个递归来遍历。
def getComputeResource(Folder,computeResourceList):
if hasattr(Folder, 'childEntity'):
for computeResource in Folder.childEntity:
getComputeResource(computeResource,computeResourceList)
else:
computeResourceList.append(Folder)
return computeResourceList
这样,我们就可以遍历所有的 拿到所有的 和 了
for datacenter in content.rootFolder.childEntity:
print "datacenter =",datacenter.name
if hasattr(datacenter.hostFolder, 'childEntity'):
hostFolder = datacenter.hostFolder
computeResourceList = []
computeResourceList = getComputeResource(hostFolder,computeResourceList)
for computeResource in computeResourceList:
print computeResource.name
print computeResource.host
类似的,主机的相关基本信息都在 host.summary 下面。其中 summary.quickStats 有一些基本的监控信息。cpu,mem 的总量则需要去 host.hardware 中去找。以下是某台主机的 , 和
esxi = 192.168.179.120
(vim.host.CpuInfo) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
numCpuPackages = 2,
numCpuCores = 8,
numCpuThreads = 16,
hz = 2666761067L
}
memorySize = 34347229184
(vim.host.Summary.QuickStats) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
overallCpuUsage = 209,
overallMemoryUsage = 13881,
distributedCpuFairness = 10000,
distributedMemoryFairness = 574,
uptime = 2018927
}
perfManager
现在我们还有主机的网络数据没有拿到,这些在 quickStats 中是没有的。此时就需要通过 来获取性能数据了。 中内置了大量的性能指标,可以从 中获取
perf_dict = {}
perfList = content.perfManager.perfCounter
for counter in perfList:
counter_full = "{}.{}.{}".format(counter.groupInfo.key, counter.nameInfo.key, counter.rollupType)
perf_dict[counter_full] = counter.key
print perf_dict
通过 我们可以拿到所有的指标 和对应的 ,后面我们查询的时候会用到这个
我们先构造一个性能查询的函数
from datetime import timedelta
def BuildQuery(content, vchtime, counterId, instance, entity, interval):
perfManager = content.perfManager
metricId = vim.PerformanceManager.MetricId(counterId=counterId, instance=instance)
startTime = vchtime - timedelta(seconds=(interval + 60))
endTime = vchtime - timedelta(seconds=60)
query = vim.PerformanceManager.QuerySpec(intervalId=20, entity=entity, metricId=[metricId], startTime=startTime,
endTime=endTime)
perfResults = perfManager.QueryPerf(querySpec=[query])
if perfResults:
return perfResults
else:
return False
几个参数说明
使用 查询性能时,需要给出查询的时间范围和查询的颗粒度。我这里使用的颗粒度是 ,也就是 20 秒一个点。提供的时间范围提前了 1 分钟,避免太接近当前时间的点上查不到数据。
一个返回的示例
(vim.PerformanceManager.EntityMetricBase) [
(vim.PerformanceManager.EntityMetric) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
entity = 'vim.HostSystem:host-9',
sampleInfo = (vim.PerformanceManager.SampleInfo) [
(vim.PerformanceManager.SampleInfo) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
timestamp = 2017-10-20T15:37:20Z,
interval = 20
},
(vim.PerformanceManager.SampleInfo) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
timestamp = 2017-10-20T15:37:40Z,
interval = 20
},
(vim.PerformanceManager.SampleInfo) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
timestamp = 2017-10-20T15:38:00Z,
interval = 20
}
],
value = (vim.PerformanceManager.MetricSeries) [
(vim.PerformanceManager.IntSeries) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
id = (vim.PerformanceManager.MetricId) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
counterId = 148,
instance = ''
},
value = (long) [
10L,
4L,
5L
]
},
(vim.PerformanceManager.IntSeries) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
id = (vim.PerformanceManager.MetricId) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
counterId = 148,
instance = 'vmnic3'
},
value = (long) [
0L,
0L,
0L
]
},
(vim.PerformanceManager.IntSeries) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
id = (vim.PerformanceManager.MetricId) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
counterId = 148,
instance = 'vmnic2'
},
value = (long) [
0L,
0L,
0L
]
},
(vim.PerformanceManager.IntSeries) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
id = (vim.PerformanceManager.MetricId) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
counterId = 148,
instance = 'vmnic1'
},
value = (long) [
10L,
4L,
5L
]
},
(vim.PerformanceManager.IntSeries) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
id = (vim.PerformanceManager.MetricId) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
counterId = 148,
instance = 'vusb0'
},
value = (long) [
0L,
0L,
0L
]
},
(vim.PerformanceManager.IntSeries) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
id = (vim.PerformanceManager.MetricId) {
dynamicType = ,
dynamicProperty = (vmodl.DynamicProperty) [],
counterId = 148,
instance = 'vmnic0'
},
value = (long) [
0L,
0L,
0L
]
}
]
}
]
起始的 表示的是性能数据所在的时间点。我们查的 是 60 秒,颗粒度是 20秒。因此返回了 3 个点。 是每个点上的值, 对应了不同的网卡,如, 等,其中 表示这台主机所有的网卡流量总和,也就是这台机器总体的网络流量。
获取 VM 信息
类似的 , 的数据都在 下面,当然也会碰到 嵌套的问题。不过我们之所以遍历 去获取主机信息,主要是为了能够在遍历过程中,拿到主机上级的 和 等信息,作为数据的 一同报送给监控系统。
这些 对于经常飘来飘去的 而言就没太大的意义了,而且对于 Open-Falcon 这样的监控系统而言, 的变动意味着 发生变更,数据会落入新的 当中,无疑是给自己找麻烦。
我们可以通过更简单的办法拿到所有的 清单
obj = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
for vm in obj.view
print vm.summary.quickStats
与主机类似的, 的基本状态信息也在 内。而诸如网络流量,磁盘 IO 等信息也需要通过 来获取。对应的 也依然可以从 中获取。
此时可能会发现部分 是拿不到网络信息,也就是 和 这两个 的性能数据。我们可以打开 内虚拟机的性能图表,会发现网络图表也会显示 或者 。
这是 VMware 的一个已知 bug,在 以上版本被修复。详见官方 Knowledge ——
轮子
如果你使用的监控系统是 Open-Falcon 的话,那么轮子已经造好了。可以直接使用 进行监控。
安装
git clone https://github.com/freedomkk-qfeng/vsphere-monitor.git
yum install -y python-virtualenv
cd vsphere-monitor
virtualenv ./env
./env/bin/pip install -r requirement.txt
配置
配置文件是 ,修改它就可以了
# falcon
endpoint = "vcenter" # 上报给 open-falcon 的 endpoint
push_api = "http://127.0.0.1:6060/api/push" # 上报的 http api 接口
interval = 60 # 上报的 step 间隔
# vcenter
host = "vcenter.host" # vcenter 的地址
user = "administrator@vsphere.local" # vcenter 的用户名
pwd = "password" # vcenter 的密码
port = 443 # vcenter 的端口
# esxi
esxi_names = [] # 需要采集的 esxi ,留空则全部采集
# datastore
datastore_names = [] # 需要采集的 datastore ,留空则全部采集
# vm
vm_enable = True # 是否要采集虚拟机信息
vm_names = [ # 需要采集的虚拟机,留空则全部采集
"vm1",
"vm2",
"vm3"
]
运行
先尝试跑一下,假定 放在 下
/opt/vsphere-monitor/env/bin/python /opt/vsphere-monitor/vsphere-monitor.py
没有问题的话,将他放入定时任务
crontab -e
0-59/1 * * * * /opt/vsphere-monitor/env/bin/python /opt/vsphere-monitor/vsphere-monitor.py
运行
ESXi 主机监控
image.png
VM 运行监控

image.png
参考文档
以上
行文有微调。