技术文档:使用阿里云 CloudMonitor API 监控 ECS (不使用 Zabbix Agent)
1. 引言
本文档旨在记录如何在不使用 Zabbix Agent 的前提下,通过调用阿里云 CloudMonitor API 获取 ECS 实例的监控数据,并将这些数据发送到 Zabbix Server 进行集中监控。该方法适用于不希望在被监控的 ECS 实例上安装 Zabbix Agent 的场景。
2. 方案概述
核心思想是编写一个运行在 Zabbix Server (或具备访问阿里云公网 API 和 Zabbix Server 的中间服务器) 上的脚本。该脚本负责:
- 使用阿里云命令行工具 (aliyun CLI) 调用 CloudMonitor 的 DescribeMetricData API。
- 传入正确的认证信息、ECS 实例 ID、地域、监控指标名称、命名空间和时间范围。
- 解析 API 返回的 JSON 数据,提取监控数值。
- 将提取到的单个数值作为脚本的标准输出,供 Zabbix 的 External check 类型监控项采集。
3. 前提条件
- 一个运行中的 Zabbix Server (版本要求支持 External check),zabbix6.4以上。
- 一个或多个需要监控的阿里云 ECS 实例。
- 拥有阿里云账号并具备管理 RAM 用户和 CloudMonitor 服务的权限。
- 在 Zabbix Server 上已安装并配置好 aliyun CLI 和 jq 工具。
- Zabbix Server 进程拥有执行外部脚本的权限。
4. 操作步骤
按照以下步骤在阿里云和 Zabbix Server 上进行配置:
4.1 阿里云控制台配置
- 登录阿里云控制台,进入 RAM 访问控制。
- 创建新的 RAM 用户,并妥善记录其 AccessKey ID 和 AccessKey Secret。
- 添加权限:为该用户授予 AliyunCloudMonitorReadOnlyAccess 权限,或者创建自定义策略,确保其具有调用 CloudMonitor DescribeMetricData API 的权限。
- 记录需要监控的 ECS 实例的 实例 ID (InstanceId) 和所在 地域 ID (RegionId)。
- 登录阿里云控制台,进入 云监控 服务,找到您的 ECS 实例,进入主机监控页面。
- 查看并记录需要监控的各项指标的 指标名称 (MetricName) 和它们所属的 命名空间 (Namespace)。例如,CPU 利用率通常是 CPUUtilization在 acs_ecs_dashboard 命名空间下;内存和磁盘利用率可能依赖于云监控 Agent,名称和命名空间需根据实际情况确认。
- MetricName参考连接:云监控控制台
4.2 Zabbix Server 环境准备
- 在Zabbix服务器上安装jq工具用于JSON解析: sudo apt-get install jq # Debian/Ubuntu
# 或
sudo yum install jq # CentOS/RHEL
- 安装阿里云CLI工具: sudo pip install aliyun-python-sdk-core aliyun-python-sdk-cms
若提示pip未安装,则需要确保已安装python3.9以上的版本,再安装pip
- 请确保安装的 aliyun CLI 版本正常,我们之前遇到了 –output 参数格式和配置目录权限问题,这些在后面的步骤中解决。
- 检查 Zabbix Server 的 systemd unit 文件 (zabbix-server.service),确认其运行用户和组。
路径/usr/lib/systemd/system/zabbix-server.service
sudo vi /usr/lib/systemd/system/zabbix-server.service
- 在 [Service] 部分查找 User= 和 Group= 行。如果这两行不存在,服务默认以 root 用户运行,这是不安全且会导致权限问题。
- 使用 systemctl edit 命令添加或修改运行用户和组为 zabbix (标准非特权用户): sudo systemctl edit zabbix-server.service
在编辑器中添加或修改以下内容:
[Service]
User=zabbix
Group=zabbix
保存并退出。
- 重新加载 systemd 配置并重启zabbix服务器: sudo systemctl daemon-reload
- 将 Zabbix Server 主配置文件 /etc/zabbix/zabbix_server.conf 的所有者更改为 zabbix 用户,以便 Zabbix Server 进程能够读取它: sudo chown zabbix:zabbix /etc/zabbix/zabbix_server.conf
- 应用新的用户配置和文件权限: sudo systemctl restart zabbix-server
- 确认服务以 zabbix 用户运行:ps aux | grep zabbix_server。
- 切换到 zabbix 用户环境并运行 aliyun configure。这将确保 aliyun CLI 的配置文件 (config.json) 生成在 zabbix 用户的主目录下,并且由 zabbix 用户拥有权限访问,从而解决 panic: mkdir /.aliyun: permission denied 错误。
- 进入路径 /var/lib/zabbix/.aliyun,准备在此路径下生成aliyun-cli的配置文件config.json
sudo su – zabbix -s /bin/bash -c "aliyun configure"
- 根据提示输入您的阿里云 AccessKey ID, Secret Key, Default Region Id (cn-hangzhou), output format (json), language (zh)。
- 确认配置文件存在并归 zabbix 用户所有(例如 /var/lib/zabbix/.aliyun/config.json)。
4.3 创建监控脚本
1.创建脚本文件:
- 在 Zabbix ExternalScripts 目录下创建脚本文件 (作者使用的是zabbix默认目录,若有需要可以在zabbix_server.conf配置文件内修改路径)
/usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh
sudo vim /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh
2.编辑脚本内容:
- 将以下脚本内容复制到文件中。请根据您的实际情况修改开头的阿里云密钥、实例ID、地域ID,以及根据您在阿里云控制台查到的信息修改 get_metric_data 函数调用中的 MetricName 和 Namespace。
- 该脚本设计为:
- 带一个参数(Zabbix Item Key,例如 cpu.usage)运行时,获取对应指标的单个数值并输出(用于 External Check)。
- 不带参数运行时,输出用法错误提示(不用于 External Check)。
- 脚本内部通过环境变量传递密钥给 aliyun CLI,并处理 aliyun 命令的错误输出和 jq 解析的健壮性。
#!/bin/bash
# 阿里云API配置
# 请替换为您的Access Key ID 和 Secret Key
ALIYUN_ACCESS_KEY="您的Access Key ID"
ALIYUN_SECRET_KEY="你的Secret Key"
ECS_INSTANCE_ID="你的实例id i-bxxxxxxxxxxx"
REGION_ID="cn-hangzhou" #你的服务器地域
# 设置阿里云CLI的Access Key和Secret Key (推荐设置环境变量或使用配置文件,这里为了演示方便直接在脚本中指定)
export ALIYUN_ACCESS_KEY_ID="$ALIYUN_ACCESS_KEY"
export ALIYUN_ACCESS_KEY_SECRET="$ALIYUN_SECRET_KEY"
# 注意:直接在脚本中设置密钥存在安全风险,推荐在运行脚本的用户环境中设置环境变量或使用阿里云CLI的配置profile
# 获取结束时间(ISO8601格式)
# 获取当前时间,并格式化为 ISO8601 格式,阿里云CLI通常接受这种格式
END_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# 获取开始时间,这里计算1分钟前的时间,并格式化
START_TIME=$(date -u -d '1 minute ago' +"%Y-%m-%dT%H:%M:%SZ")
# 获取监控数据函数
get_metric_data() {
local metric_name="$1"
local namespace="$2"
# 调用阿里云API获取监控数据
# 直接将参数传递给 aliyun cms DescribeMetricData 命令
# 移除 –body "$params",直接使用参数
local response=$(aliyun cms DescribeMetricData \\
–RegionId "$REGION_ID" \\
–Namespace "$namespace" \\
–MetricName "$metric_name" \\
–Dimensions "[{\\"instanceId\\":\\"$ECS_INSTANCE_ID\\"}]" \\
–StartTime "$START_TIME" \\
–EndTime "$END_TIME" \\
–Period "60"
)
# 检查API调用是否成功,并解析JSON提取数据
# 使用 jq 安全地解析JSON,并提取第一个数据点的 Average 值
local value=$(echo "$response" | jq -r '
if (.Datapoints | type) == "string" then
(.Datapoints | fromjson)[0].Average // 0
else
.Datapoints[0].Average // 0
end
')
# 如果jq提取的值为空或null,则将其设置为0
[ -z "$value" ] && value=0
echo "$value"
}
# 以下部分保持不变,调用函数获取数据并输出给Zabbix
# … (get_metric_data 函数定义结束) …
# **核心修改:根据传入的参数输出单个指标的值,用于 Zabbix External Check**
if [ "$#" -eq 1 ]; then # 检查是否接收到一个参数 (Zabbix Key)
case "$1" in
"cpu.usage")
# 确保这里的 MetricName 和 Namespace 与您成功获取 CPU 数据时使用的匹配
cpu_value=$(get_metric_data "CPUUtilization" "acs_ecs_dashboard") # 请根据控制台或成功时的设置修改
echo "$cpu_value" # 只输出值
exit 0 # 获取并输出后立即退出
;;
"memory.usage")
memory_value=$(get_metric_data "memory_usedutilization" "acs_ecs_dashboard") # 示例,请替换为实际可用指标
echo "$memory_value" # 只输出值
exit 0
;;
"disk.usage")
disk_value=$(get_metric_data "diskusage_utilization" "acs_ecs_dashboard") # 示例,请替换为实际可用指标
echo "$disk_value" # 只输出值
exit 0
;;
"network.in")
network_in_value=$(get_metric_data "VPC_PublicIP_InternetInRate" "acs_ecs_dashboard") # 示例,请替换为实际可用指标
echo "$network_in_value" # 只输出值
exit 0
;;
"network.out")
# 网络指标仍然返回 0,请用控制台查到的实际可用指标名称和命名空间替换
network_out_value=$(get_metric_data "VPC_PublicIP_InternetOutRate" "acs_ecs_dashboard") # 示例,请替换为实际可用指标
echo "$network_out_value" # 只输出值
exit 0
;;
*)
# 如果参数无效,输出错误信息到标准错误,并返回非零退出码
echo "ERROR: Invalid parameter '$1'" >&2
exit 1
;;
esac
else
# **如果脚本不带参数运行(用于手动测试或zabbix_sender),执行原来的批量获取和输出逻辑**
# 请注意:Zabbix External Check 不期望这种多行输出
# 为了避免在 Zabbix 中出现混淆的输出,当不带参数运行时,您可以选择什么都不输出或输出一个错误提示。
# 在External Check场景下,不带参数运行通常是配置错误导致的。
echo "ERROR: This script expects exactly one parameter (Zabbix Key) when run as External check." >&2
# 以下是原来的批量获取逻辑,您可以保留用于手动调试,但在Zabbix External Check中运行时不会执行到这里
# cpu_usage=$(get_metric_data "cpu_utilization" "acs_ecs")
# memory_usage=$(get_metric_data "memory_usedutilization" "acs_ecs_dashboard")
# … (获取其他指标) …
# echo -e "$ZABBIX_HOSTNAME cpu.usage $cpu_usage\\n$ZABBIX_HOSTNAME memory.usage $memory_usage\\n…" # 原来的批量输出
exit 1 # 不带参数运行时,返回非零退出码提示用法错误
fi
3.设置脚本权限:
- 确保 zabbix 用户有读取和执行权限: sudo chmod +x /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh
sudo chmod o+rx /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh
或确保文件所有者/组权限正确。
4.测试脚本
指定zabbix用户执行脚本
sudo su – zabbix -s /bin/bash -c "/usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh cpu.usage"
与aliyun官网调取的值一致,说明调用成功。
4.4 Zabbix Web 界面配置
1.创建主机:
- 在 Zabbix Web 界面中,为您的阿里云 ECS 实例创建一个主机。 Hostname 建议使用方便识别的名称。无需配置 Agent 接口。
2.创建监控项 (Items):
- 在该主机下创建 External check 类型的监控项。
- 对于每个需要监控的指标(CPU, Memory, Disk, Network In, Network Out),创建一个独立的监控项。
- 以创建cpu使用率监控项为例
测试
在最新数据下查看数据是否读取
到此为止,监控项配置成功!!可根据需要追加新的监控项。
- 关键配置:
- Name: 指标描述名称 (例如 "CPU Utilization (Aliyun)")
- Type: External check
- Key: 脚本的完整路径[参数]。参数为您希望脚本获取的指标 Key。
- CPU Key: /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh[cpu.usage]
- Memory Key: /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh[memory.usage]
- Disk Key: /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh[disk.usage]
- Network In Key: /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh[network.in]
- Network Out Key: /usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh[network.out]
- Type of information: Numeric (float)
- Units: 指标单位 (%, GiB, Bps 等,根据您获取的指标单位设置)
- Update interval: 检查间隔,建议设置为与 API Period 相匹配或其倍数 (例如 Period 600s -> Update interval 10m)。
- 其他设置根据您的需求配置 (History, Trends, Applications 等)。
5. 验证与故障排除
- 在 Zabbix Web 界面中检查主机和监控项的状态。
- 查看 Zabbix Server 日志 (/var/log/zabbix/zabbix_server.log) 获取详细错误信息。我们之前遇到的权限、jq 解析、类型不匹配等问题都应该在此日志中反映。
- 使用 sudo su – zabbix -s /bin/bash -c "/usr/lib/zabbix/externalscripts/aliyun_ecs_monitor.sh [Key]" 命令手动以 zabbix 用户身份测试脚本,观察输出是否为单个数值。
常见问题及解决回顾:
- unknown parameter "Ena>": Zabbix Server 配置文件 (zabbix_server.conf) 中有语法错误。手动检查并修正。
- ERROR: bad flag format –output…: aliyun CLI 版本问题。通过移除 –output json 或根据 aliyun –help 调整参数格式解决。
- ERROR: region can't be empty: aliyun CLI 未找到默认地域配置。以 zabbix 用户运行 aliyun configure 解决。
- panic: mkdir /.aliyun: permission denied: aliyun CLI 在无权限目录尝试创建配置。通过以 zabbix 用户配置 aliyun CLI (生成 .aliyun/config.json 在用户主目录下),或设置 ALIYUN_CONFIG_PATH 环境变量解决。将 Zabbix Server 运行用户改为 zabbix 是根本措施。
- cannot open config file (Zabbix Server): Zabbix Server 以 zabbix 用户运行时无权读取其主配置文件。更改 zabbix_server.conf 文件所有者为 zabbix 解决。
- Value of type "string" is not suitable for value type "Numeric (float)": 脚本输出了 Zabbix 监控项不期望的字符串 (多行输出或错误信息)。通过修改脚本使其只输出单个数值,并将错误输出重定向 (2>/dev/null) 解决。
- jq 解析错误 (没有那个文件或目录): 多行 jq 表达式的 shell 解析问题。通过将多行表达式定义为变量并引用解决。
- 指标数据为 0 或 the metric is not exist (Code 400): CloudMonitor API 调用失败或在查询的时间段内没有数据点。通过在阿里云控制台确认正确的 MetricName/Namespace/Period,并考虑是否需要安装云监控 Agent 来采集特定指标解决。
6. 安全注意事项
- 切勿以 root 用户运行 Zabbix Server 服务。 始终使用专用的非特权用户 (如 zabbix)。
- 妥善保管阿里云 AccessKey Secret。 避免在公共场合暴露。虽然脚本中硬编码密钥方便调试,但更安全的做法是通过 Zabbix Server 运行用户的环境变量或其配置文件来管理密钥。
- 限制脚本文件的权限,仅允许 Zabbix 运行用户读取和执行。
评论前必须登录!
注册