Terraform扁平结构迁移至模块化架构的技术咨询
Hey there! Let's break down how to properly implement your Terraform modular migration for the EC2 instance and EIP setup you're working on. You're already heading in the right direction, but there are a few critical tweaks to get this working smoothly.
1. Module Structure Best Practices
First, let's align your folder structure with standard Terraform conventions—this makes your code easier to maintain and scale. Here's how it should look:
terraform/ ├── instance/ │ ├── main.tf # Holds your EC2 instance resource (use main.tf instead of instance.tf for consistency) │ ├── variables.tf # Defines configurable inputs for the instance (e.g., AMI ID, instance type) │ └── outputs.tf # Exposes instance properties other modules need to reference (this is the missing piece!) └── eip/ ├── main.tf # Holds the EIP resource and instance module reference ├── variables.tf # Passes inputs down to the instance module └── outputs.tf # Exposes EIP properties if needed by higher-level modules
2. Configure the Instance Module (Outputs Are Non-Negotiable!)
The biggest mistake in your current setup is not explicitly exposing the instance's ID via an output. Modules don't let you directly reference internal resources from outside—you have to define outputs for properties other modules need.
Instance Module Files:
instance/main.tf (parameterize for reusability)
variable "ami_id" { description = "AMI ID to use for the EC2 instance" type = string } variable "instance_type" { description = "EC2 instance type" type = string default = "t3.medium" # Set a sensible default } resource "aws_instance" "rancher-node-production" { ami = var.ami_id instance_type = var.instance_type # Add other required config (security groups, subnet ID, etc.) as variables }
instance/outputs.tf (expose the instance ID)
output "instance_id" { description = "Unique ID of the EC2 instance" value = aws_instance.rancher-node-production.id } # Optional: Expose other useful properties if needed output "private_ip" { description = "Private IP address of the instance" value = aws_instance.rancher-node-production.private_ip }
3. Reference the Instance Module in the EIP Module
Now you can safely reference the instance module from your EIP module. You'll need to pass any required variables to the instance module and use its exposed output to link the EIP.
EIP Module Files:
eip/variables.tf (define inputs for both EIP and instance module)
variable "instance_ami_id" { description = "AMI ID to pass to the instance module" type = string } variable "instance_type" { description = "Instance type to pass to the instance module" type = string default = "t3.medium" }
eip/main.tf (reference instance module and create EIP)
# Reference the instance module (path is relative to this file's location) module "instance" { source = "../instance" # Pass variables to the instance module ami_id = var.instance_ami_id instance_type = var.instance_type } # Create EIP and link it to the instance using the module's output resource "aws_eip" "rancher-node-production-eip" { instance = module.instance.instance_id # Use the exposed output here! vpc = true # Required if your instance is in a VPC }
4. Tie It All Together with a Root Module
To run your configuration, you'll need a root module (typically in the terraform/ root directory) that calls the EIP module. This is where you'll set environment-specific values.
terraform/main.tf
module "rancher_node_production" { source = "./eip" # Set environment-specific values instance_ami_id = "ami-1234567890abcdef0" # Replace with your actual AMI instance_type = "t3.large" # Override default if needed } # Optional: Output the public IP for easy access output "rancher_node_public_ip" { value = module.rancher_node_production.eip_public_ip }
5. Core Configuration Takeaways
- Always define outputs for module properties others need: You can't reference internal resources across modules—outputs are the only way to share data.
- Use relative paths correctly: The
sourceparameter in a module block is relative to the file it's written in (e.g.,../instancefromeip/main.tfworks because the folders are siblings). - Parameterize modules: Avoid hardcoding values like AMI IDs or instance types—use variables so you can reuse modules across environments (production, staging, etc.).
- Follow naming conventions: Stick to
main.tf,variables.tf, andoutputs.tffor module files—it makes your code predictable for other developers.
内容的提问来源于stack exchange,提问作者pkaramol

