购买谷歌云账号:利用Cloud Scheduler配合云功能定时自动切换VM虚拟机

cloud 2026-05-30 阅读 5
1

      在日常的云端运维中,很多团队都会遭遇一个让人肉疼的“预算黑洞”:服务器空转。

比如公司的开发环境、测试环境或者是内部的报表系统,通常只有在白天工作时间的 8 到 10 个小时内有人使用。但因为运维懒得去折腾、或者经常下班忘了关机,这些服务器往往 24 小时、365 天无休止地在后台疯狂开机空转。

在 Google Cloud (GCP) 的计费模式里,虚拟机(Compute Engine)是按秒和实例规格算钱的。这意味着,如果你下班不关机,一整晚白白浪费的服务器费用,可能直接占到了你单月账单的 60% 以上

传统的做法是写一个复杂的 Shell 脚本,配上本地的 cron 定时任务。但本地机器一旦断网、断电,脚本就会漏跑。

在谷歌云的现代化生态里,有一个堪称优雅的无服务器(Serverless)黄金组合:利用 Cloud Scheduler(云计划任务)配合 Cloud Functions(云功能)。它就像是一个全自动的“云端开关柜”,你只需要动动嘴皮子写几行排班表,谷歌就会在后台不占用任何服务器的前提下,秒级帮你完成服务器的定时开断。

今天我们拒绝任何官方说教套话,直接从纯实战出发,手把手带你焊死这套大厂级的定时省钱防线。

第一阶段:深度拆解,云端定时开关的“三维世界模型”

在动手写代码之前,你必须在脑子里建立起这套自动化运维流转的物理模型。整套流水线由三个核心组件无缝组合:

  1. 云端闹钟(Cloud Scheduler):完全托管的定时器(相当于云端 crontab)。你用标准的 Linux Cron 语法告诉它:“每天早上 9 点叫我,每天晚上 8 点叫我”。它按时按点就会往外发射一个信号。
  2. 秘密信使(Pub/Sub 消息队列):一个安全的内网无线电台。闹钟响了之后,会把一个简单的指令(比如 start 或 stop)打包投递到电台的某个频道里。
  3. 电工机器人(Cloud Functions):谷歌的轻量级无服务器函数。它平时处于完全休眠状态(0 成本)。一旦听到电台里有对应的指令,它会瞬间在后台“起尸”0.5 秒,调用谷歌云的 API 把目标虚拟机一键开机或关机,然后继续原地物理销毁。

第二阶段:实战前夜——为机器人开辟合法身份(IAM)

在让 Cloud Functions 去动服务器之前,我们必须坚决贯彻“最小权限原则”,给它办一张合法的特权工作证,防止它权限过大误伤了其他核心资产。

  1. 登录 GCP 控制台,导航到 “IAM 和管理” -> “服务账号(Service Accounts)”。
  2. 点击 “创建服务账号”,起名叫 vm-timer-executor。
  3. 精准灌注最小角色:在角色赋予页面,搜索并选择 “Compute Instance Admin (v1)”(虚拟机实例管理员)。注:如果为了更严苛的安全,你可以自定义一个只包含 compute.instances.start 和 compute.instances.stop 的自定义角色。
  4. 点击完成。

第三阶段:实战演练一——编写 Cloud Functions 核心开关代码

我们来到核心计算战场。我们要写一段极简的 Node.js 代码,让它能接收暗号并对服务器下达指令。

  1. 搜索并进入 Cloud Functions(云功能) 页面,点击 “创建函数”。
  2. 基础设置:函数名称:vm-auto-switcher。区域(Region):选择离你虚拟机最近的地域(如 asia-east1 台湾)。触发器类型(Trigger):下拉菜单选择“Cloud Pub/Sub”。点击创建新主题,起名叫 vm-timer-topic。
  3. 运行时参数调整:展开下方的“运行时、构建、连接和安全设置”,在服务账号一栏,必须把默认账号切掉,精准选择我们在第二阶段建好的 vm-timer-executor。

点击下一步,进入代码编辑器。运行环境选择 Node.js 20(或者任何你熟悉的语言)。

index.js 里的代码全部清空,贴入以下大厂生产环境标准的硬核控制代码:

JavaScript


const Compute = require('@google-cloud/compute');
const compute = new Compute();

exports.manageVmStatus = async (cloudEvent) => {
  // 1. 强行解包从 Pub/Sub 电台传过来的加密无线电信号
  const base64Data = cloudEvent.data.message.data;
  const jsonString = Buffer.from(base64Data, 'base64').toString();
  const payload = JSON.parse(jsonString);

  // 2. 精准提取设计图纸:你要动哪里的哪台机器?你想让它干嘛?
  const { zone, instanceName, action } = payload; 
  
  if (!zone || !instanceName || !action) {
    console.error('【灾难报错】传参缺失!必须包含 zone, instanceName 和 action!');
    return;
  }

  const zoneObj = compute.zone(zone);
  const vm = zoneObj.vm(instanceName);

  console.log(`【自动化运维激活】正在尝试对位于 ${zone} 的虚拟机 [${instanceName}] 执行 [${action}] 操作...`);

  try {
    if (action.toLowerCase() === 'start') {
      // 执行一键开机
      await vm.start();
      console.log(`【成功】虚拟机 [${instanceName}] 开机指令下发成功,正在全速唤醒中!`);
    } else if (action.toLowerCase() === 'stop') {
      // 执行一键安全关机
      await vm.stop();
      console.log(`【成功】虚拟机 [${instanceName}] 关机指令下发成功,开始安全断电!`);
    } else {
      console.warn(`【警告】无法识别的操作指令: ${action}。本函数只支持 start 或 stop。`);
    }
  } catch (error) {
    console.error(`【物理失败】执行过程中遭遇报错: ${error.message}`);
  }
};

顺手把旁边的 package.json 修改为包含谷歌官方 Compute 库的依赖:

JSON


{
  "dependencies": {
    "@google-cloud/compute": "^4.0.0",
    "@google-cloud/cloudevents-conformance": "^0.2.2"
  }
}

把右上角的“要执行的函数(Entry point)”修改为:manageVmStatus。点击 “部署(Deploy)”

第四阶段:实战演练二——配置 Cloud Scheduler 焊死定时发令枪

函数部署完后,它就像是一个静静等待暗号的特工。现在,我们要去建两个云端闹钟,一个负责早上叫它开机,一个负责晚上催它睡觉。

搜索进入 Cloud Scheduler(云计划任务) 页面。

1. 闹钟一:配置周一至周五早上 8:30 全速开机

点击 “创建作业(Create job)”

  • 名称:cron-start-dev-vm。
  • 频次(Frequency):输入标准的 Linux Cron 表达式:30 8 * * 1-5。(翻译:每周一到周五的早上 8 点 30 分触发)。
  • 时区:选择你本地的主时区(如中国上海时间)。
  • 目标类型(Target type):选择 Pub/Sub。
  • 主题(Topic):选择我们刚才建好的 vm-timer-topic。
  • 消息体(Message body):这是灌入机器人的核心 Payload,精准贴入以下 JSON 指令:JSON{ "zone": "asia-east1-a", "instanceName": "my-dev-workstation", "action": "start" }

点击创建。

2. 闹钟二:配置周一至周五晚上 20:30 强行关机

再次点击创建作业:

  • 名称:cron-stop-dev-vm。
  • 频次(Frequency):输入 30 20 * * 1-5。(翻译:每周一到周五的晚上 20 点 30 分触发)。
  • 目标类型:Pub/Sub,主题依然是 vm-timer-topic。
  • 消息体(Message body):把 action 改成关机指令:JSON{ "zone": "asia-east1-a", "instanceName": "my-dev-workstation", "action": "stop" }

点击创建。至此,全自动开闭合的闭环铁丝网已经彻底锁死。

第五阶段:见证奇迹的现场——“肉身按压”手动测试演练

配置完了,难道我们要一直傻等到晚上八点半去看它起不起效吗?大厂运维从来不凭运气赌博,我们直接在现场进行“人工催化测试”。

  1. 确保你那台名叫 my-dev-workstation 的虚拟机当前正处于绿色运行状态(Running)。
  2. 来到 Cloud Scheduler 列表页面。
  3. 找到那个负责关机的 cron-stop-dev-vm 任务,点击它右侧的三个点,毫不犹豫选择 “强制运行(Force run)”。

点击的瞬间,Cloud Scheduler 会强行绕过时间限制,往 Pub/Sub 里拍进一发关机信号。

这时候,你立刻切回到 Compute Engine 虚拟机列表。你会神奇地发现,原本亮着绿灯的那台服务器,其状态图标在没有人工干预的前提下,瞬间变成了黄色的 Stopping,几秒钟后彻底变灰进入 Terminated(已关机)休眠状态。

去函数的 Logs(日志) 大屏里看一眼,里面清清楚楚地印着我们刚才写的代码痕迹:【成功】虚拟机 [my-dev-workstation] 关机指令下发成功,开始安全断电!

大功告成!从此以后,这台机器会像规律作息的打工人一样,到点打卡开机,到点强制睡觉。

第六阶段:商业级自动化运维的避坑血泪史

这套无服务器架构用起来爽快无比,省钱效果立竿见影。但要在真正的企业级大盘环境里稳定活下来,作为首席架构师,你必须立刻对方案进行边界加固,防范以下两个隐形大坑:

1. 致命的“本地盘数据灰飞烟灭”隐患(GCP 特有深坑)

很多新手开虚拟机时,贪图读写速度,会在机器里挂载 局部 SSD(Local SSD) 或者给系统配置为不可持续的非持久性磁盘。

  • 灾难发生:在 GCP 的底层逻辑里,如果你调用 vm.stop() 执行物理关机,挂载在这台机器上的所有 Local SSD 里面的数据,在断电的瞬间会被谷歌从物理硬件上彻底擦除抹清。 只有挂载标准持久盘(Persistent Disk)的数据才能在关机后保留。
  • 架构师避坑规范:凡是要加入定时开关机队列的服务器,内部严禁存放任何未做多活备份的 Local SSD 临时核心数据。 确保全盘走 Persistent Disk 资产。

2. 警惕“深夜加班狗”的哀嚎(人性化熔断机制)

自动化太硬核了,有时候也会带来负面反馈。比如某个周五晚上八点半,全组开发为了赶一个紧急项目正在服务器里疯狂改 Bug,结果八点半一到,Cloud Scheduler 极其敬业且冷酷无情地一键把服务器给拉闸断电了,导致开发写了一半的代码直接断联丢包,全组直接心态崩溃。

  • 硬核人性化调优:不要在代码里盲目直接下达 vm.stop()。
  • 高级解法:在关机代码执行前,让函数先执行一步内部探测(比如通过 SSH 或者是监控指标盘查当前服务器的 CPU 使用率或网络内网连接数)。
  • 如果发现 CPU 占用率仍然大于 20%(说明有人在压测或者加班),函数自动发送一条飞书/钉钉通知:“监测到加班迹象,本次深夜关机自动跳过,延时一小时后再盘查”。代码留有一线温情,才是成熟运维架构师的最高修养。

总结

利用 GCP Cloud Scheduler 配合 Cloud Functions 玩转定时自动切换虚拟机,核心的工业级精髓其实就在于十六个字:定时发令,无线投递,函数接单,温情熔断

你彻底告别了过去肉身盯防、下班后还要提心吊胆用手机连 VPN 去手工关服务器的原始状态。用完全免费的 Serverless 算力,去死死扣住每一枚不该浪费的云端硬币。让机器去管理机器,这才是现代云原生时代最地道、最优雅的省钱姿势。

1
← 返回新闻中心