ad4469dc-7beb-4b7f-90b1-7de.../docs/04_variables_tfvars_outputs.md

143 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 4) Variables, tfvars & Outputs (20 min)
In this section, youll **parameterize** your Terraform configuration so its flexible across environments (like *dev* and *prod*) and learn how to **print useful values** after deployment.
## Why variables and tfvars?
- **Variables** let you avoid hardcoding values (e.g., instance type, names).
- **.tfvars files** store a specific set of variable values for each environment. You can switch environments quickly without editing code.
- **Outputs** print important information (IDs, IPs, AZs) for later use in scripts, CD pipelines, or as inputs to other modules.
## Step 1: Create a working directory
```bash
mkdir -p ~/terraform-vars-lab && cd ~/terraform-vars-lab
```
Creates a clean folder for this exercise and moves into it.
## Step 2: Define variables
Create a file **variables.tf**:
```hcl
variable "instance_type" {}
variable "instance_name" {}
```
- Declares two variables, `instance_type` and `instance_name`.
- No defaults are provided, so Terraform will expect values (either via `-var` flags, `.tfvars` files, or prompts).
> Tip: You can add descriptions and types to make your code self-documenting:
> ```hcl
> variable "instance_type" { type = string, description = "EC2 size, e.g. t2.micro" }
> variable "instance_name" { type = string, description = "Tag: Name for the instance" }
> ```
## Step 3: Write the main configuration
Create **main.tf**:
```hcl
provider "aws" { region = "ap-south-1" }
resource "aws_instance" "ec2_instance" {
ami = "ami-0e6329e222e662a52"
instance_type = var.instance_type
tags = { Name = var.instance_name }
}
```
- **provider "aws"**: points Terraform to AWS in the Mumbai region.
- **resource "aws_instance" "ec2_instance"**: creates an EC2 instance.
- `ami`: the base OS image (Amazon Linux 2 for ap-south-1).
- `instance_type`: references your variable using `var.instance_type`.
- `tags`: uses `var.instance_name` so the tag can change per environment.
## Step 4: Expose useful outputs
Create **outputs.tf**:
```hcl
output "instance_id" { value = aws_instance.ec2_instance.id }
output "public_ip" { value = aws_instance.ec2_instance.public_ip }
output "availability_zone" { value = aws_instance.ec2_instance.availability_zone }
```
- After apply, Terraform will print these values.
- Great for quickly finding the instance or for handing values to other tools.
> Tip: Add `sensitive = true` to hide secrets in logs:
> ```hcl
> output "db_password" { value = var.db_password, sensitive = true }
> ```
## Step 5: Create environment files (tfvars)
Create **dev.tfvars**:
```hcl
instance_type = "t2.micro"
instance_name = "Dev-Instance"
```
Create **prod.tfvars**:
```hcl
instance_type = "t3.micro"
instance_name = "Prod-Instance"
```
- These files define different values for the *same* variables.
- You can add more environments (e.g., `test.tfvars`, `staging.tfvars`) as needed.
> Tip: Keep environment files in version control, but never commit secrets. For secrets, use a secure tool (e.g., AWS SSM Parameter Store, Vault) or CI/CDcontrolled variables.
## Step 6: Initialize, apply, output, and switch environments
```bash
terraform init
```
- Downloads provider plugins and prepares the working directory.
```bash
terraform apply -var-file="dev.tfvars" -auto-approve
```
- Applies with **dev** values.
- Creates a `t2.micro` instance named **Dev-Instance**.
```bash
terraform output
```
- Prints the values from **outputs.tf** to the terminal (instance id, public IP, AZ).
```bash
terraform destroy -auto-approve
```
- Destroys the **dev** instance to avoid charges before testing **prod**.
```bash
terraform apply -var-file="prod.tfvars" -auto-approve
```
- Applies with **prod** values.
- Creates a `t3.micro` instance named **Prod-Instance**.
```bash
terraform output -json > output.json
cat output.json
```
- Exports outputs in **JSON** format, perfect for automation pipelines.
- `output.json` can be parsed by scripts or downstream systems.
## Common gotchas & best practices
- **Keep AMIs per region**: AMI IDs are regionspecific. If you change regions, update the AMI.
- **Validate before apply**: Run `terraform validate` and `terraform plan` to catch mistakes early.
- **Naming**: Tags are your friend. Use `Name` tags consistently so you can find resources fast.
- **Separate state**: For real projects, use separate state/workspaces or remote backends (S3 + DynamoDB) per environment.
## Wrap-Up
You now know how to:
- Declare variables and pass values with `.tfvars`
- Reuse the same code for **multiple environments**
- Surface key information using **outputs**
- Export outputs to **JSON** for automation
This pattern is the backbone of scalable Terraform projects.