You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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密钥对:

  1. 前置配置:

    • 启用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命令设置)。
  2. 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连接,适合只需要触发脚本执行的场景:

  1. 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访问,避免暴露公网端口。
  2. 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版本:

  1. 前置配置:

    • 给Cloud Function的服务账号分配roles/compute.instanceAdmin.v1角色,确保它能执行实例命令。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 12:47:31