In this presentation, we will cover intermediate Terraform topics including alternative providers, collection types, loops and conditionals, and resource lifecycles. We will also focus on reusability with a discussion on modules, data sources, and remote state (including live demo examples).
Finally, we start the initial look into a full DevOps process with a quick review of Workspaces and Terraform Cloud; and wrap everything up with some key takeaway learning resources in your Terraform learning adventure.
NOTE: A recording this presentation can be found here: https://youtu.be/0CEF4eZ6HiQ
3. Microsoft’s investments in
Terraform
Microsoft Team HashiCorp Team
Terraform AzureRM Provider updates
◦ Latest release (July 2, 2020)
enhancements/bug fixes
releases/updates published in June alone!
Terraform Module Registry
◦ https://registry.terraform.io/browse/modules?provider=azurerm
5. Terraform v0.13 highlights
Support for , , and
New syntax
Custom
command connects a CLI user to the Terraform
Cloud app
variable "image_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
validation {
condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
error_message = "The image_id value must be a valid AMI id, starting with "ami-"."
}
}
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.0.0"
}
}
}
8. Terraform commands
Terraform fmt (-recursive)
Used to rewrite Terraform configuration files to a canonical format and style
Terraform graph
Used to generate a visual representation of either a configuration or execution plan
Terraform show
Used to provide human-readable output from a state or plan file
Terraform validate
Runs checks that verify whether a configuration is syntactically valid and internally consistent
Terraform taint
Manually marks a Terraform-managed resource as tainted, forcing it to be destroyed and recreated on
the next apply
9. Alternative/non-default provider
Optionally define multiple alternative ("aliased") configurations for a
single provider, to allow management of resources in different regions in
multi-region services
A resource always has an implicit dependency on its associated provider,
to ensure that the provider is fully configured before any resource
actions are taken
Arbitrary (ie. variable/parameter) expressions are not permitted for
provider because it must be resolved while Terraform is constructing the
dependency graph, before it is safe to evaluate expressions
10. Collections Types (Lists, Maps, and Sets)
list (or tuple) is a sequence of values, like ["us-west-1a", "us-west-1c"]
map (or object) is a group of values identified by named labels,
like {name = "Mabel", age = 52}
set(...) is a collection of unique values that do not have any secondary
identifiers or ordering
Note: When a list or tuple is converted to a set, duplicate values are
discarded, and the ordering of elements is lost
11. Loops and Conditionals
Loops allow you to create many of the same resource at the same time
The count meta-argument accepts a whole number and creates that many instances of the resource
The for_each meta-argument accepts a map or a set of strings and creates an instance for each item in
that map or set
The for expression iterates over each element, and then evaluates the expression, with X set to each
respective element
A conditional expression uses the value of a bool expression to select one of two values
Allows you to prevent a resource being created, updated or deleted given a certain condition
12. Lifecycle
The lifecycle block and its contents are meta-arguments, available for all resource blocks regardless of
type.
create_before_destroy (bool)
The new replacement object is created first, and then the prior object is destroyed only once the
replacement is created
prevent_destroy (bool)
Cause Terraform to reject (with an error) any plan that would destroy the infrastructure object
associated with the resource, as long as the argument remains present in the configuration
ignore_changes (list of attribute names)
Share management responsibilities of a single object with a separate process
Specifies resource attributes that Terraform should ignore when planning updates to the associated
remote object
14. Modules
A container for multiple resources that are used together
Can call other modules, which lets you include the child
module's resources
When sourced from local file paths do not support version,
since they're loaded from the same source repository
All modules require a source argument, which can either be
the path to a local directory, or a remote module source
After adding, removing, or modifying module blocks, you must
re-run terraform init to allow Terraform the opportunity to
adjust the installed modules
BONUS!
Terraform v0.13.0 beta
Modules will support…
count, for_each, and
depends_on
15. Data sources
Allows a Terraform configuration to make use of information
defined outside of Terraform, or defined by another separate
Terraform configuration
A data block requests that Terraform read from a given data
source (“azurerm_virtual_network") and export the result
under the given local name (“ProdVNET")
Within the block body (between { and }) are query constraints
defined by the data source
16. Remote state
Allows you to use the root-level outputs of one or more
Terraform configurations as input data for another
configuration
Only the root-level outputs from the remote state are
accessible. Outputs from modules within the state cannot
be accessed.
If you want a module output or a resource attribute to be
accessible via a remote state, you must thread the output
through to a root output.
17. Bonus! TFLint
A part of the GitHub Super Linter
One linter to rule them all
Used to validate against issues
Focused on possible errors, , etc.
Support for all providers
Rules that warn against
AWS = 700+ rules
Azure = 279 rules (Experimental support)
GCP = WIP
20. Workspaces (CLI)
Used to manage collections of infrastructure resources and organize them into meaningful
groups by keeping their configurations (ie. state data, variables) in separate directories
Technically equivalent to renaming your state file
Example:
Code used for a production environment's infrastructure could be split into a networking
configuration, the main application's configuration, and a monitoring configuration
After splitting the code, you would create "networking-prod", "app1-prod", "monitoring-
prod" workspaces, and assign separate teams to manage them
The important thing about workspace internals is that workspaces are meant to be a shared
resource. They aren't a private, local-only notion.
Note: Terraform Cloud and Terraform CLI both have
features called "workspaces," but they're slightly
different. CLI workspaces are alternate state files in
the same working directory; they're a convenience
feature for using one configuration to manage
multiple similar groups of resources.
21. Terraform Cloud
Manages easy access to shared state and secret data, access controls for approving changes to
infrastructure, a private registry for sharing Terraform modules, detailed policy controls for
governing the contents of Terraform configurations
Terraform Cloud acts as a remote backend for your Terraform state. State storage is tied to
workspaces, which helps keep state associated with the configuration that created it.
Performs Terraform runs to provision infrastructure, either on demand or in response to various
events
Executes these runs on disposable virtual machines in its own cloud infrastructure
Remote execution helps provide consistency and visibility for critical provisioning operations
app.terraform.io
23. Resources
Adin’s personal curated list of Terraform resources
Advanced Tips & Tricks to Optimize your Terraform Code
Terraform Advanced
Terraform on Microsoft Azure: Terraform projects organization and modules
How to create reusable infrastructure with Terraform modules
Terraform tips & tricks: loops, if-statements, and gotchas
Terraform in Action
Don’t forget about these Visual Studio
Code (VS Code) extensions:
Azure Terraform (by Microsoft)
Terraform (by Mikael Olenfalk)
Now owned by HashiCorp!
Demo example code: https://github.com/mspnp/hadrinf/tree/master/Templates/Terraform/Networking
24. More resources
Terraform Configurations in Terraform Cloud Workspaces
Terraform Modules hands-on lab
Azure Terraform QuickStart Templates
Misadventures with Terraform
Commodified IaC Using Terraform Cloud
Getting Started with Terraform on Azure: Functions, Expressions, and Loops
Introducing TerraGoat, a “vulnerable-by-design” Terraform training project
26. This is me
Adin Ermie
Cloud Solution Architect – Azure Apps & Infra @ Microsoft
◦ Azure Infrastructure-as-a-Service (IaaS), Platform-as-a-Service (PaaS)
◦ Cloud Management & Security
◦ Azure Monitor, Azure Security Center (ASC) / Azure Sentinel
◦ Cloud Governance
◦ Azure Policy, Blueprints, Management Groups, and Azure Cost Management (ACM)
◦ Business Continuity and Disaster Recovery (BCDR)
◦ Azure Site Recovery (ASR) / Azure Migrate, and Azure Backup
◦ Infrastructure-as-Code (IaC)
◦ Azure Resource Manager (ARM), and Terraform
5x MVP - Cloud and Datacenter Management (CDM)
1x HCA – HashiCorp Ambassador
Adin.Ermie@outlook.com
@AdinErmie
https://AdinErmie.com
linkedin.com/in/adinermie
Notes de l'éditeur
Terraform Graph:
The output is in the DOT format, which can be used by GraphViz to generate charts.
Terraform Show:
This can be used to inspect a plan to ensure that the planned operations are expected, or to inspect the current state as Terraform sees it.
Terraform Validate:
Primarily useful for general verification of reusable modules, including correctness of attribute names and value types.
Terraform Taint:
This command will not modify infrastructure, but does modify the state file in order to mark a resource as tainted. Once a resource is marked as tainted, the next plan will show that the resource will be destroyed and recreated and the next apply will implement this change.
Note that tainting a resource for recreation may affect resources that depend on the newly tainted resource.
The provider meta-argument overrides Terraform's default behavior of selecting a provider configuration based on the resource type name.
By default, Terraform takes the initial word in the resource type name (separated by underscores) and selects the default configuration for that named provider.
For example, the resource type azurerm_resource_group is associated automatically with the default configuration for the provider named azurerm.
The provider meta-argument expects a <PROVIDER>.<ALIAS> reference, which does not need to be quoted.
Count:
If the resource has the count argument set, the value of this expression is a list of objects representing its instances.
Each instance has a distinct infrastructure object associated with it and each is separately created, updated, or destroyed when the configuration is applied.
When count is set, Terraform distinguishes between the resource block itself and the multiple resource instances associated with it. Instances are identified by an index number, starting with 0.
<TYPE>.<NAME>[<INDEX>] (for example, aws_instance.server[0], aws_instance.server[1], etc.) refers to individual instances.
For Each:
If your resource instances are almost identical, count is appropriate. If some of their arguments need distinct values that can't be directly derived from an integer, it's safer to use for_each.
The for_each meta-argument accepts a map or a set of strings and creates an instance for each item in that map or set.
For:
A for expression can also include an optional if clause to filter elements from the source collection, which can produce a value with fewer elements than the source
If the result type is an object (using { and } delimiters) then the value result expression can be followed by the ... symbol to group together results that have a common key
Create Before Destroy:
By default, when Terraform must make a change to a resource argument that cannot be updated in-place due to remote API limitations, Terraform will instead destroy the existing object and then create a new replacement object with the new configured arguments.
Some resource types offer special options to append a random suffix onto each object name to avoid collisions, for example. Terraform CLI cannot automatically activate such features, so you must understand the constraints for each resource type before using create_before_destroy with it.
Prevent Destroy:
This can be used as a measure of safety against the accidental replacement of objects that may be costly to reproduce, such as database instances
Note that this setting does not prevent the remote object from being destroyed if the resource block were removed from configuration entirely
Ignore Changes:
In some rare cases, settings of a remote object are modified by processes outside of Terraform, which Terraform would then attempt to "fix" on the next run.
Think about when using Azure Policy and ‘deployIfNotExists’ policy actions
Terraform Modules are a way that you can encapsulate shared code.
The module takes inputs, does something and then produces outputs. By refactoring parts of your infrastructure into Modules you can easily enforce standards and keep resources in sync.
Explain how you create a module (i.e a folder IS a module), and how you use a module (code-call).
How do you reference an existing resource that was either deployed by a different Terraform template/process/workflow; or, already exists within the target environment (ie. a VNET)?
Previous example was using Data Sources but this example is more real-world for the separation of, say, the Networking code vs Application code.
For example, the Networking team can have their own workspace, state, modules, etc. and produces outputs for VNET and Subnet IDs.
The Application team needs to leverage the VNET ID for deploying their App.
So they can point to the appropriate backend containing the VNET state, and directly reference it.
Remote state provides an easy reference to dynamic configuration parameters based on the output of other modules
It is a simple way to handle “cross-stack” references in Terraform
Highlight the NOTE first
Terraform Cloud offers a team-oriented remote Terraform workflow
The foundations of this workflow are remote Terraform execution, a workspace-based organizational model, version control integration, command-line integration, remote state management with cross-workspace data sharing, and a private Terraform module registry.
NEWS: HashiICorp just recently (as of June 10th) released the v2 of the VS Code extension
Important as this is the first official release from HashiCorp since taking over the extension
See my blog for an article showing it in action!