系统与运维

搬瓦工 KiwiVM API 入门指南:如何用只读接口安全监控流量与 VPS 运行状态

阅读要点: 不想频繁登录网页控制面板查看流量余额?搬瓦工(BandwagonHost)为每台 VPS 都配备了独立的宿主机级 KiwiVM API。本文带你从最安全的只读端点切入,使用 Python 与 curl 自动化抓取月度流量消耗、计费重置日与实时负载,在享受自动化运维便利的同时筑牢凭据安全防线。

VPSMap 编辑整理 · 内容更新 2026-10-19 · 25 分钟阅读 · 纯文本版本

管理跨地域、多线路的高性能 VPS 时,频繁打开浏览器登录控制台逐台查看状态,不仅繁琐,也无法融入现代自动化运维体系。许多站长和开发者选购搬瓦工(BandwagonHost),看中的不仅是其在洛杉矶 DC9/DC6、日本大阪/东京以及欧洲阿姆斯特丹等核心机房部署的高规格 CN2 GIA、CMIN2 与联通 9929/10099 优质回国网络,更在于其底层搭载的自主研发控制系统——KiwiVM。

KiwiVM 不仅是一个功能完备的网页控制台,更为每一个 VPS 实例提供了独立的底层管理 API。这意味着你可以无需登录 SSH、无需在操作系统内部安装复杂的第三方探针,就能直接从虚拟化宿主机(Hypervisor)层级提取精确的流量消耗、硬件资源使用率和节点健康状态。

然而,KiwiVM API 是一把“双刃剑”。由于其管理权限直达宿主机控制平面,包含关机、重启、重置 root 密码乃至全盘重装等毁灭性操作,将管理 API 引入自动化管线的第一道铁律,就是始终从只读查询(Read-Only Query)开始。本文将为你拆解 KiwiVM API 的鉴权逻辑、核心只读端点,并提供生产级自动化监控脚本与安全最佳实践。


为什么 KiwiVM API 是搬瓦工的一大核心价值?#

大多数面向海外或跨境业务的 VPS 服务商,其 API 设计往往走向两个极端:要么完全不提供底层 API,运维全靠网页点击;要么采用复杂的公有云多租户 IAM 体系,门槛高且调用繁重。搬瓦工的 KiwiVM 则走出了一条极其实用的路线:

  1. 实例级独立隔离:每台 VPS 拥有专属的虚拟环境编号(VEID)与唯一的 API Key。单台实例的凭据互不干扰,适合精细化分工与自动化脚本部署。
  2. 真正的带外管理(Out-of-Band):KiwiVM API 直接与物理宿主机管理前端通信。即便你的 VPS 系统遭遇高负载死锁、内存溢出(OOM)、防火墙规则配置错误导致 SSH 失联,API 依然能够正常返回数据或执行硬件级指令。
  3. 精准的计费与流量看板:在高速跨境链路中,流量是非常宝贵的核心资产。搬瓦工的高性能套餐(如 2.5 Gbps 至 10 Gbps 上行大带宽)能提供极佳的网络吞吐,通过 API 实时监控流量消耗百分比,可以从容设置报警阈值,避免超出月度配额导致停机。

如果你正在评估搭载优质线路的高性能实例,以下几款带有丰富机房迁移权限和充沛带宽的热门套餐非常适合搭建自动化运维节点:


认识 KiwiVM API 的权限体系与安全边界#

在接入任何脚本之前,必须清晰建立对密码与凭据的分级认知。在搬瓦工的运维生态中,存在四套彼此独立的凭据系统:

凭据类型控制层级认证要求典型用途
官网账户密码商业结算层用户名、密码、双因素认证(2FA)充值、续费、升级配置、工单支持
KiwiVM 面板密码虚拟化管理层独立管理账号密码、图形验证码网页端开机、关机、快照、重装系统
系统 root 密码 / SSH Key操作系统层SSH 客户端密钥或终端交互密码登录 Linux 操作系统、部署业务代码
KiwiVM API Key宿主机接口层纯参数匹配,无需交互,无 2FA程序化调用底层 API 进行生命周期管控

[!CAUTION] 高危警示:KiwiVM API Key 不受网页端登录验证码或两步验证(2FA)保护。只要网络请求携带合法的 veid 和 api_key 发往官方端点,宿主机就会无条件执行命令。因此,API Key 必须视同根凭据严加保管,绝不可提交至公开 Git 仓库或明文记录在未经保护的脚本中。


核心只读端点与高危写端点对比#

KiwiVM API 的接口服务器主域名为 api.64clouds.com,全线强制启用 HTTPS 通信。为了保障自动化程序的安全性,我们应当对接口进行“只读/写操作”严格分类:

推荐的只读端点(Read-Only Endpoints)#

  1. /v1/getServiceInfo(轻量元数据)

    • 系统开销:极低(直接读取数据库缓存)。
    • 关键返回值:当前机房位置、IP 列表、操作系统模板、SSH 端口、plan_monthly_data(月度总配额字节数)、data_counter(已用流量字节数)、data_next_reset(下次流量重置时间戳)。
    • 适用场景:定时抓取流量进度、计算重置倒计时、健康状态仪表盘展示。
  2. /v1/getLiveServiceInfo(实时硬件穿透抓取)

    • 系统开销:中等(穿透至宿主节点抓取实时态)。
    • 关键返回值:虚拟机虚拟化类型(vm_type)、物理宿主机节点名称、当前系统平均负载(load_average)、实时物理内存与 SWAP 占用、网络实时收发包统计。
    • 适用场景:定期排障检测、带外负载告警、主机假死探测。
  3. /v1/getUsageGraphs(历史监控图表)

    • 关键返回值:CPU、内存、网络 I/O 历史图表数据与绘制资源。

必须在监控代码中坚决排除的高危写端点#

在编写自动化监控或巡检脚本时,严禁在代码中出现任何写操作接口,包括:

  • restart / start / stop / kill(电源与进程强制控制)
  • reinstallOS(一键擦除全盘并重装操作系统)
  • resetRootPassword(重置 Linux 管理员密码)
  • snapshot/*(快照创建与回滚)

遵循“最小权限”工程规范,只引入只读端点,可以彻底避免因脚本逻辑缺陷或参数拼写失误而造成生产环境误停机。


核心原则:为什么严禁用 GET 传递 API 凭据?#

在 KiwiVM 的后台示例中,常以简化的 GET 请求展示用法(如 https://api.64clouds.com/v1/getServiceInfo?veid=123456&api_key=your_key)。这仅供快速测试,切勿在正式环境中使用 GET 请求!

使用 HTTP GET 传递密钥存在不可逆的泄露风险:

  • 系统进程树暴露:使用 curl "https://...api_key=..." 时,命令行参数会被同服务器或本地的 ps aux 进程监控抓取。
  • 网络与代理日志留痕:GET 请求的 Query String 会完整记录在网关、代理服务器(如 Squid、Nginx)、透明代理和浏览器历史记录中。
  • HTTP 引用泄露(Referer):若在网页前端或调试面板中触发带参数的 URL,该 URL 极易通过 Referer 标头传递给第三方服务。

标准做法:一律采用 HTTP POST 方法,将 veid 和 api_key 封装在请求体(Body)中,通过 Content-Type: application/x-www-form-urlencoded 发送,配合端到端 TLS 加密,确保网络层与系统层均不留下明文痕迹。


极简实战:使用 curl 快速进行 POST 只读测试#

在 Linux 终端中,你可以通过单行 curl 命令安全获取实例的流量和状态数据(以 POST 方式):

bash
curl -s -X POST \
  -d "veid=YOUR_VEID&api_key=YOUR_API_KEY" \
  https://api.64clouds.com/v1/getServiceInfo

返回的 JSON 数据包含该实例的完整元数据:

json
{
  "vm_type": "kvm",
  "hostname": "my-vps",
  "node_ip": "...",
  "plan_monthly_data": 1073741824000,
  "data_counter": 85899345920,
  "data_next_reset": 1730419200,
  "ip_addresses": ["..."],
  "error": 0
}

只要返回结果中 error: 0,就代表凭据核验成功、接口调用正常。


生产级 Python 巡检脚本(纯标准库,开箱即用)#

为了方便将监控无缝集成至定时任务(Cron)或个人管理后台,以下提供一份经过安全加固的生产级 Python 3 脚本。该脚本:

  • 完全基于 Python 标准库构建,无需安装 requests 等第三方库,降低依赖维护与供应链风险;
  • 凭据优先从系统环境变量读取,若未设置则启动交互式无回显密码输入,绝不硬编码;
  • 严格限制请求目标域名与只读路径,杜绝 SSRF 与参数注入;
  • 自动将原始字节转换为直观的 GiB/MiB 规格,自动格式化时间戳并计算剩余流量比例。
python
#!/usr/bin/env python3
"""
BandwagonHost KiwiVM API 生产级只读巡检工具
遵循最小权限与防御性编码规范:仅调用 getLiveServiceInfo 与 getServiceInfo 只读端点。
"""

import datetime
import getpass
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
from typing import Any, Dict, Tuple


EXPECTED_HOST = "api.64clouds.com"
READONLY_ENDPOINT = "/v1/getLiveServiceInfo"


def get_credentials() -> Tuple[str, str]:
    """
    安全提取 API 凭据:
    优先从环境变量获取,无环境变量时提示交互式掩码输入。
    """
    veid = os.environ.get("KIWIVM_VEID", "").strip()
    api_key = os.environ.get("KIWIVM_API_KEY", "").strip()

    if not veid:
        veid = input("请输入 KiwiVM VEID (纯数字): ").strip()
    if not api_key:
        api_key = getpass.getpass("请输入 KiwiVM API Key (输入隐藏): ").strip()

    if not veid.isdigit():
        sys.exit("安全校验失败: VEID 必须为纯数字格式。")
    if not api_key:
        sys.exit("安全校验失败: API Key 不能为空。")

    return veid, api_key


def format_bytes(num_bytes: int) -> str:
    """将字节大小格式化为易读的二进制单位 (GiB / MiB)"""
    gib = num_bytes / (1024**3)
    if gib >= 1.0:
        return f"{gib:.2f} GiB"
    mib = num_bytes / (1024**2)
    return f"{mib:.2f} MiB"


def format_timestamp(ts: int) -> str:
    """将 Unix 时间戳转换为本地易读时间字符串"""
    if not ts or ts <= 0:
        return "N/A"
    try:
        dt = datetime.datetime.fromtimestamp(ts, tz=datetime.timezone.utc)
        return dt.strftime("%Y-%m-%d %H:%M:%S UTC")
    except (OverflowError, OSError, ValueError):
        return str(ts)


def query_kiwivm_metrics(veid: str, api_key: str) -> Dict[str, Any]:
    """使用严格的 HTTPS POST 表单调用只读端点"""
    url = f"https://{EXPECTED_HOST}{READONLY_ENDPOINT}"

    # 校验 URL 结构,防范异常篡改
    parsed = urllib.parse.urlsplit(url)
    if parsed.scheme != "https" or parsed.netloc != EXPECTED_HOST or parsed.path != READONLY_ENDPOINT:
        sys.exit("安全阻断: 检测到非法的请求目标或路径变更。")

    # 参数封装在 POST 请求体内
    payload = urllib.parse.urlencode({"veid": veid, "api_key": api_key}).encode("utf-8")
    headers = {
        "User-Agent": "BWH-Ops-Inspector/1.0",
        "Content-Type": "application/x-www-form-urlencoded",
    }

    req = urllib.request.Request(url, data=payload, headers=headers, method="POST")

    try:
        with urllib.request.urlopen(req, timeout=15) as resp:
            if resp.status != 200:
                sys.exit(f"接口返回非预期的 HTTP 状态码: {resp.status}")
            body_text = resp.read().decode("utf-8")
            data = json.loads(body_text)
    except urllib.error.HTTPError as err:
        sys.exit(f"网络请求失败 (HTTP {err.code}): {err.reason}")
    except urllib.error.URLError as err:
        sys.exit(f"网络连接异常: {err.reason}")
    except json.JSONDecodeError:
        sys.exit("接口响应内容解析失败,非合法 JSON 格式。")

    # 校验 KiwiVM 服务端业务错误码
    if data.get("error") != 0:
        err_msg = data.get("message", "未知错误")
        sys.exit(f"KiwiVM 接口调用失败 (代码 {data.get('error')}): {err_msg}")

    return data


def print_inspection_report(data: Dict[str, Any]) -> None:
    """排版并输出只读状态报告"""
    print("\n" + "=" * 52)
    print("       搬瓦工 VPS 宿主机只读健康巡检报告")
    print("=" * 52)

    vm_type = data.get("vm_type", "kvm").upper()
    node_name = data.get("node_name", "N/A")
    load_avg = data.get("load_average", "N/A")

    print(f"架构平台与节点 : {vm_type} (宿主机: {node_name})")
    print(f"系统平均负载   : {load_avg}")

    # 内存核算 (以字节为基准)
    mem_total = data.get("plan_ram", 0)
    mem_available = data.get("mem_available_bytes", 0)
    if mem_total > 0:
        mem_used = max(0, mem_total - mem_available)
        mem_pct = (mem_used / mem_total) * 100
        print(f"内存占用状况   : {format_bytes(mem_used)} / {format_bytes(mem_total)} ({mem_pct:.1f}%)")

    # 流量额度与重置周期
    data_counter = data.get("data_counter", 0)
    monthly_quota = data.get("plan_monthly_data", 0)
    next_reset = data.get("data_next_reset", 0)

    if monthly_quota > 0:
        usage_ratio = (data_counter / monthly_quota) * 100
        remaining = max(0, monthly_quota - data_counter)
        print(f"本月已用流量   : {format_bytes(data_counter)} / {format_bytes(monthly_quota)} ({usage_ratio:.2f}%)")
        print(f"本月剩余流量   : {format_bytes(remaining)}")
    else:
        print(f"本月已用流量   : {format_bytes(data_counter)}")

    print(f"下次重置周期   : {format_timestamp(next_reset)}")
    print("=" * 52 + "\n")


if __name__ == "__main__":
    v_id, a_key = get_credentials()
    metrics = query_kiwivm_metrics(v_id, a_key)
    print_inspection_report(metrics)

快速运行示例:#

bash
# 通过环境变量静默传入凭据(避免在 Shell 历史中保存长命令)
export KIWIVM_VEID="1234567"
export KIWIVM_API_KEY="your_secret_api_key_here"

python3 kiwivm_monitor.py

自动化运维与服务条款(ToS)约束最佳实践#

将只读查询部署到定时脚本(如 Prometheus Exporter、Telegram 报警机器人、Zabbix 扩展)时,务必注意以下工程准则与服务条款要求:

1. 严格遵守调用频次,杜绝 API 滥用#

搬瓦工官方在服务条款(ToS)中明确列出了不可接受的使用行为,其中包含:

“KiwiVM API abuse (e.g. making excessive or unjustified API calls)”

KiwiVM API 服务于整个集群的宿主机管理平面,高频恶意轮询(例如每 5 秒甚至每 1 秒轮询一次)会被服务端的流量防护拦截,甚至可能导致 API 访问被限流或封禁。

  • 流量与账单指标:月度流量使用量和重置日期数据具有低频特性,建议 15 至 30 分钟 请求一次。
  • 系统健康与负载探活:如果仅用于基础带外存活监测,建议 3 至 5 分钟 轮询一次。
  • 秒级负载监控:如果你的业务需要秒级、毫秒级的精细 CPU/内存分析,请在操作系统内部部署 Node Exporter、Telegraf 或 Datadog Agent,而不是频繁轮询宿主机 API。

2. 账单重置周期不是自然月 1 号#

在做自动化配额告警时,常见的一个逻辑误区是假设流量在每月 1 号重置。 在搬瓦工系统中,流量重置严格按你的计费周期发生(例如你在 18 日订购,流量重置通常对齐每月 18 日)。请务必以 API 返回的 data_next_reset 字段(Unix 秒级时间戳)为准计算当前周期的进度,切忌直接按自然月天数粗暴换算。

3. 理解 CPU 公平使用政策(Fair Share Policy)#

官方 ToS 对各套餐设定了明确的 1 小时平均 CPU 限制(例如部分限量版为单核 30%,The Plan 为单核 45%,常规促销型为单核 25%~50%,SLA 专业版则为全核心 100% 24/7 不受限)。 当 API 返回的 load_average 偏高时,这表明操作系统内有密集计算正在发生。只要平均负载回落,宿主机的自动化限制就会即时解除。通过 API 监控负载,可以及时发现被攻击、挖矿病毒侵入或死循环任务,确保业务始终运行在健康区间。

4. API Key 的全生命周期管理#

  • 切勿轻易下载“导出所有服务及私有密钥”:KiwiVM 控制台支持将名下所有机器的 VEID 与 API Key 导出为 CSV。该文件具有至高无上的系统级控制力,绝不要将其通过微信、Telegram 传输,也不要存放在未加密的网络网盘中。
  • 一键重新生成(Regenerate):如果怀疑 API Key 发生泄漏或交接运维人员离职,只需在 KiwiVM 面板的 API 菜单下点击 Regenerate API Key,旧密钥将瞬间失效,更新配置后即可重新生效。

通过只读接口切入 KiwiVM API,你不仅能以极低的资源消耗获得宿主机级别的精准运行视图,更能让手头的搬瓦工优质海外节点发挥出企业级基础设施的自动化威力。