Terraform User-Data执行异常:仅前两行生效,Docker安装失败
Hey there, I've run into similar issues with cloud-init scripts not executing fully when deployed via Terraform, so let's break down the possible causes and fixes step by step:
1. Check Cloud-Init Logs First
The most critical step is to look at the cloud-init execution logs on your EC2 instance—they'll tell you exactly where the script stopped and why. Log into the instance and run these commands:
cat /var/log/cloud-init-output.log cat /var/log/cloud-init.log
cloud-init-output.log captures all stdout/stderr from your user-data script, so you'll see if a specific command failed, threw an error, or caused the script to exit early.
2. Verify the Script's Shebang Line
Ubuntu 16.04 uses dash as the default sh interpreter, which has stricter syntax than bash. If your script uses bash-specific features (like [[ ]] conditional checks, == string comparisons, or advanced parameter expansion) but starts with #!/bin/sh, cloud-init will run it with dash, which can cause unexpected failures.
Fix: Ensure your script.sh starts with:
#!/bin/bash
This forces cloud-init to use bash to execute the script, matching how you ran it manually.
3. Check for set -e or Strict Mode
If your script includes set -e (or set -euo pipefail), any command that returns a non-zero exit code will immediately terminate the script. This is great for catching errors, but it means a single failed command (like a network timeout when fetching Docker's GPG key) stops everything.
Fix:
- Temporarily comment out
set -ein your script and redeploy to see if the full script runs. If it does, you can identify which command was failing by checking the logs. - Add error handling around critical commands (e.g.,
apt update || echo "Apt update failed" && exit 1) to make failures explicit.
4. Ensure Terraform Isn't Modifying Your Script
If you're embedding the script directly in your Terraform config (instead of using file("script.sh")), Terraform might be parsing and replacing shell variables (like $HOME or $USER) as Terraform variables, breaking your script.
Fix: Always use the file function to load your user-data script:
resource "aws_instance" "your_instance" { # ... other config ... user_data = file("${path.module}/script.sh") }
This ensures Terraform passes the script content exactly as-is to cloud-init.
5. Check Network & Security Group Settings
Manual execution works because your local environment has access to Docker's apt repos and Rancher, but your EC2 instance might be blocked by security groups:
- Ensure your instance's security group allows outbound traffic on port 443 (for HTTPS access to Docker's repos and Rancher).
- Verify the instance can resolve DNS (check
/etc/resolv.confand try pingingdownload.docker.com).
6. Verify Script Line Endings
If you edited the script on Windows, it might have CRLF line endings instead of LF. Cloud-init (running on Linux) can choke on CRLF, causing partial execution.
Fix: Convert the script to use LF line endings (most code editors have an option for this, or use dos2unix script.sh if you have it installed).
Once you've checked these points, you should be able to pinpoint why the script stops after the first two echo commands. Let me know if you find specific errors in the logs—I can help dig deeper!
内容的提问来源于stack exchange,提问作者ArjunDandagi

