Crisp answer: Outputs expose values from your Terraform config to the terminal after apply, to parent modules, or to other Terraform configs via remote state data sources.
Declaring outputs:
output "vpc_id" {
description = "The VPC ID"
value = aws_vpc.main.id
}
output "cluster_endpoint" {
description = "EKS cluster API endpoint"
value = aws_eks_cluster.main.endpoint
}
output "db_password" {
description = "Database master password"
value = aws_rds_cluster.main.master_password
sensitive = true # Redacted in terminal, but present in state
}
output "private_subnet_ids" {
description = "List of private subnet IDs"
value = aws_subnet.private[*].id # Collect all instances
}
Using outputs:
# See all outputs after apply:
terraform output
# Get a specific value (useful in scripts):
VPC_ID=$(terraform output -raw vpc_id)
SUBNETS=$(terraform output -json private_subnet_ids)
Using outputs from a child module:
module "networking" {
source = "./modules/vpc"
# ...
}
resource "aws_eks_cluster" "main" {
vpc_config {
subnet_ids = module.networking.private_subnet_ids # use module output
}
}
Consuming outputs from a remote state:
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "my-state-bucket"
key = "networking/terraform.tfstate"
region = "eu-west-2"
}
}
resource "aws_eks_cluster" "main" {
vpc_config {
subnet_ids = data.terraform_remote_state.networking.outputs.private_subnet_ids
}
}
This lets you split large configurations across multiple Terraform roots that share state — e.g. a networking root that owns the VPC, and an EKS root that reads the VPC outputs.
What to say in the interview:
"Outputs serve three purposes: displaying values after apply (like an endpoint URL you need to configure DNS), exposing values to parent modules so they can be wired into other resources, and sharing values between separate Terraform roots via remote state data sources. The remote state pattern is how you split a large infrastructure into manageable pieces without giving every root access to everything."