DEV Community

Cover image for Getting Started with AWS Infrastructure as Code: A Terraform Guide
Nam Phuong Tran
Nam Phuong Tran

Posted on

Getting Started with AWS Infrastructure as Code: A Terraform Guide

If you're looking to start working with AWS and dive into the world of Terraform, this article is your comprehensive guide. We'll walk you through setting up your Terraform project to work seamlessly with AWS and share essential best practices for a smooth transition.

Section 1: Getting Started with AWS
1.1 Create Your AWS Account
We begin by creating your AWS account, which is your gateway to AWS services. Follow our step-by-step guide to set up your AWS account quickly and efficiently.

1.2 Configure Users
Learn how to configure user accounts in AWS, ensuring proper access control for your team members

1.3 Set Up the AWS CLI
Discover how to install and configure the AWS CLI (Command Line Interface) for managing AWS resources from your local environment.

We have to Configure AWS CLI credentials. In this article I will use Long-term credentials option. But it would be better if you use AWS IAM Identity Center (SSO). This is more secure. However you have to use your root user credentials or an IAM user with sufficient permissions to enable AWS SSO to setup this.

Let’s start with Long-term credentials options first.
Go to the AWS Portal, choice user account then Security Credentials

Image description

Scrolling to the Access Key

Image description
Click to the Create access key button

Image description
Choice the first option (Command line Interface – CLI)

Image description
Tick to the confirmation checkbox and Click to the Next button.

Image description
Because the Secret key only available for the first time so please note that we should copy the value of secret to some where or download csv file before closing the tab.

Section 2: AWS CLI and Terraform
2.1 Installing AWS CLI
Get hands-on with the AWS CLI installation process. Check your installation with aws --version.

2.2 Configure AWS CLI Credentials
Explore different options for configuring AWS CLI credentials, including long-term credentials and more secure AWS IAM Identity Center (SSO) configurations.
Image description
Filling the value corresponding to aws configure command
Now, we are going to create a resource group, that helps us to manage resources better via Tags management.
Image description
It will show you the result
Image description

Section 3: Setting Up Remote State Storage
3.1 Using AWS S3 for Remote State
Secure Remote Backends: Store the Terraform state in secure remote backends such as AWS S3.

Image description

In AWS, the Services should be enabled tagging the tag. That can help us to manage services better. It is also the tagged the service into the resource group

Image description
After creating the S3 bucket, we can see it on the AWS portal.

Image description
Go to the Resource group and check. Awesome, they look as expected.

Image description

Section 4: DynamoDB for State Locking
4.1 Understanding State Locking
As you know that, using DynamoDB for state locking enhances the reliability and scalability of Terraform workflows, especially in environments with multiple users or automation processes working concurrently. It helps ensure that infrastructure changes are applied safely and consistently while preventing conflicts and data corruption.
Terraform uses state files to keep track of resource information and dependencies. When multiple users or automation processes work with Terraform concurrently, there's a risk of conflicts and data corruption. DynamoDB provides built-in concurrency control mechanisms, ensuring that only one process can acquire a lock for a particular state file at a given time. This prevents conflicts and ensures consistent state management.
Terraform provides built-in support for using DynamoDB as a backend for state locking. Configuring Terraform to use DynamoDB is straightforward, and it seamlessly integrates with the Terraform CLI.
So, we are going to create Dynamo table

4.2 Creating a DynamoDB Table
Step-by-step instructions on creating a DynamoDB table to serve as the state locking mechanism

Image description
It should be also tagged then it will show in the resource group

Image description

Awesome, now let’s start write Terraform code

Section 5: Writing Terraform Modules
5.1 Terraform Configuration
Setting up your Terraform project with the required providers, including AWS and optional Kubernetes configurations.

Image description

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.16.2"#"~> 4.16"
    }

    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = ">= 2.16.1"
    }
  }

  required_version = ">= 1.2.0"
}
provider "aws" {
  region = "us-east-1"
}
terraform {
  backend "s3" {
    bucket         = "s3-terraform-state-use1"
    key            = "terraform.tfstate"   # State file name
    region         = "us-east-1"           # Use your desired AWS region
    encrypt        = true                  # Optionally, enable server-side encryption
    dynamodb_table = "ddb-statelock-table" # Optional, use a DynamoDB table for state locking
  }
}
Enter fullscreen mode Exit fullscreen mode

5.2 Creating a Resource Group
Learn how to define a Terraform resource group to organize AWS resources based on tags.

resource "aws_resourcegroups_group" "rg" {
  name = join("-", [var.resource_type, var.application, var.application_environment, var.region_short])

  resource_query {
    query = <<JSON
    {
      "ResourceTypeFilters": [
        "AWS::AllSupported"
      ],
      "TagFilters": [
        {
          "Key": "Environment",
          "Values": ["${var.workload_environments}"]
        },
        {
          "Key": "ApplicationEnvironment",
          "Values": ["${var.application_environment}"]          
        },
        {
          "Key": "OpsTeam",
          "Values": ["${var.ops_team}"]
        },
        {
          "Key": "Owner",
          "Values": ["${var.owner}"]
        },{
          "Key": "Criticality",
          "Values": ["${var.business_criticality}"]          
        },{
          "Key": "OpsCommitment",
          "Values": ["${var.ops_commitment}"]          
        },{
          "Key": "ApplicationName",
          "Values": ["${upper(var.application)}"]
        }
      ]
    }
  JSON
  }
}
Enter fullscreen mode Exit fullscreen mode

5.3 Configuring S3 Buckets
Create S3 buckets for your infrastructure components, making them public and configuring website settings.

resource "aws_s3_bucket" "s3" {
  bucket = join("-", [var.resource_type, var.application, var.application_environment, var.region_short]) #"s3-static-website-bucket"                                                                               # Make the bucket public

  tags = {
    Environment            = var.workload_environments
    ApplicationEnvironment = var.application_environment
    OpsTeam                = var.ops_team
    Owner                  = var.owner
    Criticality            = var.business_criticality
    OpsCommitment          = var.ops_commitment
    ApplicationName        = upper(var.application)
  }
  depends_on = [ var.resource_group]
}

resource "aws_s3_bucket_website_configuration" "s3_website" {
  bucket = aws_s3_bucket.s3.id

  index_document {
    suffix = "index.html"
  }

  error_document {
    key = "error.html"
  }

  routing_rule {
    condition {
      key_prefix_equals = "docs/"
    }
    redirect {
      replace_key_prefix_with = "documents/"
    }
  }

  depends_on = [ var.resource_group]
}
Enter fullscreen mode Exit fullscreen mode

Section 6: Module Integration in Main Configuration
6.1 Integrating the Resource Group Module
See how to call and configure the resource group module in your

main configuration.
module "rg" {
  for_each                = var.application_environments
  source                  = "./modules/resource-group"
  resource_type           = "rg"
  application             = var.organization
  workload_environments   = var.workload_environments
  application_environment = each.value #var.application_environment# 
  region                  = var.region
  region_short            = var.region_short
  ops_team                = var.ops_team
  owner                   = var.owner
  business_criticality    = var.business_criticality
  ops_commitment          = var.ops_commitment
}
Enter fullscreen mode Exit fullscreen mode

6.2 Integrating the S3 Bucket Module
Integrate the S3 bucket module into your main configuration and link it to your resource group.

module "s3" {
  for_each                = var.application_environments
  source                  = "./modules/bucket"
  resource_type           = "s3"
  application             = var.organization
  workload_environments   = var.workload_environments
  application_environment = each.value #var.application_environment#
  region                  = var.region
  region_short            = var.region_short
  ops_team                = var.ops_team
  owner                   = var.owner
  business_criticality    = var.business_criticality
  ops_commitment          = var.ops_commitment
  resource_group          = module.rg[each.value]
  resource_group_id       = module.rg[each.value].resource_group_id
  resource_group_arn      = module.rg[each.value].resource_group_arn
}
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

Image description

Image description

Image description

Source code: https://github.com/namphuongtran/aws-infrastructure
By the end of this article, you'll have a firm grasp of setting up AWS and Terraform for your infrastructure needs. The included best practices will ensure you're working efficiently and effectively in your new AWS environment.

Top comments (0)