在GCP使用Pulumi实现VM创建后仅执行一次Bash脚本
在GCP Pulumi中实现VM创建后仅运行一次的Bash脚本
针对你需求,有两种实用方案可以实现VM创建完成后仅执行一次脚本的效果:
方法一:给启动脚本添加执行标记
利用metadata_startup_script自带的执行机制,通过文件系统标记控制核心逻辑只运行一次。脚本每次启动都会执行,但会先检查标记文件,仅在首次运行时执行核心操作:
#!/bin/bash # 定义标记文件路径,用于记录脚本是否已执行过 MARKER_FILE="/var/run/one_time_setup_completed" if [ ! -f "$MARKER_FILE" ]; then # 这里放置你的一次性任务逻辑 echo "开始执行一次性初始化..." apt update && apt install -y nginx systemctl enable --now nginx # 创建标记文件,避免后续启动重复执行 touch "$MARKER_FILE" else echo "一次性脚本已执行过,跳过本次运行" fi
在Pulumi的compute.Instance配置中,直接将上述脚本内容赋值给metadata_startup_script参数即可。
方法二:使用Pulumi Remote Exec Provisioner
通过Pulumi的远程执行功能,在VM创建完成后主动通过SSH连接执行脚本,天然只执行一次(仅在资源创建阶段触发):
以TypeScript为例,示例代码如下:
import * as gcp from "@pulumi/gcp"; import * as fs from "fs"; import * as ssh from "@pulumi/ssh"; // 创建VM实例 const vmInstance = new gcp.compute.Instance("my-single-use-vm", { machineType: "e2-micro", bootDisk: { initializeParams: { image: "debian-cloud/debian-11", }, }, networkInterfaces: [{ network: "default", accessConfigs: [{}], // 自动分配公网IP }], // 配置SSH密钥,确保Pulumi能远程连接 metadata: { sshKeys: `${process.env.USER}:${fs.readFileSync(`${process.env.HOME}/.ssh/id_rsa.pub`, "utf8")}`, }, }); // 执行一次性远程脚本 const oneTimeSetup = new ssh.RemoteExec("vm-one-time-setup", { host: vmInstance.networkInterfaces[0].accessConfigs[0].natIp, user: "debian", // 根据镜像调整用户名,Ubuntu镜像用"ubuntu" privateKey: fs.readFileSync(`${process.env.HOME}/.ssh/id_rsa`, "utf8"), script: ` #!/bin/bash echo "通过Pulumi远程执行一次性任务..." apt update && apt install -y redis-server systemctl enable --now redis-server `, }, { dependsOn: [vmInstance] }); // 确保VM创建完成后再执行
两种方案对比
- 方法一:无需额外网络依赖,脚本随VM自带,若VM保留磁盘重建,标记文件会保留,不会重复执行;缺点是脚本本身每次启动都会运行(仅跳过核心逻辑)。
- 方法二:完全只执行一次,不依赖VM启动脚本;缺点是要求Pulumi运行环境能SSH访问VM,且防火墙需开放22端口。
内容的提问来源于stack exchange,提问作者dimid
相关产品推荐
相关产品推荐

