luvv to helpDiscover the Best Free Online Tools
Topic 1 of 8

Infrastructure As Code Basics

Learn Infrastructure As Code Basics for free with explanations, exercises, and a quick test (for Data Engineer).

Published: January 8, 2026 | Updated: January 8, 2026

Why this matters

Worked examples

Example 1: Storage bucket with versioning (Terraform HCL)
# variables.tf
variable "bucket_name" {
  type        = string
  description = "Name of the data lake bucket"
}

# main.tf (AWS example)
provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "data_lake" {
  bucket = var.bucket_name
  tags = {
    project = "analytics"
    env     = "dev"
  }
}

resource "aws_s3_bucket_versioning" "ver" {
  bucket = aws_s3_bucket.data_lake.id
  versioning_configuration {
    status = "Enabled"
  }
}

output "bucket_arn" {
  value = aws_s3_bucket.data_lake.arn
}

Run: terraform init → terraform validate → terraform plan. You should see: “Plan: 2 to add, 0 to change, 0 to destroy.”

Example 2: IAM policy for read-only access to that bucket
data "aws_iam_policy_document" "read_only" {
  statement {
    actions   = ["s3:GetObject", "s3:ListBucket"]
    resources = [
      aws_s3_bucket.data_lake.arn,
      "${aws_s3_bucket.data_lake.arn}/*"
    ]
  }
}

resource "aws_iam_policy" "read_only_policy" {
  name   = "data-lake-read-only"
  policy = data.aws_iam_policy_document.read_only.json
}

This attaches least-privilege permissions for consumers who only need to read data.

Example 3: GCP bucket with labels (Terraform)
provider "google" {
  project = "your-project-id"
  region  = "us-central1"
}

resource "google_storage_bucket" "lake" {
  name     = "my-data-lake-dev"
  location = "US"
  storage_class = "STANDARD"
  labels = {
    project = "analytics"
    env     = "dev"
  }
  versioning {
    enabled = true
  }
}

The idea is identical: declare the bucket, labels, and versioning. Different provider, same IaC workflow.

Learning path

  1. Understand declarative IaC, state, plan/apply, and idempotency.
  2. Create small resources (buckets, tags/labels, versioning, lifecycle).
  3. Add IAM: least privilege policies and roles.
  4. Refactor into modules and variables for reuse.
  5. Introduce environments: dev → stage → prod with workspaces or separate state.
  6. Automate: run fmt/validate/plan in CI and require review before apply.

Exercises

Note: You can take the quick test below without signing in. To save your progress and resume later, sign in to your LuvvHelp account.

Exercise 1: Bucket with versioning, lifecycle, and output

Create a Terraform project that declares a storage bucket with:

  • Versioning enabled.
  • A lifecycle rule that deletes noncurrent versions after 30 days.
  • Tags/labels for project and environment.
  • An output that prints the bucket ARN (or self_link on GCP).

Use a variable for the bucket name. Run init → validate → plan. Do not apply to a real account unless you fully understand the consequences.

Checklist
  • [ ] variables.tf contains bucket_name.
  • [ ] Versioning enabled resource present.
  • [ ] Lifecycle rule handles noncurrent versions in 30 days.
  • [ ] Tags/labels set for project and env.
  • [ ] Output prints bucket identifier (ARN or self_link).
  • [ ] terraform validate passes.
  • [ ] terraform plan shows only adds, no destroys in a new workspace.

Common mistakes and self-check

  • Forgetting version control: Always commit IaC to Git to review and roll back.
  • Hardcoding names: Use variables; keep provider/region abstract when possible.
  • Skipping plan review: Never apply without reading the plan in PR or locally.
  • Ignoring state: Do not delete or manually edit state. Use remote state for teams.
  • Over-permissive IAM: Start with least privilege; expand only if needed.
  • Drift blindness: Schedule regular plans to detect drift (changes made outside IaC).

Self-check: If you run plan twice with no code changes, it should show “0 to add, 0 to change, 0 to destroy.” If not, identify drift or non-idempotent code.

Practical projects

  • Data Lake Starter: One bucket per layer (raw, curated), standard tags/labels, versioning, lifecycle; outputs for ARNs/links.
  • Read-Only Consumer Role: A reusable module that grants limited access to curated data.
  • Sandbox Environment: Dev environment that mirrors prod structure with smaller sizes and fewer permissions.

Next steps

  • Extract your bucket and IAM patterns into modules.
  • Add CI checks: fmt, validate, plan on pull requests.
  • Introduce environments with workspaces or separate state files.

Mini challenge

Design a minimal IaC layout for three environments (dev/stage/prod) that reuses the same module for buckets and IAM, differing only by variables. Write down your directory structure and the variables you would expose (e.g., bucket prefix, lifecycle days, tags/labels, permissions).

Quick test notice

Everyone can take the quick test below for free. Sign in if you want your score and progress to be saved.

Practice Exercises

1 exercises to complete

Instructions

Create a Terraform project that defines a storage bucket with:

  • Versioning enabled
  • A lifecycle rule deleting noncurrent versions after 30 days
  • Tags/labels for project and env
  • An output printing the bucket ARN (AWS) or self_link (GCP)

Use a variable for the bucket name. Run terraform init, terraform validate, and terraform plan. Do not apply to a real account unless this is an approved sandbox.

Expected Output
terraform validate passes; terraform plan shows only additions (e.g., Plan: 2–3 to add, 0 to change, 0 to destroy) and prints the output name in the plan.

Infrastructure As Code Basics — Quick Test

Test your knowledge with 10 questions. Pass with 70% or higher.

10 questions70% to pass

Have questions about Infrastructure As Code Basics?

AI Assistant

Ask questions about this tool