← Back to list

Automating the Start and Stop of RDS Instances with Terraform and AWS Systems Manager

Efficient cloud resource management is essential for optimizing costs and maintaining sustainable operations. In database environments…

César Albuquerque · 2024-11-29 14:10 · 38 claps · 4.0 min read
#aws-rds #aws-ssm #rds-schedule #terraform #cost-cloud-reduce
Open on Medium ↗
Wiki topics: BIZ · Business Strategy ESG · ESG & Sustainability ☁️ · DevOps & Cloud

Automating the Start and Stop of RDS Instances with Terraform and AWS Systems Manager

Efficient cloud resource management is essential for optimizing costs and maintaining sustainable operations. In database environments, stopping RDS instances outside business hours and starting them only when needed is a straightforward yet effective cost-saving strategy.

With AWS Systems Manager (SSM), you can automate routine tasks like starting and stopping RDS instances using Maintenance Windows. By integrating this capability with Terraform, the process becomes even more practical, allowing you to create consistent and replicable solutions.

This guide provides a step-by-step tutorial to configure this automation with Terraform, based on the official AWS guide. You’ll learn to configure IAM permissions, create resource groups, and define maintenance windows to manage RDS instance operating hours.

The example times used here (7:30 AM and 6:15 PM) are based on the São Paulo, Brazil timezone (UTC-3). Adjust them as needed for your location.

Step-by-Step Guide

The solution is organized into clear steps. Each step addresses a specific need in the automation process, from configuring permissions to establishing maintenance windows in SSM for schedule management.

1. Create an IAM Role for AWS SSM

The first step is to configure an IAM role that allows AWS Systems Manager to perform tasks on your RDS instances.

In Terraform, you will define the role and associated policies:

# Create an IAM role to allow SSM to perform tasks on RDS
resource "aws_iam_role" "ssm_maintenance_role" {
  name = "ssm_maintenance_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ssm.amazonaws.com"
        }
      }
    ]
  })
}

2. Create a Custom IAM Policy

Now, create an IAM policy that allows starting and shutting down RDS instances. This policy will be attached to the role you created earlier.

# Create a custom IAM policy to allow SSM to start and stop RDS instances
resource "aws_iam_policy" "ssm_rds_policy" {
  name        = "ssm_rds_policy"
  description = "Policy to allow SSM to start and stop RDS instances"
  policy      = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "rds:StartDBCluster",
          "rds:StopDBCluster",
          "rds:ListTagsForResource",
          "rds:DescribeDBInstances",
          "rds:StopDBInstance",
          "rds:DescribeDBClusters",
          "rds:StartDBInstance"
        ]
        Resource = "arn:aws:rds:*"
      },
      {
        Effect = "Allow"
        Action = [
          "resource-groups:ListGroupResources",
          "resource-groups:GetGroup",
          "resource-groups:GetGroupQuery",
          "ssm:SendCommand",
          "ssm:CancelCommand",
          "ssm:ListCommands",
          "ssm:ListCommandInvocations",
          "ssm:GetCommandInvocation",
          "ssm:GetAutomationExecution",
          "ssm:StartAutomationExecution",
          "ssm:ListTagsForResource",
          "ssm:GetParameters",
          "tag:GetResources"
        ]
        Resource = "*"
      }
    ]
  })
}

# Attach the custom policy to the IAM role
resource "aws_iam_role_policy_attachment" "ssm_maintenance_role_policy" {
  role       = aws_iam_role.ssm_maintenance_role.name
  policy_arn = aws_iam_policy.ssm_rds_policy.arn
}

3. Create a Resource Group in AWS Resource Groups

AWS Resource Groups allow you to group resources, such as RDS instances, based on criteria like tags. This simplifies applying scheduled actions only to the desired resources.

Important Note: All RDS instances you want to include in the automation must have the same tags configured in this step. The solution will work for any RDS instance with the specified tags.

# Create an AWS Resource Groups resource group to filter RDS instances based on tags
resource "aws_resourcegroups_group" "rds_group" {
  name        = "rds-schedule-group"
  description = "Resource group for scheduling RDS start and stop"

  resource_query {
    query = jsonencode({
      ResourceTypeFilters = ["AWS::RDS::DBInstance", "AWS::EC2::Instance"],
      TagFilters = [
        {
          Key    = "Operational-Schedule",
          Values = ["Office-Hours"]
        }
      ]
    })
  }
}

4. Create Maintenance Windows in AWS SSM

Maintenance windows define the times when RDS instances will be started and stopped.

4.1. Window to Start RDS Instances

# Create an AWS SSM maintenance window to start the RDS at 7:30 AM (10:30 UTC) from Monday to Friday
resource "aws_ssm_maintenance_window" "rds_start_maintenance_window" {
  name               = "rds-start-schedule-window"
  schedule           = "cron(30 10 ? * MON-FRI *)"
  duration           = 1
  cutoff             = 0
  allow_unassociated_targets = true
}

4.2. Window to Stop RDS Instances

# Create an AWS SSM maintenance window to stop the RDS at 6:15 PM (21:15 UTC) from Monday to Friday
resource "aws_ssm_maintenance_window" "rds_stop_maintenance_window" {
  name               = "rds-stop-schedule-window"
  schedule           = "cron(15 21 ? * MON-FRI *)"
  duration           = 1
  cutoff             = 0
  allow_unassociated_targets = true
}

5. Define Targets for the Maintenance Windows

Associate the resource group created in Step 3 with the maintenance windows.

# Define the maintenance window target to start the RDS
resource "aws_ssm_maintenance_window_target" "rds_start_target" {
  window_id          = aws_ssm_maintenance_window.rds_start_maintenance_window.id
  resource_type      = "RESOURCE_GROUP"
  targets {
    key    = "resource-groups:Name"
    values = [aws_resourcegroups_group.rds_group.name]
  }
}

# Define the maintenance window target to stop the RDS
resource "aws_ssm_maintenance_window_target" "rds_stop_target" {
  window_id          = aws_ssm_maintenance_window.rds_stop_maintenance_window.id
  resource_type      = "RESOURCE_GROUP"
  targets {
    key    = "resource-groups:Name"
    values = [aws_resourcegroups_group.rds_group.name]
  }
}

6. Create Tasks to Start and Stop RDS Instances

6.1. Task to Start

# Create the maintenance window task to start the RDS using the AWS-StartRdsInstance document
resource "aws_ssm_maintenance_window_task" "rds_start_task" {
  depends_on = [
    aws_resourcegroups_group.rds_group,
    aws_ssm_maintenance_window_target.rds_start_target
  ]
  window_id          = aws_ssm_maintenance_window.rds_start_maintenance_window.id
  targets {
    key    = "WindowTargetIds"
    values = [aws_ssm_maintenance_window_target.rds_start_target.id]
  }
  task_arn           = "arn:aws:ssm:us-east-1::document/AWS-StartRdsInstance"
  service_role_arn   = aws_iam_role.ssm_maintenance_role.arn
  task_type          = "AUTOMATION"
  task_invocation_parameters {
    automation_parameters {
      document_version = "$LATEST"

      parameter {
        name   = "InstanceId"
        values = ["{{RESOURCE_ID}}"]
      }
    }
  }
  priority            = 1
  max_concurrency     = "1"
  max_errors          = "1"
  name                = "StartRDSInstance"
  description         = "Start RDS instance as part of maintenance window"
}

6.2. Task to Stop

# Create the maintenance window task to stop the RDS using the AWS-StopRdsInstance document
resource "aws_ssm_maintenance_window_task" "rds_stop_task" {
  depends_on = [
    aws_resourcegroups_group.rds_group,
    aws_ssm_maintenance_window_target.rds_stop_target
  ]
  window_id          = aws_ssm_maintenance_window.rds_stop_maintenance_window.id
  targets {
    key    = "WindowTargetIds"
    values = [aws_ssm_maintenance_window_target.rds_stop_target.id]
  }
  task_arn           = "arn:aws:ssm:us-east-1::document/AWS-StopRdsInstance"
  service_role_arn   = aws_iam_role.ssm_maintenance_role.arn
  task_type          = "AUTOMATION"
  task_invocation_parameters {
    automation_parameters {
      document_version = "$LATEST"
      parameter {
        name   = "InstanceId"
        values = ["{{RESOURCE_ID}}"]
      }
    }
  }
  priority            = 1
  max_concurrency     = "1"
  max_errors          = "1"
  name                = "StopRDSInstance"
  description         = "Stop RDS instance as part of maintenance window"
}

Conclusion

This guide presented a practical solution to automate RDS instance management using Terraform and AWS Systems Manager. By implementing this automation, you can reduce operational costs by stopping instances outside business hours (considering the São Paulo, Brazil timezone) without compromising efficiency or security.

If you have questions or suggestions, feel free to share them in the comments. 🚀


메타데이터
post_id
9cd98b3fb0c8
slug
automating-the-start-and-stop-of-rds-instances-with-terraform-and-aws-systems-manager-9cd98b3fb0c8
url
https://medium.com/@cesartdealbuquerque/automating-the-start-and-stop-of-rds-instances-with-terraform-and-aws-systems-manager-9cd98b3fb0c8
canonical_url
https://medium.com/@cesartdealbuquerque/automating-the-start-and-stop-of-rds-instances-with-terraform-and-aws-systems-manager-9cd98b3fb0c8
author_url
https://medium.com/@cesartdealbuquerque
status
ok
fetched_at
2026-07-19 10:39:39