用 API / Terraform 批量开 VPS 与自动化运维
2026-08-15 · DevCraft Studio
手动在面板一台台点机器太低效。本文讲清为什么用 Vultr/CloudCone 等官方 API 或 Terraform Provider 做基础设施即代码(IaC),批量开机、销毁,并给出密钥保管与防失控账单的成本护栏。
延伸阅读
更多相关攻略推荐:从 Git Push 到秒级上线:CI/CD 流水线与"无中断"发布、【VPS 进阶玩法精选 030】用 VPS 搭建云端 IDE(cod、连云厂商也看不到你的数据?机密计算(Confidential Com、被割裂的"云上互联网":数据主权(GDPR)、本地化存储与主权云(S、什么时候非得要独立 IPv4?便宜国外 VPS 独立 IP 适用场景。
一、手动点面板,点不动十台以上的机器
刚玩 VPS 时,在商家面板点几下开一台机器很爽。可一旦你要开 10 台做分布式爬虫、20 台做压测节点、或者按业务每天定时起一批临时机器,纯手工点面板就崩了:每台都得选机房、选系统、贴 SSH 公钥、等开通、再手动记 IP,错一台就得重来。更糟的是,机器多了之后「哪些还在跑、谁该关没关」全靠脑子记,月底账单直接吓一跳。这时候就得上基础设施即代码(IaC):把机器写成代码,一键批量开、一键批量销,状态可回放、可版本化。本文以 Vultr、CloudCone 为主,顺带提 DigitalOcean,讲清楚怎么用官方 API 和 Terraform 把开机器变成写配置。
二、为什么需要 IaC:可复现、可版本化、省人力
IaC 的核心思想就一句:把服务器当成代码来管理。好处是实打实的:
- 可复现:同样的 .tf 文件,今天跑和三个月后跑,开出来的机器一模一样,不依赖某人「当时点了啥」的记忆。
- 可版本化:配置进 Git,谁改了什么一清二楚,回滚就像 git revert。审计、协作都踏实。
- 省人力:
terraform apply一条命令顶你点一百次面板,半夜批量开测试机、跑完terraform destroy一键清空,零人工值守。 - 防漂移:Terraform 记录状态,你手动在面板改了东西它下次会纠正,基础设施不会悄悄「长歪」。
对只开一台长期稳定机器的个人用户,面板足够;但凡涉及批量、临时、多环境,IaC 就是分水岭。
三、主流厂商 API 概览
三家都提供 REST API,鉴权基本是 Bearer Token:
- Vultr:API v2,基址
https://api.vultr.com/v2,请求头带Authorization: Bearer 你的KEY。功能最全,实例、裸机、对象存储、网络、K8s 都能管。官方还有vultr-cli命令行。 - CloudCone:API 在
api.cloudcone.com,用 API Key + API Secret 组合鉴权(curl 里用-u KEY:SECRET)。主打便宜大盘和按小时计费,适合批量临时机。 - DigitalOcean:API v2,基址
https://api.digitalocean.com/v2,Bearer Token 鉴权,官方命令行doctl。生态成熟,文档友好。
用 curl 列 Vultr 可用套餐的示例(把 $VULTR_API_KEY 换成你的密钥):
curl -H "Authorization: Bearer $VULTR_API_KEY" https://api.vultr.com/v2/plans列 CloudCone 实例:
curl -u 你的APIKEY:你的APISECRET https://api.cloudcone.com/v1/instancesDigitalOcean 列 droplet:
curl -H "Authorization: Bearer $DO_TOKEN" https://api.digitalocean.com/v2/droplets四、Terraform Provider 实战:几行配置开一台
Terraform 是 HashiCorp 的 IaC 工具,用 HCL 声明式语言描述资源。Vultr 有官方 provider。先写 provider 配置:
terraform {
required_providers {
vultr = {
source = "vultr/vultr"
version = "~> 2.26"
}
}
}
provider "vultr" {
api_key = var.VULTR_API_KEY
}
variable "VULTR_API_KEY" {}密钥放 terraform.tfvars(别提交进 Git),里面写 VULTR_API_KEY = "你的真实密钥"。然后定义一个实例:
resource "vultr_instance" "web" {
label = "web-01"
plan = "vc2-1c-1gb"
region = "sgp"
os_id = 2284
enable_ipv6 = true
}
output "ip" {
value = vultr_instance.web.main_ip
}初始化并应用:
terraform init
terraform plan
terraform applyterraform plan 先预览会改什么,terraform apply 真正开机,结束会打印输出里的 IP。想销毁就 terraform destroy。os_id 2284 是 Ubuntu 24.04,region sgp 是新加坡,plan 代码可在 plans 接口里查。
五、批量开:用 count 一把开 N 台
要开 5 台做节点,不用复制 5 遍,用 count 元参数:
resource "vultr_instance" "nodes" {
count = 5
label = format("node-%d", count.index)
plan = "vc2-1c-1gb"
region = "sgp"
os_id = 2284
}这一个块会开出 node-0 到 node-4 共 5 台,terraform apply 一次搞定。需要不同机房混布,就把 region 抽成变量或用 for_each 配 map。CloudCone、DigitalOcean 也有对应 provider(或直接在脚本里调 API),思路完全一致:声明想要什么,工具负责怎么实现。
六、API 密钥的安全保管:别把钥匙交出去
API Key 等于你账户的「提款权」,泄露了别人能开机器刷爆你的卡。守则:
- 永远别把密钥写进代码提交 Git:放
terraform.tfvars(加入 .gitignore)或用环境变量,CI 里用 Secrets 注入。 - 最小权限:Vultr 可建子 API Key 限定权限范围;CloudCone 的 Key/Secret 分开保管。只给「开机/销机」权限,不给「改账户/付款」权限。
- 本地文件权限:tfvars 设
chmod 600,别放公开仓库或贴到论坛。 - 定期轮换:人员变动或怀疑泄露,立刻在面板吊销旧 Key 换新。
七、批量开/销与成本护栏:别让账单失控
自动化的反面是「脚本一跑开了 200 台忘了关」。护栏必须提前埋:
- 先用 plan 再 apply:apply 前看清楚会新建几台、花多少钱档位。
- 设预算告警:Vultr、DigitalOcean 后台都能设月预算阈值,超了发邮件,相当于闹钟。
- 临时机加生命周期:测试机用
terraform destroy或定时任务自动销,别靠记忆。 - 小范围试点:新配置先 count=1 跑通,再放大,避免一把开错配置烧一天钱。
- 用变量约束上限:把 count 抽成变量并写注释上限,CI 里加校验拒绝超大值。
八、和手工面板比,到底强在哪
对比一下就明白:
- 一致性:面板点 10 台,第 3 台容易选错系统;代码 10 台一模一样。
- 速度:面板逐台等开通;apply 并行拉起,喝口水就好。
- 可追溯:面板操作不留痕;Git 提交即审计。
- 销毁:面板得逐台找、逐台删;destroy 一键归零,账单立刻停。
代价是要学一点 HCL 和鉴权流程,但开过一次后,第二次到第 N 次都是复制粘贴改参数的事。
九、注意事项:state 文件与权限
- state 文件是命根子:
terraform.tfstate记录了「实际开了哪些资源」,删了它就认不出已有机器,可能重复创建或误删。强烈建议用远程后端(如 Vultr 对象存储 S3 后端、Terraform Cloud)存 state,别只留本地。 - state 含敏感信息:state 里可能带 IP 甚至密钥痕迹,远程后端务必设私有访问。
- 并发与锁:远程后端提供状态锁,防止两个人同时 apply 互相覆盖。
- 权限最小化:运行 Terraform 的机器只装必要 provider,API Key 权限按上文收紧。
- 变更要走 review:生产环境的 .tf 改动走 PR 审核,
plan输出贴到评审里,避免手滑。
RackNerd 这类主打便宜年付的厂商多数没有官方 Terraform provider,但一般提供 API 或允许用脚本调其下单接口;批量场景若依赖它,建议自己封装一层小脚本 + 配置文件,思路同样是「声明式 + 可复现」。
十、完整可抄的 Terraform 示例:开一批带 SSH 密钥的节点
前面都是片段,这里给一段能直接落地的完整配置:一批节点统一打同一把 SSH 公钥、共用一个资源标签,用 for_each 而非 count,这样每台机器的名字是显式键而非数字下标,删掉中间一台不会把其余机器的编号重排(这是 count 的经典坑)。
variable "VULTR_API_KEY" {}
variable "ssh_key" {
default = "ssh-ed25519 AAAA...你的公钥..."
}
variable "nodes" {
type = map(string)
default = {
web-01 = "sgp"
web-02 = "sgp"
web-03 = "nrt"
}
}
terraform {
required_providers {
vultr = {
source = "vultr/vultr"
version = "~> 2.26"
}
}
}
provider "vultr" {
api_key = var.VULTR_API_KEY
}
resource "vultr_ssh_key" "main" {
name = "ci-key"
ssh_key = var.ssh_key
}
resource "vultr_instance" "node" {
for_each = var.nodes
label = each.key
region = each.value
plan = "vc2-1c-2gb"
os_id = 2284
ssh_key_ids = [vultr_ssh_key.main.id]
}
output "ips" {
value = { for k, v in vultr_instance.node : k => v.main_ip }
}要点:for_each 的 map 里值是机房,删掉 web-02 只销毁那一台,其余两台的名字和 IP 都不变,不会像 count 那样把 node-2 重命名成 node-1;vultr_ssh_key 先声明公钥,再用 ssh_key_ids 让每台机器开机就能用你的公钥登录,省去手动贴;最后用 for 表达式把所有 IP 汇成一个 map 输出,方便灌进 Ansible 的 inventory。把变量抽到 terraform.tfvars,terraform init 后 terraform apply 即可一次性跨机房起三台节点。
十一、常见 API 错误排查:401 / 403 / 429 怎么治
脚本调 API 十有八九会撞错,按状态码对症下药,能省下大量瞎猜的时间:
- 401 Unauthorized:密钥没带或带错。检查请求头
Authorization: Bearer 你的KEY是否拼对,CloudCone 是-u KEY:SECRET而非 Bearer;确认密钥没被面板吊销、字符串前后没多打空格或换行。 - 403 Forbidden:密钥有效但权限不够,比如用只给「只读」的子 Key 去开机。去面板把对应 Key 的权限加到「实例创建 / 销毁」,或换一个全权限 Key 试一次排除法。
- 404 Not Found:接口路径或资源 ID 错。region、plan、os_id 不存在都会报这个;先用 plans 接口核对自己填的 region(如 sgp、nrt)和 plan 代码在目标机房真实有效,有时某套餐在特定机房下架。
- 409 Conflict:资源状态冲突,常见于对同一台机器并发操作(开机瞬间又去删、或两台脚本抢同一 label)。加退避重试,或把脚本改成串行排队。
- 429 Too Many Requests:触发厂商限流。Vultr 对创建类接口有速率上限,批量开几十台要自己限速,比如每开一台
sleep 2,或用队列错峰,别一个循环瞬间打爆。 - 5xx(500/502/503):服务端临时抽风,不是你的问题。指数退避重试通常能过;若持续 5xx 再开工单,附上响应里的请求 ID 和 UTC 时间戳,厂商排查更快。
调试技巧:curl 加 -i 看完整响应头与正文,加 -s -w "%{http_code}" 单独打印状态码;Terraform 失败时在命令前加 TF_LOG=DEBUG terraform apply,它能把实际发出的 HTTP 请求和收到的响应体都打出来,往往一眼就能区分是鉴权问题还是参数问题。把这套排查流程写进你团队的运维手册,新人接手脚本时少踩一半坑。