packer(7)provisioner shell-local vs shell区别

在 HashiCorp Packer 中,provisioner "shell-local"provisioner "shell" 是两种不同的配置器(provisioner),它们的主要区别在于执行脚本的位置不同。


1. provisioner "shell-local"

定义:

  • shell-local 是一个在本地机器(即运行 Packer 的机器)上执行 shell 脚本的配置器
  • 它不会在目标构建环境(例如虚拟机或容器)中运行脚本,而是直接在 Packer 的主机上执行。

特点:

  • 运行位置:本地主机(你的 Mac、Linux 或 Windows 机器)。
  • 用途:通常用于在构建流程中执行一些与目标镜像无关的本地任务,例如:
    • 在本地生成配置文件或临时文件。
    • 调用本地工具(如 AWS CLI)上传文件。
    • 运行预处理或后处理脚本。
  • 限制:无法直接影响目标构建环境(如安装软件到虚拟机或容器中)。

示例:

1
2
3
provisioner "shell-local" {
inline = ["echo 'Running on local machine!'", "ls -la"]
}
  • 这段代码会在运行 Packer 的本地机器上打印消息并列出目录内容,而不是在构建的镜像中执行。

2. provisioner "shell"

定义:

  • shell 是一个在目标构建环境(即 Packer 正在构建的机器镜像,例如虚拟机、Docker 容器等)上执行 shell 脚本的配置器。
  • 它通过 SSH 或其他连接方式将脚本发送到目标机器并执行。

特点:

  • 运行位置:目标构建环境(虚拟机、Docker 容器、云实例等)。
  • 用途:用于对构建的镜像进行配置,例如:
    • 安装软件包(如 apt-get install nginx)。
    • 修改文件系统。
    • 配置服务或环境变量。
  • 要求
    • 目标环境必须支持 Shell(通常是 Linux/Unix 系统)。
    • Packer 需要与目标环境建立连接(例如通过 SSH 或 WinRM)。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
source "virtualbox-iso" "example" {
guest_os_type = "Ubuntu_64"
iso_url = "http://releases.ubuntu.com/20.04/ubuntu-20.04.6-live-server-amd64.iso"
iso_checksum = "sha256:f8e3084d772ef058e2c428e729d53b5e"
ssh_username = "packer"
ssh_password = "packer"
}

build {
sources = ["source.virtualbox-iso.example"]
provisioner "shell" {
inline = ["echo 'Running on the VM!'", "sudo apt-get update"]
}
}
  • 这段代码会在 VirtualBox 虚拟机中运行,打印消息并更新软件包列表。

主要区别

特性 shell-local shell
执行位置 本地机器(运行 Packer 的主机) 目标构建环境(虚拟机、容器等)
用途 本地预处理或后处理任务 配置目标镜像(如安装软件)
连接要求 无需连接目标环境 需要 SSH/WinRM 等连接到目标环境
典型命令 本地文件操作、调用本地工具 远程安装软件、修改系统配置
环境依赖 依赖本地操作系统的 Shell 依赖目标环境的 Shell

使用场景对比

使用 shell-local 的场景:

  • 在本地生成一个密钥对并将其上传到目标环境:
    1
    2
    3
    4
    5
    6
    7
    provisioner "shell-local" {
    inline = ["ssh-keygen -t rsa -f mykey -N ''"]
    }
    provisioner "file" {
    source = "mykey.pub"
    destination = "/tmp/mykey.pub"
    }
  • 在本地调用 AWS CLI 上传文件:
    1
    2
    3
    provisioner "shell-local" {
    inline = ["aws s3 cp myfile.txt s3://my-bucket/"]
    }

使用 shell 的场景:

  • 在目标镜像上安装 Nginx:
    1
    2
    3
    provisioner "shell" {
    inline = ["sudo apt-get update", "sudo apt-get install -y nginx"]
    }
  • 在目标镜像上配置环境变量:
    1
    2
    3
    provisioner "shell" {
    inline = ["echo 'export MY_VAR=value' >> /etc/profile"]
    }

注意事项

  1. shell-local 不影响镜像内容
    因为它运行在本地,shell-local 的操作不会直接改变构建的镜像。如果需要修改镜像,必须使用 shell 或其他远程配置器。

  2. 执行顺序
    build 块中,provisioner 的执行顺序是按照定义顺序进行的。shell-localshell 可以结合使用,例如先在本地生成文件,再用 shell 安装到目标镜像。

  3. 跨平台兼容性

    • shell-local 的脚本依赖本地 Shell(macOS 上可能是 Bash/Zsh),可能需要注意跨平台差异。
    • shell 的脚本依赖目标环境的 Shell,通常是 Linux 的 Bash。

总结

  • **shell-local**:适合本地任务,不影响目标镜像。
  • **shell**:适合配置目标镜像,直接操作构建环境。