如何在Packer构建的AMI中声明变量以填充EFS挂载脚本
在Packer中配置EFS DNS变量并完成挂载
要让Packer在provisioner脚本里正确填充EFS的DNS名称,按以下步骤操作:
1. 配置Packer模板的EFS数据源和变量(可选)
首先在你的Packer HCL模板中,通过AWS数据源获取EFS的DNS名称;如果需要参数化传入EFS ID,也可以先定义变量:
# 可选:定义变量,方便外部传入EFS ID variable "efs_file_system_id" { type = string description = "目标EFS文件系统的ID" } # 获取EFS的DNS名称 data "aws_efs_file_system" "efs" { file_system_id = var.efs_file_system_id }
2. 在Provisioner中传递并使用变量
根据你使用的是inline脚本还是外部脚本,分两种方式处理:
方式一:直接用inline Shell脚本
直接在Packer的shell provisioner里引用数据源的DNS名称,同时注意权限和引号问题:
provisioner "shell" { inline = [ # 先创建挂载目录(如果不存在) "sudo mkdir -p /var/www/html", # 临时挂载EFS "sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${data.aws_efs_file_system.efs.dns_name}:/ /var/www/html", # 写入fstab实现永久挂载——用tee解决sudo重定向权限问题 "echo '${data.aws_efs_file_system.efs.dns_name}:/ /var/www/html nfs4 defaults,vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 0 0' | sudo tee -a /etc/fstab > /dev/null" ] }
这里重点注意:
- 用
tee -a代替>>,因为sudo echo ... >> /etc/fstab中,重定向操作是当前用户执行,没有写入/etc/fstab的权限,而tee可以通过sudo获取权限。 - 外层用单引号包裹fstab的配置内容,避免shell解析内部的空格和参数,同时Packer会先替换掉
${data.aws_efs_file_system.efs.dns_name}变量。
方式二:使用外部Shell脚本
如果挂载逻辑复杂,建议把脚本单独写在外部文件,通过环境变量传递EFS DNS名称:
- 创建外部脚本
mount_efs.sh:
#!/bin/bash # 创建挂载目录 sudo mkdir -p /var/www/html # 临时挂载EFS sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport "${EFS_DNS_NAME}":/ /var/www/html # 写入fstab echo "${EFS_DNS_NAME}:/ /var/www/html nfs4 defaults,vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 0 0" | sudo tee -a /etc/fstab > /dev/null
- 在Packer模板中引用脚本并传递环境变量:
provisioner "shell" { script = "./mount_efs.sh" # 传递EFS DNS名称到脚本的环境变量 environment_vars = [ "EFS_DNS_NAME=${data.aws_efs_file_system.efs.dns_name}" ] }
额外注意事项
- 确保Packer创建的临时实例安全组允许NFS(2049端口)的入站流量,且实例角色拥有访问EFS的权限(比如附加
AmazonElasticFileSystemClientFullAccess策略)。 - 如果EFS是跨可用区的,要确保临时实例所在可用区有EFS的挂载目标。
内容的提问来源于stack exchange,提问作者gklucard
相关产品推荐
相关产品推荐

