Terraform环境main.tf无法识别模块variables.tf变量声明的问题
Terraform模块变量引用报错问题
项目目录结构
├── environments │ └── dev-1 │ ├── main.tf │ ├── terraform.tfvars │ └── variables.tf ├── main.tf ├── modules │ ├── ec2_instance │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── rds_instance │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── security_group │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── outputs.tf └── variables.tf
模块调用代码(dev-1/main.tf)
module "some_ec2_security_group" { source = "../../modules/security_group" environment = var.environment vpc_id = var.vpc_id ssh_ec2_cidr_blocks = var.ssh_ec2_cidr_blocks }
报错信息
│ Error: Reference to undeclared input variable │ │ on main.tf line 22, in module "some_ec2_security_group": │ 22: vpc_id = var.vpc_id │ │ An input variable with the name "vpc_id" has not been declared. This variable can be declared with a variable "vpc_id" {} block.
问题背景
变量值硬编码在dev-1/terraform.tfvars中。如果在dev-1/variables.tf中声明变量,验证可以通过;但如果只在模块的variables.tf(../../modules/security_group/variables.tf)中声明变量,就会触发上述错误。
原本以为在模块中声明变量是推荐做法,能减少重复声明(毕竟这些变量每个环境都需要),已经多次重新初始化Terraform、清除缓存,当前使用版本:
Terraform v1.7.2 on linux_amd64 + provider registry.terraform.io/hashicorp/aws v5.34.0
原因解释
你混淆了Terraform的变量作用域:
- 模块的variables.tf:定义的是模块对外接收的输入参数,告诉调用者“我需要这些参数才能运行”。
- 你在模块调用里写的
var.vpc_id:引用的是当前工作目录(dev-1)下的变量,和模块里的变量属于完全不同的作用域,Terraform不会自动把模块的变量当成当前环境的变量。
简单说:模块的变量是模块的“需求清单”,而调用时传的var.xxx是当前环境的“库存”,你得先在当前环境的variables.tf里把“库存”(变量)声明出来,才能把它传给模块的“需求”。
正确做法
- 模块侧:在
modules/security_group/variables.tf中声明所有模块需要的输入变量(这确实是推荐做法,保证模块的独立性和复用性),示例:
variable "environment" { type = string description = "部署环境标识" } variable "vpc_id" { type = string description = "VPC ID" } variable "ssh_ec2_cidr_blocks" { type = list(string) description = "允许SSH访问EC2的CIDR段" }
- 环境侧:在
environments/dev-1/variables.tf中声明当前环境需要的变量,示例:
variable "environment" { type = string } variable "vpc_id" { type = string } variable "ssh_ec2_cidr_blocks" { type = list(string) }
- 赋值与调用:在
environments/dev-1/terraform.tfvars中给这些变量赋值,然后在dev-1/main.tf的模块调用里,把当前环境的变量传给模块对应的参数(就是你现在写的调用代码,没问题)。
这样既保证了模块的复用性,每个环境又能独立配置变量值,符合Terraform的最佳实践。
内容的提问来源于stack exchange,提问作者pnc
相关产品推荐
相关产品推荐

