如何配置 Zabbix 以允许主机在计划外的时间不可访问?
我们有一些正在运行的集群,其中通常并非所有节点都得到充分利用(VMware、Slurm、OpenStack),我们目前正在评估在哪里可以关闭主机以尽可能节省电力。
VMware 和 Slurm 都可以轻松做到这一点,但它们或多或少是随机决定关闭哪些主机以及何时关闭,因此维护窗口被关闭。
在 Slurm 上,我必须编写一个脚本来处理关机和启动,我可以在那里添加一个 API 调用来禁用和启用对关闭服务器的监控,但在 VMware 上我无法做到这一点。
我目前能想到的唯一方法是触发依赖关系,但我真的不知道如何以有用的方式配置它们。
一些澄清:
- 我想“暂停”对已关闭节点的监控故意地
- 我仍然需要在节点宕机时触发警报无意地
- 我宁愿不在 ESXi 主机上安装任何东西,除非是将来会支持的 VIB
- 我希望所有内容都直接在 Zabbix 或 Zabbix 主机上进行
- 我希望所有类型的主机都使用相同的方法,这样更容易维护
我目前的想法(正在进行中):
- 通过控制平面监控节点状态
- 当状态为计划待机时触发的触发器
- 启用/禁用主机或创建/删除维护期的操作
这需要在 Zabbix 主机上使用 API 的小脚本,但这对我来说没问题
答案1
您可以定义如此命名维护期(计划停机)。
Navigate to Configuration → Maintenance Click on the Create maintenance period button Type in the maintenance period name Select the maintenance type and the activity time window Add a period during which your maintenance will take place Select hosts and/or host groups Optionally, specify tags to suppress only the matching problems Add the maintenance period Wait until the configuration changes are picked up by the Zabbix server Navigate to Monitoring → Problems Confirm if the problems on the host are suppressed
您可以通过以下方式定义上述内容Zabbix API。
答案2
我继续处理这个问题,并想分享结果,以防其他人遇到类似的问题。
首先,我从特定的控制平面获取相关节点的状态。
泥浆
其中一个控制节点上的代理配置:
UserParameter=slurm.nodes.discovery,sinfo -N -h -o '{"{#NODENAME}":"%N"}' |jq -sr '[.[]]'
UserParameter=slurm.node.state[*],sinfo -h -o %T -n $1
Zabbix发现规则:
- 密钥:slurm.nodes.discovery
- 产品原型
- 姓名:
Slurm node {#NODENAME} status
- 类型:Zabbix 代理
- 钥匙:
slurm.node.state[{#NODENAME}]
- 信息类型:文本
- 姓名:
- 扳機原型
- 姓名:
Slurm node {#NODENAME} in stand by
- 运行数据:
{#NODENAME}
- 严重性:信息
- 表达:
find(/controlnodename/slurm.node.state[{#NODENAME}],#3,"regexp","[~#]$")=1
- 标签
powersave
::standby
- 姓名:
- 产品原型
VMware vSphere
我编写了一个小脚本,从 vCenter API 获取 ESXi 主机的电源状态:
#!/usr/bin/env python3
import os
import sys
from pyVim import connect
from pyVmomi import vim
vc_url = "vcenter.example.com"
vc_user = "[email protected]"
vc_password = "aHR0cDovL2JpdC5seS8xVHFjd243Cg=="
if len(sys.argv) < 1:
print("host parameter missing", file=sys.stderr)
os.exit(3)
esx_name = sys.argv[1]
my_cluster = connect.ConnectNoSSL(vc_url, 443, vc_user, vc_password)
content = my_cluster.RetrieveContent()
object_view = content.viewManager.CreateContainerView(content.rootFolder, [vim.HostSystem], True)
host_list = object_view.view
object_view.Destroy()
for host in host_list:
if host.name == esx_name:
print(host.runtime.powerState)
connect.Disconnect(my_cluster)
这是我发现的唯一一种即使在主机关闭时也能获取主机状态的方法。
Zabbix发现规则:
- 密钥:
vmware.hv.discovery[{$VMWARE.URL}]
类型:简单检查- 产品原型
- 姓名:
Power state of Hypervisor {#HV.NAME}
- 类型:外部检查
- 钥匙:
vsphere_host_powerstate.py[{#HV.NAME}]
- 信息类型:文本
- 姓名:
- 扳機原型
- 姓名:
VMware Host {#HV.NAME} in stand by
- 运行数据:
{#HV.NAME}
- 严重性:信息
- 表达:
last(/vc/vsphere_host_powerstate.py[{#HV.NAME}])="standBy"
- 标签
powersave
::standby
- 姓名:
- 产品原型
通用配置
该字段Operational data
很重要,因为我稍后在使用宏调用脚本时会用到它。使用带有触发器值的{EVENT.OPDATA}
标签,因此我可以对所有主机使用单个操作。powersave
standby
我一直在争论是否应该在 Zabbix 中禁用为了省电而关闭的机器或者将其放入维护窗口。
我认为将机器置于维护窗口中更为直观:
- 如果禁用,则对于在 Zabbix 中管理机器的每个人来说都不明显为什么它被禁用
- 维护窗口的描述直接显示在事件中
我编写了一个脚本来在维护窗口中添加和删除机器:
#!/usr/bin/env bash
# set -xv
ZBX_URL="https://zabbix.example.com/zabbix/api_jsonrpc.php"
ZBX_USERNAME="zabbix-api"
ZBX_PASSWORD="aHR0cDovL2JpdC5seS8xVHFjd243Cg=="
ZBX_MAINTENANCE_ID=431
function usage {
echo "Usage:"
echo " $0 <hostname> <maintenance_add|maintenance_remove>"
}
function api_error {
echo -n "API ERROR: "
echo "$*" | jq -r .error.data
exit 3
}
if [[ $# -lt 2 ]]; then
echo "Error: argument missing"
usage
exit 1
fi
function zbx_request {
REQUEST='{
"jsonrpc": "2.0",
"method": "'$1'",
"params": '$2',
"auth": "'$AUTH'",
"id": 1
}'
# echo "$REQUEST" |jq
RESPONSE=$(curl -s -X POST \
-H 'Content-Type: application/json-rpc' \
-d "$REQUEST" "$ZBX_URL")
echo "$RESPONSE" | jq --exit-status .result > /dev/null || api_error "$RESPONSE"
echo "$RESPONSE"
}
function host_get {
PARAMS='{
"filter": {
"host": [
"'$1'"
]
}
}'
RESPONSE=$(zbx_request "host.get" "$PARAMS")
echo "$RESPONSE" | jq -r .result[0].hostid
}
function maintenance_get {
PARAMS='{
"maintenanceids": [ '$ZBX_MAINTENANCE_ID' ],
"selectHosts": [ "hostid" ]
}'
RESPONSE=$(zbx_request "maintenance.get" "$PARAMS")
echo "$RESPONSE" |jq .result[0].hosts | jq -r 'map(.hostid)'
}
function maintenance_add {
MAINTENANCE_HOSTS=$(maintenance_get)
HOSTID=$(host_get "$1")
if jq -e '. | index("'"$HOSTID"'")' <<<"$MAINTENANCE_HOSTS" > /dev/null; th
en return; fi
HOSTS=$(jq '. += ["'"$HOSTID"'"]' <<<"$MAINTENANCE_HOSTS")
PARAMS='{
"maintenanceid": "'$ZBX_MAINTENANCE_ID'",
"hostids": '$HOSTS'
}'
zbx_request "maintenance.update" "$PARAMS" > /dev/null
}
function maintenance_remove {
MAINTENANCE_HOSTS=$(maintenance_get)
HOSTID=$(host_get "$1")
HOSTINDEX=$(jq '. | index("'"$HOSTID"'")' <<<"$MAINTENANCE_HOSTS")
if [ "$HOSTINDEX" == "null" ]; then return; fi
HOSTS=$(jq 'del(.['"$HOSTINDEX"'])' <<<"$MAINTENANCE_HOSTS")
PARAMS='{
"maintenanceid": "'$ZBX_MAINTENANCE_ID'",
"hostids": '$HOSTS'
}'
zbx_request "maintenance.update" "$PARAMS" > /dev/null
}
RESPONSE=$(curl -s -X POST -H 'Content-Type: application/json-rpc' \
-d '
{"jsonrpc":"2.0","method":"user.login","params":
{"user":"'"$ZBX_USERNAME"'","password":"'"$ZBX_PASSWORD"'"},
"id":1,"auth":null}
' "$ZBX_URL")
echo "$RESPONSE" | jq --exit-status .result > /dev/null || api_error "$RESPONSE"
AUTH=$(echo "$RESPONSE" | jq -r .result)
case $2 in
maintenance_add)
maintenance_add "$1"
;;
maintenance_remove)
maintenance_remove "$1"
;;
*)
echo "invalid state: $2"
usage
exit 2
;;
esac
脚本配置:
- 姓名:
Run Script zbx-set-host.sh maintenance_add
- 类型:脚本
- 命令:
/path/to/zbx-set-host.sh {EVENT.OPDATA} maintenance_add
- 姓名:
Run Script zbx-set-host.sh maintenance_add
- 类型:脚本
- 命令:
/path/to/zbx-set-host.sh {EVENT.OPDATA} maintenance_remove
触发动作:
- 姓名:
Disable host in stand by (power saving)
- 状况:
- 标签值
powersave
等于standby
- 标签值
- 运营
- 手术:
Run script "Run Script zbx-set-host.sh maintenance_add"
- 目标列表:当前主机
- 手术:
- 恢复操作Recovery operations
- 手术:
Run script "Run Script zbx-set-host.sh maintenance_remove"
- 目标列表:当前主机
- 手术: