購買谷歌雲賬號:利用Cloud Scheduler配合雲功能定時自動切換VM虛擬機

雲端 2026-05-30 阅读 12
3

在日常的雲端運維中,很多團隊都會遭遇一個讓人肉疼的「預算黑洞」:

服務器空轉。

比如公司的開發環境、測試環境或者是內部的報表系統,通常只有在白天工作時間的 8 到 10 個小時內有人使用。 但因為運維懶得去折騰、或者經常下班忘了關機,這些服務器往往 24 小時、365 天無休止地在後台瘋狂開機空轉。

在 Google Cloud (GCP) 的計費模式里,虛擬機(Compute Engine)是按秒和實例規格算錢的。 這意味著,

如果你下班不關機,一整晚白白浪費的服務器費用,可能直接占到了你單月賬單的 60% 以上

傳統的做法是寫一個複雜的 Shell 腳本,配上本地的

Cron

定時任務。 但本地機器一旦斷網、斷電,腳本就會漏跑。

在谷歌雲的現代化生態裡,有一個堪稱優雅的無伺服器(Serverless)黃金組合:

利用 Cloud Scheduler(雲計劃任務)配合 Cloud Functions(雲功能)

。 它就像是一個全自動的「雲端開關櫃」,你只需要動動嘴皮子寫幾行排班表,谷歌就會在後台不占用任何服務器的前提下,秒級幫你完成服務器的定時開斷。

今天我們拒絕任何官方說教套話,直接從純實戰出發,手把手帶你焊死這套大廠級的定時省錢防線。

第一階段:深度拆解,雲端定時開關的「三維世界模型」

在動手寫代碼之前,你必須在腦子裡建立起這套自動化運維流轉的物理模型。 整套流水線由三個核心組件無縫組合:

雲端鬧鐘(Cloud Scheduler):完全託管的定時器(相當於雲端 crontab)。 你用標準的 Linux Cron 語法告訴它:「每天早上 9 點叫我,每天晚上 8 點叫我」。 它按時按點就會往外發射一個信號。

秘密信使(Pub/Sub 消息隊列):一個安全的內網無線電台。 鬧鐘響了之後,會把一個簡單的指令(比如 start 或 stop)打包投遞到電台的某個頻道里。

電工機器人(Cloud Functions):谷歌的輕量級無服務器函數。 它平時處於完全休眠狀態(0 成本)。 一旦聽到電台裡有對應的指令,它會瞬間在後台「起屍」0.5 秒,調用谷歌雲的 API 把目標虛擬機一鍵開機或關機,然後繼續原地物理銷毀。

第二階段:實戰前夜--為機器人開闢合法身份(IAM)

在讓 Cloud Functi

Ons 去動服務器之前,我們必須堅決貫徹「最小權限原則」,給它辦一張合法的特權工作證,防止它權限過大誤傷了其他核心資產。

登錄 GCP 控制台,導航到 「IAM 和管理」 -> 「服務賬號(Service Accounts)」。

點擊 「創建服務賬號」,起名叫 vm-timer-executor。

精準灌注最小角色:在角色賦予頁面,搜索並選擇 「Compute Instance Admin (v1)」(虛擬機實例管理員)。 註:如果為了更嚴苛的安全,你可以自定義一個只包含 compute.instances.start 和 compute.instances.stop 的自定義角色。

點擊完成。

第三階段:實戰演練一--編寫 Cloud Functions 核心開關代碼

我們來到核心計算戰場。 我們要寫一段極簡的 Node.js 代碼,讓它能接收暗號並對服務器下達指令。

搜索並進入 Cloud Functions(雲功能) 頁面,點擊 「創建函數」。

基礎設置:函數名稱:vm-auto-switcher。 區域(Region):選擇離你虛擬機最近的地域(如 asia-east1 台灣)。 觸發器類型(Trigger):下拉菜單選擇「Cloud Pub/Sub」。 點擊創建新主題,起名叫 vm-timer-topic。

運行時參數調整:展開下方的「運行時、構建、連接和安全設置」,在服務賬號一欄,必須把默認賬號切掉,精準選擇我們在第二階段建好的 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 jsonS

Tring = Buffer.from(base64Data, 'base64').toString();

Const payload = JSON.parse(jsonString);

// 2. 精準提取設計圖紙:你要動哪裡的哪台機器? 你想讓它幹嘛?

Const { zone, instanceName, action } = payload;

如果! Zone ||! InstanceName ||! Action) {

Console.error('【災難報錯】傳參缺失! 必須包含 zone, instanceName 和 action! ');

返回;

}

Const zoneObj = compute.zone(zone);

Const vm = zoneObj.vm(instanceName);

Console.log('【自動化運維激活】正在嘗試對位於 ${zone} 的虛擬機 [${instanceName}] 執行 [${action}] 操作...');

嘗試 {

If (action.toLowerCase() === 'start') {

// 執行一鍵開機

Await vm.start();

Console.log('【成功】虛擬機 [${instanceName}] 開機指令下發成功,正在全速喚醒中! ');

} Else if (action.toLowerCase() === 'stop') {

// 執行一鍵安全關機

Await vm.stop();

Console.log('【成功】虛擬機 [${instanceName}] 關機指令下發成功,開始安全斷電! ');

} 否則 {

Console.warn('【警告】無法識別的操作指令: ${action}。 本函數只支持 start 或 stop。 ');

}

} 捕捉 (錯誤) {

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-workst

Ation", "action": "stop" }

點擊創建。 至此,全自動開閉合的閉環鐵絲網已經徹底鎖死。

第五階段:見證奇蹟的現場--「肉身按壓」手動測試演練

配置完了,難道我們要一直傻等到晚上八點半去看它起不起效嗎? 大廠運維從來不憑運氣賭博,我們直接在現場進行「人工催化測試」。

確保你那台名叫 my-dev-workstation 的虛擬機當前正處於綠色運行狀態(Running)。

來到 Cloud Scheduler 列表頁面。

找到那個負責關機的 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)的數據才能在關機後保留。

架構師避坑規範:凡是要加入定時開關機隊列的服務器,內部嚴禁存放任何未做多活備份的 Loc

Al SSD 臨時核心數據。 確保全盤走 Persistent Disk 資產。

2. 警惕「深夜加班狗」的哀嚎(人性化熔斷機製)

自動化太硬核了,有時候也會帶來負面反饋。 比如某個周五晚上八點半,全組開發為了趕一個緊急項目正在服務器里瘋狂改 Bug,結果八點半一到,cloud Scheduler 極其敬業且冷酷無情地一鍵把服務器給拉閘斷電了,導致開發寫了一半的代碼直接斷聯丟包,全組直接心態崩潰。

硬核人性化調優:不要在代碼里盲目直接下達 vm.stop()。

高級解法:在關機代碼執行前,讓函數先執行一步內部探測(比如通過 SSH 或者是監控指標盤查當前服務器的 CPU 使用率或網絡內網連接數)。

如果發現 CPU 占用率仍然大於 20%(說明有人在壓測或者加班),函數自動發送一條飛書/釘釘通知:「監測到加班跡象,本次深夜關機自動跳過,延時一小時後再盤查」。 代碼留有一線溫情,才是成熟運維架構師的最高修養。

總結

利用 GCP Cloud Scheduler 配合 Cloud Functions 玩轉定時自動切換虛擬機,核心的工業級精髓其實就在於十六個字:

定時發令,無線投遞,函數接單,溫情熔斷

你徹底告別了過去肉身盯防、下班後還要提心吊膽用手機連 VPN 去手工關服務器的原始狀態。 用完全免費的 Serverless 算力,去死死扣住每一枚不該浪費的雲端硬幣。 讓機器去管理機器,這才是現代雲原生時代最地道、最優雅的省錢姿勢。

3
← 返回新闻中心