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.