Share
Embed
Building in the Cloud with Terraform
This is a presentation about using Terraform (or OpenTofu) to build cloud infrastructure.
The content presented is suitable for beginner to intermediate cloud infrastructure professionals.
This was delivered at a Dallas Software Developers (DSD) meetup in March, 2025.
Justin
May 07, 2025
Transcript
46 slides
-
Building in the Cloud with Terraform Justin Biard Principal Member
of Technical Staff, Oracle March 13, 2025 Disclaimer: opinions presented are my own! -
Building in the cloud As of 2025: SaaS: Software as
a Service PaaS: Platform as a Service IaaS: Infrastructure as a Service -
Why use tools like Terraform / OpenTofu? Abstraction: Abstract the
logic of each cloud API to a Terraform provider -
Why use tools like Terraform / OpenTofu? Abstraction: Abstract the
logic of each cloud API to a Terraform provider Reconciliation: Reconcile changes to resources against a known good config -
Why use tools like Terraform / OpenTofu? Abstraction: Abstract the
logic of each cloud API to a Terraform provider Reconciliation: Reconcile changes to resources against a known good config Automation: Automate tedious or manual infrastructure tasks (vs. console clicks) -
Why use tools like Terraform / OpenTofu? Abstraction: Abstract the
logic of each cloud API to a Terraform provider Reconciliation: Reconcile changes to resources against a known good config Automation: Automate tedious or manual infrastructure tasks (vs. console clicks) Comprehension: Comprehend of the scope and scale of deployed infrastructure -
Building in the cloud As of 2025: SaaS: Software as
a Service PaaS: Platform as a Service IaaS: Infrastructure as a Service -
Building in the cloud As of 2025: SaaS: Software as
a Service PaaS: Platform as a Service IaaS: Infrastructure as a Service 25 years from now… DaaS: Donuts as a Service -
Why DaaS? Assumption: • Fresh donuts are tasty • Donuts
are popular with consumers • Growing industry with large CapEx[1] and long lead time (build, etc.) Conclusion: • Improving the efficiency of donut production is worth time and energy 1- Capital expense (CapEx) is the cost of buying, building, or improving a depreciable fixed asset (such as a building) -
We need a recipe to build DaaS A cloud service
(i.e. The Bakery CloudTM) provides: 1. The infrastructure (network, compute, ovens, etc.) 2. A REST API for resource management 3. A Terraform provider -
We need a recipe to build DaaS A cloud service
(i.e. The Bakery CloudTM) provides: 1. The infrastructure (network, compute, ovens, etc.) 2. A REST API for resource management 3. A Terraform provider A donut shop provides: • The configuration - Infrastructure as Code (IaC) -
Theory: What is Infrastructure as Code? Configuration of cloud infrastructure
resources documented as code (a configuration language) terraform { ... } Network Load Balancer Database Fryer Compartment Policy Drying Rack Virtual Machine ./my-project/main.tf -
Theory: Plan changes Configuration is parsed and requests sent to
a cloud control plane using Terraform providers (reads) terraform { ... } Cloud Service $ terraform plan -
Theory: Apply changes A cloud service performs operations requested by
a Terraform provider (to manage resources) terraform { ... } Cloud Service $ terraform apply -
Theory: Version control Configuration is code, so keep it in
a version control system (change control, collaboration, etc.) terraform { ... } Cloud Service Version Control -
Theory: Reusable configuration A configuration can be applied to more
than one cloud region or stage (dev, pre-prod, prod, etc.) terraform { ... } Cloud Service Version Control Pre-prod Region 2 Region 1 -
Theory: Conditional configuration Terraform can apply different configurations conditionally (large
vs. small regions, stages, etc.) terraform { ... } Cloud Service Version Control -
Theory: Resource state reconciliation Terraform state is reconciled and updated
based on changes to the actual cloud resources terraform { ... } Cloud Service Version Control {tfstate} -
Enough theory! How do we code it? • Configure a
remote backend or use local (default) -
Enough theory! How do we code it? • Configure a
remote backend or use local (default) • Declare and configure providers -
Enough theory! How do we code it? • Configure a
remote backend or use local (default) • Declare and configure providers • Declare resources (defined as code) -
Enough theory! How do we code it? • Configure a
remote backend or use local (default) • Declare and configure providers • Declare resources (defined as code) • Add variables and modules as needed (refactor?) -
Enough theory! How do we code it? • Configure a
remote backend or use local (default) • Declare and configure providers • Declare resources (defined as code) • Add variables and modules as needed (refactor?) • Add outputs as needed -
Enough theory! How do we code it? • Configure a
remote backend or use local (default) • Declare and configure providers • Declare resources (defined as code) • Add variables and modules as needed (refactor?) • Add outputs as needed • Terraform apply -> Donuts as a Service! $ terraform apply -
Practice: Create a directory In this example: 1. donut-shop is
the “root module” in this example 2. kitchen is a sub- module ./donut-shop - kitchen/ - main.tf - main.tf - ... -
Practice: Configure a backend (optional) Which backend? 1. Cloud services
2. A bucket 3. ... 4. local is the default terraform { ... backend "s3" { ... } } $ terraform init –backend-config="bakery.backend.config" -
Practice: Declare required providers ... required_providers { bakery = {
source = "bakery/cloud" version = ">= 4.2.5" } } Which provider(s) are required? 1. A cloud service 2. In-house / 3rd party 3. Etc. $ terraform init –upgrade -
Practice: Configure providers provider ... { setting1 = value1 setting2
= value2 ... } What configuration is required? 1. See provider documentation! 2. Settings are convention or configuration. An optional alias helps if multiple instances are needed. -
Practice: Declare Resources resource "provider_of_thing" "alias_of_resource" { property = 8080
list_of_things = ["thing 1", "thing 2", ...] string_property = "some string value" } See provider documentation for resources and parameters. • Networks, load balancers, virtual machines, etc. -
Practice: Format it (optional) resource "provider_of_thing" "alias_of_resource" { property =
8080 list_of_things = ["thing 1", "thing 2", ...] string_property = "some string value" } $ terraform fmt <file.tf> • Networks, load balancers, virtual machines, etc. -
Practice: Create multiples (optional) resource "provider_of_thing" "alias_of_resource" { for_each =
toset(["thing 1", "thing 2", ...]) ... name_of_thing = each.key } You can also use the count meta-argument and count.index -
Practice: Add variables (optional) variable "stage" {} locals { destination_port
= var.stage == "dev" ? 8080 : 443 oven_shape = var.stage == "dev" ? "SMALL" : "LARGE" } ... resource "provider_of_thing" "alias_of_resource" { property = local.destination_port } Variables are set using files, ENV, arguments, or defaults. -
# ./kitchen/main.tf variable "oven_count" {} variable "oven_shape" {} resource "type_a"
... {...} resource "type_b" ... {...} resource "type_c" ... {...} Practice: Add modules (optional) Consider separate .tf files if code re-use is not a goal. -
# ./kitchen/main.tf variable "oven_count" {} variable "oven_shape" {} resource "type_a"
... {...} resource "type_b" ... {...} resource "type_c" ... {...} Practice: Add modules (optional) # ./main.tf module "bakery_kitchen" { source = "./kitchen" oven_count = 10 oven_shape = ... } Reusable chunks of configuration (source can also be remote.) -
# ./main.tf resource "type_a" ... {...} resource "type_b" ... {...}
resource "type_c" ... {...} Practice: Refactor moves (optional) # ./kitchen/main.tf resource "type_a" ... {...} resource "type_b" ... {...} resource "type_c" ... {...} • Add moved{} blocks temporarily (Terraform 1.5+) • Edit the state using terraform state mv • Import existing resources at the new Terraform address $ terraform state mv the.address module.kitchen.the.address -
Practice: Conditional modules (optional) # ./main.tf module "bakery_kitchen" { count
= local.is_bakery_enabled ? 1 : 0 source = "./kitchen" oven_count = 10 oven_shape = ... } Count meta-argument for modules requires Terraform 0.13+ -
Practice: Add outputs (optional) output "endpoint" { value = oven_cluster.management.endpoint
description = "Useful to pass values from modules" } # from root: module.bakery_kitchen.endpoint Outputs from the root module are also useful (debugging). -
Practice: Plan changes $ terraform plan ... Plan: 5 to
add, 1 to change, 5 to destroy. Pay attention to plan output for unexpected change! -
Finale: Donuts as a Service! $ terraform apply ... Apply
complete! Resources: 5 added, 1 changed, 5 destroyed. Pay attention to apply output for unexpected errors! -
Recap: Building in the cloud … • Terraform brings: abstraction,
reconciliation, automation, and improved comprehension • Resources are configured using declarative code • Configure backend, providers, resources, etc. • Modules and variables are optional but useful -
Recap: Building in the cloud … • Terraform brings: abstraction,
reconciliation, automation, and improved comprehension • Resources are configured using declarative code • Configure backend, providers, resources, etc. • Modules and variables are optional but useful • The future of donuts is DaaS -
Thank you! Find me at: • icodealot.com • @icodealot -
x.com, bsky.app -
Image Credits • Unknown. n.d. Colorful Donut Photo. Provided by
Microsoft Office. • Leannk. August 14, 2020. Glazed Donut Photo. Retrieved from Unsplash.