如何从Terraform向cloud-init调用的bash脚本传递参数
解决方案
问题根因
原有写法存在两个核心错误:
base64encode(file(var.bootstrap_file) "123456")仅做简单字符串拼接,将脚本内容和密码拼成了一段连续文本,并不会给脚本传入位置参数,cloud-init执行user-data中的shell脚本时,无法识别拼接在尾部的字符串为$1参数。- 直接拼接明文密码存在泄露风险,且Jupyter要求服务配置中传入哈希后的密码值,直接传明文无法正常认证。
不需要使用remote-exec,全程通过cloud-init的user-data通道即可实现,无需向Terraform配置传入SSH私钥,无额外安全风险。
第一步:调整Terraform配置
放弃file+字符串拼接的写法,使用Terraform内置的templatefile函数完成脚本参数渲染,将密码定义为敏感变量避免日志泄露。
- 先在
variables.tf中新增密码变量:
variable "jupyter_password" { type = string description = "Jupyter Notebook访问密码" sensitive = true # 标记为敏感值,Terraform执行时不会在输出日志中打印明文 }
- 修改实例资源中的metadata配置:
resource "oci_core_instance" "jupyterlab_instance" { # 保留原有其他实例配置(可用性域、镜像、规格、子网等) metadata = { ssh_authorized_keys = var.ssh_public_key_file user_data = base64encode(templatefile("${path.module}/bootstrap.sh", { jupyter_plain_password = var.jupyter_password })) } }
执行部署时通过-var="jupyter_password=你的实际密码"或者.tfvars文件传入密码值即可。
第二步:修改bootstrap.sh脚本
脚本头部增加shebang声明,将原位置参数$1替换为模板占位符,在脚本内部完成Jupyter密码哈希生成,避免明文写入systemd配置。修改后完整内容如下:
#!/bin/bash function systemd_jupyter_instance() { echo "setting up systemd for jupyter at 0.0.0.0:8888" # 脚本内生成Jupyter要求的哈希密码,根据安装的Jupyter版本选择对应导入路径 # 新版Jupyter使用jupyter_server.auth模块,老版本Notebook可替换为from IPython.lib.security import passwd password_hash=$(python3 -c "from jupyter_server.auth import passwd; print(passwd('${jupyter_plain_password}'))") mkdir -p /etc/jupyter /home/opc cat <<EOF > /etc/systemd/system/jupyterInst.service [Unit] Description=Jupyter instance After=network.target [Service] User=opc Group=opc WorkingDirectory=/home/opc ExecStart=/usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8888 --NotebookApp.password=${password_hash} Restart=always RestartSec=5 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl is-active --quiet jupyterInst && systemctl stop jupyterInst systemctl enable --now jupyterInst systemctl status jupyterInst --no-pager } function main() { # 如果镜像未预装Jupyter,可在此处补充安装命令,例如: # pip3 install jupyter systemd_jupyter_instance } main
注意事项
- bootstrap.sh第一行必须保留
#!/bin/bash声明,否则cloud-init可能无法正确识别脚本执行器。 templatefile渲染时会自动将${jupyter_plain_password}占位符替换为传入的实际密码值,渲染完成后生成完整可执行脚本,无需额外传参。- 整个配置流程不需要建立SSH连接到实例,完全通过云实例元数据通道传递配置,不存在私钥泄露风险。
内容的提问来源于stack exchange,提问作者masterfly
相关产品推荐
相关产品推荐

