使用openstacksdk启动OpenStack实例时userdata自定义脚本未执行如何解决
OpenStack userdata 未执行问题排查与解决
代码层面问题修复
你现有代码存在两处直接导致userdata无效的逻辑问题:
- 错误传入文件路径而非文件内容:nova client的
servers.create方法要求userdata参数传入的是脚本的实际内容字符串/字节流,而非本地脚本的路径,你当前直接赋值server['file'](大概率是路径字符串),cloud-init接收到无效内容自然不会执行。 - 无效的文件存在性判断:你判断的是固定文件
instalacion_k8s_docker.sh是否存在,判断通过后还是给userdata赋值server['file'],完全没有用到这个判断结果,也没有读取文件内容。
修复后的实例创建函数参考代码:
import os def create_server(server): s = {} print("Creating "+server['compulsory']['name']+"...") s['name'] = server['compulsory']['name'] s['image'] = server['compulsory']['os'] s['flavor'] = server['compulsory']['flavor'] s['min_count'] = server['compulsory']['copyNumber'] s['max_count'] = server['compulsory']['copyNumber'] s['key_name'] = server['compulsory']['keyName'] s['availability_zone'] = server['compulsory']['availabilityZone'] s['nics'] = server['compulsory']['network'] # 读取userdata文件内容 userdata_path = server['file'] if not os.path.exists(userdata_path): print(f"错误:userdata文件{userdata_path}不存在,跳过实例创建") return print(f"读取userdata文件:{userdata_path}") with open(userdata_path, 'r', encoding='utf-8') as f: s['userdata'] = f.read() nova.servers.create(**s)
其他常见原因排查
如果修改代码后仍然不执行,按以下顺序排查:
- 检查镜像是否预装
cloud-init:只有预装了cloud-init服务且设置开机自启的镜像才会处理OpenStack传入的userdata,主流官方云镜像默认已配置,自制镜像需要手动安装并执行cloud-init clean后再制作快照。 - 检查bash脚本格式:脚本首行必须以
#!/bin/bash或#!/bin/sh开头,无语法错误,可先手动在运行中的实例内执行脚本验证可用性。 - 检查userdata大小:OpenStack默认限制userdata最大为16KB,超出后内容会被截断导致执行失败,大体积脚本建议把资源下载逻辑放到脚本内从内网存储拉取,不要直接写在userdata中。
- 查看实例内cloud-init日志:登录创建好的实例,查看
/var/log/cloud-init.log和/var/log/cloud-init-output.log两个日志文件,可以定位到脚本未执行的具体原因。 - 排除平台配置问题:可以通过OpenStack命令行工具测试userdata是否有效,排除代码外的平台配置问题:
openstack server create --image <镜像ID> --flavor <规格ID> --key-name <密钥名> --user-data ./你的脚本路径.sh --nic net-id=<网络ID> 测试实例名
内容的提问来源于stack exchange,提问作者Xurxo
相关产品推荐
相关产品推荐

