如何通过Google Cloud Function触发Compute Engine VM中的Python脚本(不使用启动脚本)
可行方案:无需
gcloud ssh从Cloud Function触发VM上的Python脚本 我完全理解你不想用VM启动脚本的需求——有时候我们需要按需触发脚本,而不是让脚本在VM启动时自动执行。下面是几个不需要依赖gcloud ssh命令的可行方案:
方案1:用Python SSH客户端库直接连接VM执行命令
这个方法可以让你在Cloud Function里直接通过SSH协议连接VM,执行指定的Python脚本,推荐使用OS Login来简化密钥管理,避免手动维护SSH密钥对:
前置配置:
- 启用Compute Engine的OS Login API(在Google Cloud控制台的API库中搜索启用)。
- 给Cloud Function使用的服务账号分配
roles/compute.osLogin(普通权限)或roles/compute.osAdminLogin(管理员权限)角色,确保它能通过OS Login访问VM。 - 确保VM已经启用了OS Login(可以通过
gcloud compute instances add-metadata INSTANCE_NAME --metadata enable-oslogin=TRUE命令设置)。
Cloud Function代码示例(用paramiko库):
首先需要在requirements.txt中添加依赖:paramiko>=2.12.0 google-api-python-client>=2.86.0然后编写Function代码:
import paramiko from googleapiclient.discovery import build from google.cloud import secretmanager def trigger_vm_script(request): # 配置参数 PROJECT_ID = "your-project-id" ZONE = "your-vm-zone" INSTANCE_NAME = "your-vm-name" SCRIPT_PATH = "/path/to/your/python/script.py" USERNAME = "your-oslogin-username" # 可通过gcloud compute os-login describe-profile获取 SECRET_NAME = "service-account-private-key" # 从Secret Manager读取服务账号私钥 secret_client = secretmanager.SecretManagerServiceClient() secret_path = f"projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/latest" secret_response = secret_client.access_secret_version(name=secret_path) private_key = secret_response.payload.data.decode() # 调用Compute Engine API获取VM的外部IP compute = build('compute', 'v1') instance = compute.instances().get(project=PROJECT_ID, zone=ZONE, instance=INSTANCE_NAME).execute() vm_ip = instance['networkInterfaces'][0]['accessConfigs'][0]['natIP'] # 初始化SSH客户端 ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) private_key_obj = paramiko.RSAKey.from_private_key_file(StringIO(private_key)) # 连接VM并执行脚本 ssh_client.connect( hostname=vm_ip, username=USERNAME, pkey=private_key_obj ) stdin, stdout, stderr = ssh_client.exec_command(f"python3 {SCRIPT_PATH}") # 获取执行结果 output = stdout.read().decode() error = stderr.read().decode() ssh_client.close() return f"脚本执行输出: {output}\n错误信息: {error}"注意:服务账号的私钥建议存储在Secret Manager中,避免硬编码敏感信息。
方案2:在VM上部署HTTP服务,Cloud Function通过HTTP请求触发
这个方法更简单,无需处理SSH连接,适合只需要触发脚本执行的场景:
VM端配置:
- 在VM上安装Flask,编写一个简单的API端点用来触发脚本:
# vm_flask_app.py from flask import Flask, request import subprocess app = Flask(__name__) @app.route('/run-script', methods=['POST']) def run_script(): # 执行目标Python脚本 result = subprocess.run(["python3", "/path/to/your/script.py"], capture_output=True, text=True) return { "stdout": result.stdout, "stderr": result.stderr, "returncode": result.returncode } if __name__ == '__main__': # 绑定到0.0.0.0,允许VPC内访问(搭配VPC Connector更安全) app.run(host='0.0.0.0', port=5000) - 配置VPC Connector让Cloud Function和VM处于同一个VPC网络,直接通过内部IP访问,避免暴露公网端口。
- 在VM上安装Flask,编写一个简单的API端点用来触发脚本:
Cloud Function代码示例:
在requirements.txt中添加requests:requests>=2.31.0然后编写Function代码:
import requests def trigger_vm_script(request): VM_INTERNAL_IP = "your-vm-internal-ip" VM_PORT = 5000 # 发送POST请求触发脚本 response = requests.post(f"http://{VM_INTERNAL_IP}:{VM_PORT}/run-script") if response.status_code == 200: return f"脚本执行成功: {response.json()}" else: return f"请求失败,状态码: {response.status_code}, 错误信息: {response.text}"
方案3:使用Compute Engine远程执行命令API(原生替代gcloud ssh --command)
如果你更倾向于Google Cloud原生API,不依赖第三方库,可以调用instances().executeCommand方法,这相当于gcloud compute ssh --command的API版本:
前置配置:
- 给Cloud Function的服务账号分配
roles/compute.instanceAdmin.v1角色,确保它能执行实例命令。
- 给Cloud Function的服务账号分配
Cloud Function代码示例:
from googleapiclient.discovery import build def trigger_vm_script(request): PROJECT_ID = "your-project-id" ZONE = "your-vm-zone" INSTANCE_NAME = "your-vm-name" SCRIPT_COMMAND = "python3 /path/to/your/script.py" compute = build('compute', 'v1') request_body = { "command": SCRIPT_COMMAND, "timeout": "300s" # 设置命令超时时间 } # 执行远程命令 response = compute.instances().executeCommand( project=PROJECT_ID, zone=ZONE, instance=INSTANCE_NAME, body=request_body ).execute() return f"命令执行任务ID: {response['name']}, 状态: {response['status']}"注意:这个方法不会实时返回脚本输出,你需要通过后续API调用或Stackdriver日志获取执行结果。
总结
- 如果需要实时获取脚本执行结果,**方案2(HTTP服务)**是最简单的选择,配置少且易于维护。
- 如果需要直接对VM进行更多操作(比如文件传输、多命令串联执行),**方案1(SSH客户端库)**更灵活。
- 如果偏好Google Cloud原生生态,不依赖第三方库,可以选择方案3。
内容的提问来源于stack exchange,提问作者Varun Sharma
相关产品推荐
相关产品推荐

