Intro / General
Terraform Editions
- Terraform Open Source is a free, downloadable tool that allows you to provision infrastructure on any cloud provider and manage configuration, plugins, infrastructure, and state via the command line.
- Terraform Cloud is a SaaS application that runs Terraform in a stable, remote environment, securely stores state and secrets, and offers a rich user interface, role-based access controls, and a private registry for sharing modules and providers. It also integrates with common version control systems (VCS) like GitHub, GitLab, and Bitbucket.
- Terraform Enterprise is similar to Terraform Cloud but is designed for larger organizations with complex technical and collaboration challenges. It provides a central way for many users within the organization to safely and efficiently provision and manage their infrastructure.
Basic configuration
- Required providers and providers block.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
- When you do
terraform init
, it downloads all the code required for the provider AWS and that specific version. terraform destroy -target module.eks
will destroy a specific target.- The tfstate file has the state information. If you manually delete the EC2 instance or change its attributes in AWS and run
terraform apply
again, it will recreate the instance as long as you have defined that attribute while creating it through terraform. - The tfstate file should be stored externally to maintain a steady state.
- When you run
terraform apply -refresh-only
, Terraform will update the state file to match the changed configuration in AWS. You however have to update the configuration files manually.
Variables
Create Terraform variables wherever required and assign default values.
TF_VAR_instancetype
- setting environment variableterraform apply -var="instancetype=t2.micro"
terraform apply -var-file="custom.tfvars"
string
variable "instance_name" {
type = string
default = "my-instance"
}
number
variable "instance_count" {
type = number
default = 1
}
boolean
variable "enable_feature" {
type = bool
default = true
}
list
variable "subnets" {
type = list(string)
default = ["subnet-12345678", "subnet-87654321", "subnet-abcd1234"]
}
List is an ordered collection of values, while a set is an unordered collection of unique values. Lists are indexed by position and duplicates are allowed, while sets are not indexed and cannot contain duplicates. When working with lists, you can access individual elements using an index, while sets do not support indexing.
Set
variable "subnets" {
type = set(string)
default = ["subnet-12345678", "subnet-87654321", "subnet-abcd1234"]
}
In this example, the subnets
variable is defined as a set of strings. The default
value is a list of subnet IDs, which will be converted to a set automatically by Terraform. Sets are unordered collections of unique values, so any duplicates in the list will be removed when it is converted to a set.
Object
Here's an example of an object in Terraform:
variable "instance" {
type = object({
instance_type = string
ami_id = string
subnet_id = string
})
default = {
instance_type = "t2.micro"
ami_id = "ami-0c55b159cbfafe1f0"
subnet_id = "subnet-12345678"
}
}
resource "aws_instance" "example" {
instance_type = var.instance.instance_type
ami = var.instance.ami_id
subnet_id = var.instance.subnet_id
}
Objects are a complex data type in Terraform that can store multiple values of different types. They are defined using the object
type, which requires a map of attribute names to their corresponding types. Object attributes can be accessed using dot notation, like var.instance.instance_type
in this example.
Object attributes can be accessed using dot notation, while map keys can be accessed using square brackets. Generally, maps are used to store simple data structures, while objects are used to store more complex data structures.
tuple
Here is an example of using a tuple in Terraform with 5 different elements in an array:
variable "tuple_example" {
type = tuple([string, number, bool, list(string), map(string, number)])
default = ["example", 123, true, ["value1", "value2"], {"key1" = 1, "key2" = 2}]
}
resource "example_resource" "example" {
name = var.tuple_example[0]
count = var.tuple_example[1]
is_enabled = var.tuple_example[2]
values = var.tuple_example[3]
mapping = var.tuple_example[4]
}
Tuples are useful for grouping together values of different types and can be used in a variety of ways in Terraform configurations.
map
variable "instance_tags" {
type = map(string)
default = {
Name = "Web Server"
Environment = "Production"
Owner = "John Doe"
}
}
Generate terraform configuration
- Use Terraform import command to import existing infrastructure resources into Terraform state in order to manage them with Terraform. The
terraform import
command only updates the Terraform state file; it does not create or modify the Terraform configuration files. - Define a resource block for the instance with
resource "aws_instance" "my_ec2_instance" {...}
in Terraform configuration file - Run
terraform import
command with the resource block's address and ID of the instance to import the instance to Terraform state:terraform import aws_instance.my_ec2_instance i-0123456789abcdef
- Update the instance's configuration by modifying its resource block arguments and running
terraform apply
- Similar process can be used to import other types of resources such as VPCs and security groups
Create resources in multiple AWS accounts
- To create resources in multiple AWS accounts using a single Terraform script, define multiple provider blocks with different aliases and credentials.
- Each provider block represents a different AWS account, and you can reference them in your Terraform resources using the
provider
meta-argument. - Here's an example:
provider "aws" {
alias = "account1"
region = "us-east-1"
profile = "account1"
}
provider "aws" {
alias = "account2"
region = "us-west-2"
profile = "account2"
}
resource "aws_instance" "example1" {
provider = aws.account1
}
resource "aws_instance" "example2" {
provider = aws.account2
}
- This allows you to create resources in multiple AWS accounts using a single Terraform script.
- You can use a similar approach to create other types of resources in multiple AWS accounts.
Create resources in multiple AWS regions
- To create resources in multiple AWS regions using Terraform, define multiple provider blocks with different aliases and regions.
- Each provider block represents a different AWS region, and you can use the
alias
attribute to give each provider block a unique name. - Reference the different providers in your Terraform resources using the
provider
meta-argument. - Example:
- This approach can be used to create other types of resources in multiple AWS regions.
provider "aws" {
alias = "us-east-1"
region = "us-east-1"
}
provider "aws" {
alias = "us-west-2"
region = "us-west-2"
}
resource "aws_instance" "example1" {
provider = aws.us-east-1
}
resource "aws_instance" "example2" {
provider = aws.us-west-2
}
Sentinel in terraform cloud
Using Sentinel and OPA with Terraform Cloud provides several benefits that enhance the overall management and security of your infrastructure. Using Sentinel with Terraform Cloud provides a powerful mechanism to enforce policies, increase security, and maintain compliance in your infrastructure deployments. It gives you greater control and confidence in managing your cloud resources while promoting best practices and reducing the risk of misconfiguration. Here are some specific reasons and examples on why you would use Sentinel with Terraform Cloud:
- Policy Enforcement: Sentinel and OPA enable you to define and enforce policies that govern the configurations and changes made to your infrastructure. You can create custom policies tailored to your organization's needs, ensuring compliance with regulatory requirements, security best practices, and internal standards.
- Automated Governance: With Sentinel and OPA, you can implement automated governance and compliance checks in your Terraform workflows. This means that every time changes are proposed or applied, Sentinel or OPA evaluates those changes against the defined policies, automatically preventing non-compliant configurations from being deployed.
- Enhanced Security: By incorporating Sentinel or OPA into your Terraform Cloud environment, you can bolster your infrastructure security. Sentinel can flag and block any potentially risky configurations, helping to minimize security vulnerabilities and ensuring that only approved, secure changes are allowed.
- Version-controlled Policies: Sentinel and OPA policies are defined as code, which means they can be stored in version control alongside your Terraform configurations. This allows your policies to be managed, reviewed, and updated through the same version control system, improving collaboration and maintaining a history of policy changes.
- Custom Approval Workflows: You can create customized approval workflows based on policy conditions using Sentinel or OPA. This means that changes to the infrastructure can be automatically approved or flagged for manual review, depending on the defined policies, ensuring tighter control over infrastructure modifications.
- Preventing Costly Mistakes: Sentinel and OPA policies can help catch potential mistakes or misconfigurations before they impact your infrastructure. By running policy checks in real-time, you can identify issues early on and avoid costly downtime or unexpected behavior caused by incorrect configurations.
- Consistency and Best Practices: Utilizing Sentinel/OPA allows you to enforce consistent naming conventions, tagging standards, and other best practices across your infrastructure. This consistency leads to improved manageability and makes it easier for teams to collaborate effectively.
- Auditing and Compliance Reporting: With Sentinel's logging and reporting capabilities, you can track policy decisions and changes made to your infrastructure over time. This audit trail is valuable for compliance purposes and can be used to demonstrate adherence to regulatory requirements.
Terraform and GoLang
The relation between Terraform and Golang is that Terraform has a plugin system that allows developers to create custom providers and provisioners using Golang. This means that developers can use Golang to extend the functionality of Terraform by creating custom plugins that can interact with additional services or APIs. Additionally, there are several libraries and tools available for integrating Terraform with Golang projects, such as the terraform-plugin-go
library which provides low-level Go bindings for the Terraform plugin protocol.