Terraform配置Shell脚本钩子实现EBS卷DeleteOnTermination及报错排查
问题解决:EBS卷DeleteOnTermination配置与S3桶弃用警告
一、修复local-exec的"bash: ... No such file or directory"错误(退出码127)
退出码127本质是脚本中调用的命令不存在,或脚本路径/写法有误。提供两种解决方案:
方案1:修正local-exec脚本写法
如果坚持使用local-exec,需满足以下要求并调整配置:
- 执行Terraform的环境已安装AWS CLI,且配置了修改EBS卷属性的权限
- 脚本变量引用正确,命令路径完整
示例配置:
resource "aws_instance" "example" { ami = "ami-xxxxxx" instance_type = "t2.micro" # 附加EBS卷 ebs_block_device { device_name = "/dev/sdh" volume_size = 10 } provisioner "local-exec" { command = <<EOT # 等待实例进入运行状态 aws ec2 wait instance-running --instance-ids ${self.id} # 获取目标EBS卷ID VOLUME_ID=$(aws ec2 describe-instances --instance-ids ${self.id} --query 'Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==`/dev/sdh`].Ebs.VolumeId' --output text) # 修改DeleteOnTermination属性 aws ec2 modify-instance-attribute --instance-id ${self.id} --block-device-mappings "[{\"DeviceName\": \"/dev/sdh\", \"Ebs\": {\"DeleteOnTermination\": true}}]" EOT interpreter = ["/bin/bash", "-c"] } }
注意事项:
- 显式指定
interpreter避免shell环境差异 - 确保
aws命令在PATH中,或直接写绝对路径(如/usr/local/bin/aws) - 用
${self.id}正确引用实例ID,避免语法错误
方案2:用Terraform原生资源替代local-exec(推荐)
local-exec依赖外部工具易出环境问题,更可靠的方式是用aws_ebs_volume_attachment直接配置:
# 创建独立EBS卷 resource "aws_ebs_volume" "example" { availability_zone = aws_instance.example.availability_zone size = 10 } # 附加卷到实例并启用DeleteOnTermination resource "aws_ebs_volume_attachment" "example" { device_name = "/dev/sdh" instance_id = aws_instance.example.id volume_id = aws_ebs_volume.example.id delete_on_termination = true # 直接启用目标属性 } resource "aws_instance" "example" { ami = "ami-xxxxxx" instance_type = "t2.micro" }
这种方式完全由Terraform管理,无需依赖外部脚本,从根源避免环境类错误。
二、修复S3桶属性弃用警告
Terraform AWS Provider现在推荐将S3桶配置拆分为独立资源,而非在aws_s3_bucket中嵌套属性:
旧的弃用写法(触发警告)
resource "aws_s3_bucket" "example" { bucket = "my-example-bucket" # 以下属性已被弃用 acl = "private" server_side_encryption_configuration { rule { apply_server_side_encryption_by_default { kms_master_key_id = "arn:aws:kms:us-east-1:xxxxxx:key/xxxxxx" sse_algorithm = "aws:kms" } } } }
新的合规写法
resource "aws_s3_bucket" "example" { bucket = "my-example-bucket" } # 单独配置ACL resource "aws_s3_bucket_acl" "example" { bucket = aws_s3_bucket.example.id acl = "private" } # 单独配置服务器端加密 resource "aws_s3_bucket_server_side_encryption_configuration" "example" { bucket = aws_s3_bucket.example.id rule { apply_server_side_encryption_by_default { kms_master_key_id = "arn:aws:kms:us-east-1:xxxxxx:key/xxxxxx" sse_algorithm = "aws:kms" } } }
其他如版本控制、日志配置等,也需拆分为aws_s3_bucket_versioning、aws_s3_bucket_logging等独立资源,遵循最新Provider规范。
内容的提问来源于stack exchange,提问作者ranjeet guha
相关产品推荐
相关产品推荐

