如何在销毁EC2资源前执行命令?Terraform远程执行需求咨询
实现Terraform销毁VM/EC2前执行命令的方法
方法一:使用Terraform的destroy-time provisioner(通过remote-exec执行)
Terraform支持在资源销毁阶段触发provisioner,只需显式指定when = "destroy"。针对EC2实例,配置示例如下:
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" # 替换为你的目标AMI instance_type = "t2.micro" # 销毁前执行的清理命令 provisioner "remote-exec" { when = "destroy" inline = [ "echo 'Instance is being destroyed, running cleanup...'", # 替换为你需要执行的具体命令,比如备份数据、停止服务等 "sudo systemctl stop my_app_service", "aws s3 sync /app/data s3://my-backup-bucket/instance-${self.id}-backup" ] connection { type = "ssh" user = "ec2-user" # 根据AMI调整,Ubuntu为ubuntu,CentOS为centos private_key = file("~/.ssh/id_rsa") host = self.public_ip } } }
注意事项:
- 确保销毁时Terraform能连通实例:安全组需允许SSH(Windows用WinRM)访问,实例公/私网IP对Terraform运行环境可达,密钥对有效。
- 若实例部署在私有网络,需Terraform环境能访问私网(比如通过跳板机、VPN),否则连接失败会导致销毁流程中断。
- 若provisioner执行失败,Terraform会终止销毁,需手动处理后重新执行
terraform destroy。
方法二:利用EC2生命周期钩子+SSM Run Command(无Terraform依赖场景)
如果担心Terraform销毁时无法连接实例,可通过AWS原生服务触发清理:
实现步骤:
- 创建IAM角色,允许Lambda调用SSM
SendCommand,并拥有EC2实例的访问权限。 - 编写Lambda函数,捕获EC2终止事件,通过SSM在目标实例执行命令:
import boto3 ssm = boto3.client('ssm') def lambda_handler(event, context): instance_id = event['detail']['instance-id'] try: ssm.send_command( InstanceIds=[instance_id], DocumentName='AWS-RunShellScript', Parameters={ 'commands': [ 'echo "Termination detected, starting cleanup"', 'sudo rm -rf /tmp/temp_work_dir', 'sudo tar -czf /var/log/app_backup.tar.gz /var/log/my_app' ] } ) except Exception as e: print(f"Failed to send command: {str(e)}") raise e
- 创建CloudWatch Event规则,捕获EC2的
Instance Terminate事件,触发上述Lambda函数。 - 确保目标EC2实例已安装SSM Agent(Amazon Linux 2默认预装,其他系统需手动安装)。
注意事项:
- 生命周期钩子有默认300秒超时限制,需确保清理命令能在超时前完成。
- 此方法不依赖Terraform连接,适合网络隔离或Terraform环境无法访问实例的场景。
方法三:实例内监听终止信号(本地可靠方案)
在EC2实例内部,通过监听元数据的终止通知触发本地脚本:
- 编写后台监听脚本
/usr/local/bin/termination-cleanup.sh:
#!/bin/bash while true; do # 检查是否收到终止通知 if curl -s http://169.254.169.254/latest/meta-data/spot/termination-time > /dev/null; then echo "Termination signal received, executing cleanup..." # 执行清理操作 sudo systemctl stop my_app aws s3 cp /app/config s3://my-config-bucket/instance-backup/$(hostname) break fi sleep 5 done
- 将脚本注册为系统服务,确保实例启动时自动运行:
sudo tee /etc/systemd/system/termination-cleanup.service <<EOF [Unit] Description=Run cleanup on instance termination [Service] ExecStart=/usr/local/bin/termination-cleanup.sh Restart=always User=root [Install] WantedBy=multi-user.target EOF sudo chmod +x /usr/local/bin/termination-cleanup.sh sudo systemctl daemon-reload sudo systemctl enable termination-cleanup.service
注意事项:
- 适用于所有EC2实例(按需/Spot),无需外部服务依赖。
- 需给实例附加IAM角色,赋予S3等服务的访问权限(如需上传备份)。
内容的提问来源于stack exchange,提问作者Dhananjay Gahiwade
相关产品推荐
相关产品推荐

