DevOps Peach

Linux · Terraform – Infrastructure as Code · Lesson 2 of 5

Terraform, HCL, and Ansible

Choose tools by lifecycle instead of forcing one tool to do everything.

Practice interactively →

How Terraform works

Terraform reads HCL configuration, calls provider APIs, and reconciles configuration with state and remote objects. A provider declares resource types and data sources; a resource block describes a managed object. Terraform is a single binary; terraform version shows it and the providers in use.

terraform {
  required_providers {
    aws = { source = "hashicorp/aws" }
  }
}

locals {
  name = "demo-${var.env}"   # string interpolation
}

resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = "t3.micro"
  tags          = { Name = local.name }
}
flowchart LR
  TF["Terraform<br/>declarative, state"] --> INFRA["Provision<br/>VPC, subnet, VM"]
  INFRA --> OUT["Outputs<br/>public IPs"]
  OUT --> ANS["Ansible<br/>inventory from outputs"]
  ANS --> CONF["Configure<br/>packages, files, services"]
  CONF --> APP["Running app"]
  %% step TF: Terraform declares the infrastructure and tracks it in state.
  %% step INFRA: It creates, changes and destroys cloud resources in dependency order.
  %% step OUT: Outputs expose values such as IP addresses.
  %% step ANS: Ansible uses those addresses as its inventory.
  %% step CONF: Ansible configures what runs inside the machines.
  %% step APP: Each tool does the part of the lifecycle it is built for.

HCL in brief

HCL is built from blocks (resource, variable, output, locals, module) that contain arguments (instance_type = "t3.micro"). Expressions reference other objects by address, such as aws_instance.web.id or var.env, and those references are how Terraform learns the order to create things. # starts a comment. All .tf files in a directory are read together, so splitting into main.tf, variables.tf, and outputs.tf is only for readability. terraform console evaluates expressions interactively.

HCL concept Role
Provider Plugin communicating with an API
Resource Object whose lifecycle Terraform manages
Data source Read object or data without owning lifecycle
Local value Named expression reused inside the module

HCL is not YAML. terraform fmt normalizes style; terraform validate checks configuration in an initialized directory but cannot prove every remote permission or quota.

Terraform and Ansible side by side

Aspect Terraform Ansible
Main job Create and delete infrastructure Configure software inside hosts
Language HCL, declarative YAML tasks, mostly ordered steps
Memory of what exists State file None; checks hosts on each run
Removing something Delete the block, then apply Write a task with state: absent

Terraform is strong at provisioning and dependency graphs. Ansible is strong at in-host configuration, package and service orchestration, and application deployment. A pipeline often uses Terraform to create networks and VMs and then feeds outputs or inventory to Ansible; the boundary is not absolute, but ownership must be clear.

Other hand-offs exist too: Terraform can pass a cloud-init script through user_data for first-boot setup, and Packer can bake a ready image so servers need little configuration after launch.

Practice interactively →