Packer构建Alpine镜像时Shell Provisioner修改无法持久化的问题
Packer QEMU构建Alpine镜像后Shell Provisioner修改不保留的问题
问题现象
基于Alpine Virt ISO(alpine-virt-3.20.3-x86_64.iso)使用Packer QEMU Builder构建qcow2镜像,通过boot_command执行setup-alpine完成网络和磁盘配置,Shell Provisioner脚本执行日志显示成功(输出"good"),但启动最终镜像后,脚本创建的文件、修改的配置均不存在。
相关配置与脚本
Packer配置文件(alpine.pkr.hcl)
packer { required_plugins { qemu = { version = ">= 1.0.10" source = "github.com/hashicorp/qemu" } } } source "qemu" "alpine-demo" { iso_url = "./alpine-virt-3.20.3-x86_64.iso" iso_checksum = "81df854fbd7327d293c726b1eeeb82061d3bc8f5a86a6f77eea720f6be372261" output_directory = "build" disk_image = false disk_size = "5000M" disk_interface = "virtio" format = "qcow2" accelerator = "kvm" vm_name = "alpine-minimal.qcow2" machine_type = "pc" net_device = "virtio-net" headless = false cpus = 1 boot_key_interval = "10ms" shutdown_command = "poweroff" communicator = "ssh" ssh_username = "root" ssh_password = "alpine" ssh_timeout = "10m" memory = "1024" boot_wait = "10s" boot_command = [ "<wait>root<enter><wait>", "setup-alpine<enter><wait>", "us<enter>us<enter><wait>", "<enter><wait><enter><wait><enter><wait><enter><wait5>", "alpine<enter><wait>alpine<enter><wait>", "<enter><wait5>", "<enter><wait><enter><wait><enter><wait><enter><wait>", "yes<enter><wait>", "<enter><wait5>", "vda<enter><wait>sys<enter><wait>y<enter><wait20>", ] } build { name = "learn-packer" sources = ["source.qemu.alpine-demo"] provisioner "shell" { script = "./provisioner.sh" } }
Shell Provisioner脚本(provisioner.sh)
#!/bin/sh set -ex touch createdfile echo "JAJAJ" > createdfile if [ -f ./createdfile ]; then echo "good" else echo "bad" fi
构建与启动命令
- 构建命令:
PACKER_LOG=1 packer build ./alpine.pkr.hcl - 启动镜像命令:
qemu-system-x86_64 -name alpinelinux3.19-minimal \ -machine type=pc,accel=kvm \ -cpu host \ -m 512M \ -enable-kvm \ -nic user \ -drive file=./build/alpine-minimal.qcow2,if=virtio,media=disk \ -boot c
问题原因
Alpine Virt ISO启动后默认运行在RAM磁盘中,setup-alpine完成磁盘分区和系统安装后,不会自动切换到磁盘系统。此时Packer通过SSH连接的会话仍处于RAM环境,所有脚本修改都保存在内存中,执行poweroff关机后,内存中的数据全部丢失,未写入磁盘镜像。
解决方案
1. 修改boot_command,添加磁盘系统切换与重启步骤
在原boot_command的最后添加以下内容,确保系统重启后切换到磁盘运行:
"<wait>", "mount /dev/vda2 /mnt<enter><wait>", "echo '/dev/vda2 / ext4 defaults 0 0' > /mnt/etc/fstab<enter><wait>", "echo '/dev/vda1 /boot vfat defaults 0 2' >> /mnt/etc/fstab<enter><wait>", "umount /mnt<enter><wait>", "reboot<enter><wait30>",
注:这里的
vda1是EFI分区,vda2是根分区,对应setup-alpine中选择的sys磁盘布局。
2. 调整Packer连接与等待参数
- 将
ssh_timeout修改为"15m",给重启后的系统足够时间启动SSH服务 - 将
boot_wait调整为"20s",确保系统重启完成后再尝试SSH连接
3. 修改关机命令为安全关机
将shutdown_command = "poweroff"改为:
shutdown_command = "halt -p"
确保系统同步磁盘数据后再关机,避免数据丢失。
4. 脚本使用绝对路径操作文件
修改provisioner.sh,使用绝对路径创建文件,避免当前路径问题:
#!/bin/sh set -ex touch /root/createdfile echo "JAJAJ" > /root/createdfile if [ -f /root/createdfile ]; then echo "good" else echo "bad" fi
内容的提问来源于stack exchange,提问作者ivans
相关产品推荐
相关产品推荐

