Day 3 of 5
⏱ ~60 minutes
Terraform in 5 Days — Day 3

Resources and Data Sources

Define EC2 instances, security groups, and VPCs. Use data sources to reference existing infrastructure.

Real Resources: VPC + EC2

vpc.tf
# Create a VPC
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = { Name = "main-vpc" }
}

# Public subnet
resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id  # reference another resource
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  map_public_ip_on_launch = true
}

# Security group
resource "aws_security_group" "web" {
  vpc_id = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
ec2.tf
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = "t3.micro"
  subnet_id              = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.web.id]

  user_data = <<-EOF
    #!/bin/bash
    yum install -y nginx
    systemctl start nginx
    EOF

  tags = { Name = "web-server" }
}
ℹ️
References like aws_vpc.main.id create implicit dependencies. Terraform builds a dependency graph and creates resources in the right order. The subnet waits for the VPC. The EC2 waits for the subnet. You don't have to specify the order.
📝 Day 3 Exercise
Build a VPC + EC2 Setup
  1. C
  2. r
  3. e
  4. a
  5. t
  6. e
  7. a
  8. V
  9. P
  10. C
  11. ,
  12. p
  13. u
  14. b
  15. l
  16. i
  17. c
  18. s
  19. u
  20. b
  21. n
  22. e
  23. t
  24. ,
  25. i
  26. n
  27. t
  28. e
  29. r
  30. n
  31. e
  32. t
  33. g
  34. a
  35. t
  36. e
  37. w
  38. a
  39. y
  40. ,
  41. s
  42. e
  43. c
  44. u
  45. r
  46. i
  47. t
  48. y
  49. g
  50. r
  51. o
  52. u
  53. p
  54. (
  55. a
  56. l
  57. l
  58. o
  59. w
  60. 8
  61. 0
  62. /
  63. 4
  64. 4
  65. 3
  66. )
  67. ,
  68. a
  69. n
  70. d
  71. a
  72. n
  73. E
  74. C
  75. 2
  76. i
  77. n
  78. s
  79. t
  80. a
  81. n
  82. c
  83. e
  84. w
  85. i
  86. t
  87. h
  88. N
  89. g
  90. i
  91. n
  92. x
  93. .
  94. U
  95. s
  96. e
  97. a
  98. d
  99. a
  100. t
  101. a
  102. s
  103. o
  104. u
  105. r
  106. c
  107. e
  108. f
  109. o
  110. r
  111. t
  112. h
  113. e
  114. A
  115. M
  116. I
  117. .
  118. S
  119. S
  120. H
  121. i
  122. n
  123. t
  124. o
  125. t
  126. h
  127. e
  128. i
  129. n
  130. s
  131. t
  132. a
  133. n
  134. c
  135. e
  136. a
  137. n
  138. d
  139. v
  140. e
  141. r
  142. i
  143. f
  144. y
  145. N
  146. g
  147. i
  148. n
  149. x
  150. i
  151. s
  152. r
  153. u
  154. n
  155. n
  156. i
  157. n
  158. g
  159. .

Day 3 Summary

  • Resources reference each other: resource_type.name.attribute. Terraform infers dependency order.
  • Data sources query existing resources. data.aws_ami.amazon_linux.id finds the latest Amazon Linux AMI.
  • user_data runs shell commands when the instance first boots.
  • depends_on for explicit dependencies when the implicit graph isn't enough.
Finished this lesson?