Skip to content

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.

  1. TF_VAR_instancetype - setting environment variable
  2. terraform apply -var="instancetype=t2.micro"
  3. 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.