AWS S3 Bucket Creation and Management

Vanshika SharmaVanshika Sharma
10 min read

AWS S3 Bucket:

Amazon S3 (Simple Storage Service) is a highly scalable, durable, and secure object storage service provided by AWS. It allows you to store and retrieve any amount of data from anywhere.

Key Features of S3:

Scalability – Automatically scales storage based on demand.
Durability – Provides 99.999999999% (11 nines) durability.
Security – Supports encryption, IAM policies, and access control.
Data Management – It offers versioning, lifecycle policies, and replication.
Cost-Effective – Multiple storage classes (Standard, Glacier, Intelligent-Tiering, etc.) to optimize costs.

Common Use Cases:

Backup and Restore – Store backups securely with lifecycle rules.
Static Website Hosting – Host static websites directly from S3.
Big Data Analytics – Stores large datasets for processing.
Media Storage – Keep images, videos, and documents.
Log Storage – Centralized storage for logs and analytics.

Task 1

  • Create an S3 bucket using Terraform.

  • Configure the bucket to allow public read access.

  • Create an S3 bucket policy that allows read-only access to a specific IAM user or role.

  • Enable versioning on the S3 bucket.

Below is the Terraform script to create an S3 bucket with the following configurations:

  1. Creates an S3 bucket

  2. Allows public read access

  3. Adds a bucket policy for read-only access to a specific IAM user/role

  4. Enables versioning on the bucket


Terraform Configuration for S3 Bucket

provider "aws" {
  region = "us-east-1"  # Change the region as needed
}

# Create S3 Bucket
resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-terraform-s3-bucket-1234"  # Change this to a unique bucket name
}

# Enable Versioning on the Bucket
resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.my_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

# Public Read Access Policy
resource "aws_s3_bucket_public_access_block" "public_access" {
  bucket = aws_s3_bucket.my_bucket.id

  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

# S3 Bucket Policy to Allow Public Read Access
resource "aws_s3_bucket_policy" "public_read" {
  bucket = aws_s3_bucket.my_bucket.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = "*"
        Action    = "s3:GetObject"
        Resource  = "${aws_s3_bucket.my_bucket.arn}/*"
      }
    ]
  })
}

# Read-Only Access for a Specific IAM User or Role
resource "aws_s3_bucket_policy" "read_only_access" {
  bucket = aws_s3_bucket.my_bucket.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = {
          AWS = "arn:aws:iam::123456789012:user/MyUser"  # Replace with actual IAM User or Role ARN
        }
        Action    = "s3:GetObject"
        Resource  = "${aws_s3_bucket.my_bucket.arn}/*"
      }
    ]
  })
}

Steps to Deploy

  1. Initialize Terraform

     terraform init
    
  2. Plan the Deployment

     terraform plan
    
  3. Apply the Configuration

     terraform apply -auto-approve
    

Scaling with Terraform

Understanding Scaling:

Scaling in cloud computing refers to adjusting resources to efficiently handle increased or decreased workloads. It ensures that applications remain performant and cost-effective.


Types of Scaling

1. Vertical Scaling (Scaling Up/Down)

  • Definition: Increasing or decreasing the capacity of a single instance or resource.

  • How? Upgrading CPU, RAM, or storage.

  • Example:

    • Upgrading an EC2 instance from t2.micro to t2.large

    • Increasing the RDS database storage capacity

Pros: Simple, no architectural changes
Cons: Hardware limitations, downtime may be required


2. Horizontal Scaling (Scaling Out/In)

  • Definition: Adding or removing multiple instances to distribute the load.

  • How? Increasing the number of servers dynamically.

  • Example:

    • Adding more EC2 instances behind an Elastic Load Balancer (ELB)

    • Expanding an Auto Scaling Group (ASG) when traffic spikes

Pros: High availability, fault tolerance, no hardware limitations
Cons: Requires proper load balancing and stateless applications


Scaling in AWS Services

  • Auto Scaling – Automatically adjusts EC2 instances based on demand.

  • Elastic Load Balancing (ELB) – Distributes traffic across multiple instances.

  • Amazon RDS Scaling – Vertical scaling is done by increasing the DB instance size.

  • Amazon S3 Scaling – Object storage that scales automatically with demand.

  • AWS Lambda Scaling – Automatically scales based on function invocation.


Choosing the Right Scaling Strategy

  • For high-traffic applicationsHorizontal Scaling (Auto Scaling Groups)

  • For memory-intensive workloadsVertical Scaling (Larger EC2 instance)

  • For unpredictable workloadsServerless Scaling (AWS Lambda)

Task 2: Create an Auto Scaling Group

Auto Scaling Groups are used to automatically add or remove EC2 instances based on the current demand. Follow these steps to create an Auto Scaling Group:

  • In your main.tf file, add the following code to create an Auto Scaling Group:

resource "aws_launch_configuration" "web_server_as" {
  image_id        = "ami-005f9685cb30f234b"
  instance_type  = "t2.micro"
  security_groups = [aws_security_group.web_server.name]

  user_data = <<-EOF
              #!/bin/bash
              echo "<html><body><h1>You're doing really Great</h1></body></html>" > index.html
              nohup python -m SimpleHTTPServer 80 &
              EOF
}

resource "aws_autoscaling_group" "web_server_asg" {
  name                 = "web-server-asg"
  launch_configuration = aws_launch_configuration.web_server_lc.name
  min_size             = 1
  max_size             = 3
  desired_capacity     = 2
  health_check_type    = "EC2"
  load_balancers       = [aws_elb.web_server_lb.name]
  vpc_zone_identifier  = [aws_subnet.public_subnet_1a.id, aws_subnet.public_subnet_1b.id]
}
  • Terraform applies to create the Auto Scaling Group.

Your Terraform script has a few issues that need correction before running terraform apply:

Issues in the Code

  1. Incorrect Launch Configuration Reference:

    • launch_configuration = aws_launch_configuration.web_server_lc.name

    • The resource is named web_server_as, not web_server_lc.

  2. Deprecated Launch Configuration:

    • aws_launch_configuration is deprecated. Use aws_launch_template instead.
  3. Incorrect Load Balancer Reference:

    • load_balancers is used for Classic Load Balancers (ELB).

    • For an Application Load Balancer (ALB), use target_group_arns instead.

  4. Security Group Reference:


Corrected Code Using Launch Template

resource "aws_launch_template" "web_server_lt" {
  name          = "web-server-launch-template"
  image_id      = "ami-005f9685cb30f234b"
  instance_type = "t2.micro"

  vpc_security_group_ids = [aws_security_group.web_server.id]

  user_data = base64encode(<<-EOF
              #!/bin/bash
              echo "<html><body><h1>You're doing really Great</h1></body></html>" > index.html
              nohup python -m SimpleHTTPServer 80 &
              EOF
  )
}

resource "aws_autoscaling_group" "web_server_asg" {
  name                = "web-server-asg"
  min_size            = 1
  max_size            = 3
  desired_capacity    = 2
  vpc_zone_identifier = [aws_subnet.public_subnet_1a.id, aws_subnet.public_subnet_1b.id]

  launch_template {
    id      = aws_launch_template.web_server_lt.id
    version = "$Latest"
  }

  target_group_arns = [aws_lb_target_group.web_server_tg.arn]

  health_check_type = "EC2"
}

Steps to Deploy

  1. Initialize Terraform:

     terraform init
    
  2. Validate the configuration:

     terraform validate
    
  3. Plan the deployment:

     terraform plan
    
  4. Apply the configuration:

     terraform apply -auto-approve
    

This will create an Auto Scaling Group with an ALB target group and ensure smooth scaling of instances.

Task 3: Test Scaling

  • Go to the AWS Management Console and select the Auto Scaling Groups service.

  • Select the Auto Scaling Group you just created and click on the "Edit" button.

  • Increase the "Desired Capacity" to 3 and click on the "Save" button.

  • Wait a few minutes for the new instances to be launched.

  • Go to the EC2 Instances service and verify that the new instances have been launched.

  • Decrease the "Desired Capacity" to 1 and wait a few minutes for the extra instances to be terminated.

  • Go to the EC2 Instances service and verify that the extra instances have been terminated.

Testing Auto Scaling in AWS

Once you've deployed your Auto Scaling Group using Terraform, follow these steps to test its scaling behavior:

Step 1: Increase Desired Capacity

  1. Open the AWS Management Console.

  2. Navigate to EC2 > Auto Scaling Groups.

  3. Find and select the web-server-asg Auto Scaling Group.

  4. Click the Edit button.

  5. Change the Desired Capacity from 2 to 3.

  6. Click Save.

  7. Wait a few minutes for the new instance to be launched.

Step 2: Verify Instance Scaling

  1. Go to EC2 Dashboard.

  2. Click on Instances in the left panel.

  3. Check if a new instance has been added.

  4. Ensure the instance is running.

Step 3: Decrease Desired Capacity

  1. Navigate back to Auto Scaling Groups.

  2. Click on the web-server-asg Auto Scaling Group.

  3. Click Edit and set the Desired Capacity to 1.

  4. Click Save.

  5. Wait a few minutes for the extra instances to be terminated.

Step 4: Verify Termination

  1. Go back to the EC2 Instances page.

  2. Check if the extra instances have been terminated.

  3. Only one instance should remain running.

This test confirms that the Auto Scaling Group dynamically adjusts the number of instances based on the configured desired capacity.

Meta-Arguments in Terraform

  1. count → It creates multiple instances of a resource.

     resource "aws_instance" "web" {
       count = 3
     }
    

    ➝ Creates 3 EC2 instances.

  2. for_each → Iterates over a map or set.

     resource "aws_instance" "web" {
       for_each = toset(["dev", "staging", "prod"])
     }
    

    ➝ Creates instances named dev, staging, and prod.

  3. depends_on → Defines resource dependencies.

     depends_on = [aws_security_group.web_sg]
    

    ➝ Ensure the security group is created before the EC2 instance.

  4. lifecycle → Controls resource behavior.

     lifecycle {
       prevent_destroy = true
     }
    

    ➝ Prevents accidental deletion.

  5. provider → Specifies which provider to use.

     provider = aws.west
    

    ➝ Deploys in the us-west-2 region.

Count:

The count Meta-argument allows you to create multiple instances of a resource dynamically based on a specified number.


Basic Usage

resource "aws_instance" "web" {
  count         = 3
  ami          = "ami-005f9685cb30f234b"
  instance_type = "t2.micro"
}

Creates 3 EC2 instances.

  • Access them using aws_instance.web[0], aws_instance.web[1], etc.

Conditional Resource Creation

resource "aws_instance" "web" {
  count = var.enable_instance ? 1 : 0
  ami   = "ami-005f9685cb30f234b"
  instance_type = "t2.micro"
}

Creates 1 instance if enable_instance is true, otherwise creates none.


Using count.index

resource "aws_instance" "web" {
  count = 3
  ami   = "ami-005f9685cb30f234b"
  instance_type = "t2.micro"

  tags = {
    Name = "Instance-${count.index}"
  }
}

tag instances as Instance-0, Instance-1, and Instance-2.


When to Use count?

  1. When creating multiple identical resources.

  2. When enabling/disabling a resource conditionally.

for_each:

The for_each meta-argument is used to create multiple resources dynamically from a set or map, giving more control than count.


1. Using for_each with a Set

resource "aws_instance" "web" {
  for_each     = toset(["dev", "staging", "prod"])
  ami          = "ami-005f9685cb30f234b"
  instance_type = "t2.micro"

  tags = {
    Name = each.key
  }
}

Creates three instances with names dev, staging, and prod.


2. Using for_each with a Map

resource "aws_instance" "web" {
  for_each = {
    dev     = "t2.micro"
    staging = "t2.small"
    prod    = "t3.medium"
  }

  ami          = "ami-005f9685cb30f234b"
  instance_type = each.value

  tags = {
    Name = each.key
  }
}

Creates three instances with different instance types.


3. Using for_each with a List of Objects

variable "instances" {
  type = list(object({
    name = string
    type = string
  }))
  default = [
    { name = "dev", type = "t2.micro" },
    { name = "staging", type = "t2.small" },
    { name = "prod", type = "t3.medium" }
  ]
}

resource "aws_instance" "web" {
  for_each     = { for inst in var.instances : inst.name => inst }
  ami          = "ami-005f9685cb30f234b"
  instance_type = each.value.type

  tags = {
    Name = each.key
  }
}

Creates instances dynamically from a list of objects.


Terraform Modules

A Terraform module is a reusable collection of Terraform resources that helps organize and manage infrastructure efficiently.

Key Benefits of Modules:

  1. Reusability – Use the same code for multiple projects/environments.

  2. Maintainability – Easier updates and modifications.

  3. Scalability – Manage large infrastructures efficiently.

Types of Modules:

  1. Root Module – The main Terraform configuration where submodules are called.

  2. Child Modules – Reusable, self-contained configurations stored separately.

Using Modules:

  • Modules can be stored locally, in GitHub, or the Terraform Registry.

  • To use a module, specify the source in main.tf:

      module "example" {
        source = "./modules/example-module"
      }
    
  • Best Practice: Use modules for VPC, EC2, S3, RDS, IAM, etc., to simplify Terraform projects.

Task-04

  • Write about different modules of Terraform.

  • Difference between Root Module and Child Module.

  • Are modules and Namespaces are same? Justify your answer for both Yes/No

1. Different Modules in Terraform

Terraform modules are categorized into two main types:

A. Root Module

  • This is the main Terraform configuration where execution starts.

  • It typically includes .tf files (e.g., main.tf, variables.tf, outputs.tf).

  • Calls child modules to structure the infrastructure.

B. Child Module

  • A reusable, self-contained module that can be used within the root module.

  • Helps in organizing and managing infrastructure efficiently.

  • It can be stored locally, in a Git repository, or on the Terraform Registry.


2. Difference Between Root Module and Child Module

FeatureRoot ModuleChild Module
DefinitionThe main Terraform configuration where execution starts.A reusable module used within the root module.
UsageCalls child modules or defines resources directly.Provides pre-defined infrastructure components.
LocationStored in the project’s main directory.Stored in a separate directory or external source (Git, Terraform Registry).
Examplemain.tf, variables.tf, outputs.tf in the project root.modules/vpc/main.tf, modules/ec2/main.tf

3. Are Modules and Namespaces the Same?

No, Modules and Namespaces Are Not the Same

  • Modules: A logical grouping of resources that can be reused (e.g., VPC module, EC2 module).

  • Namespaces: A way to organize resources uniquely, often used in Kubernetes or cloud services (e.g., AWS IAM namespaces).

  • Justification: Modules help structure Terraform configurations, while namespaces help manage resource identification and isolation.

0
Subscribe to my newsletter

Read articles from Vanshika Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vanshika Sharma
Vanshika Sharma

I am currently a B.Tech student pursuing Computer Science with a specialization in Data Science at I.T.S Engineering College. I am always excited to learn and explore new things to increase my knowledge. I have good knowledge of programming languages such as C, Python, Java, and web development.