<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Prashant Bhatasana</title>
    <description>The latest articles on DEV Community by Prashant Bhatasana (@prashant_b).</description>
    <link>https://dev.to/prashant_b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F634518%2Fc84c9888-069f-4406-b5b6-7189df4107fd.png</url>
      <title>DEV Community: Prashant Bhatasana</title>
      <link>https://dev.to/prashant_b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prashant_b"/>
    <language>en</language>
    <item>
      <title>Terraform — Deploying Multi-Region AWS RDS Cluster with Failover Setup using Terraform</title>
      <dc:creator>Prashant Bhatasana</dc:creator>
      <pubDate>Wed, 21 May 2025 09:59:47 +0000</pubDate>
      <link>https://dev.to/aws-builders/terraform-deploying-multi-region-aws-rds-cluster-with-failover-setup-using-terraform-4ahg</link>
      <guid>https://dev.to/aws-builders/terraform-deploying-multi-region-aws-rds-cluster-with-failover-setup-using-terraform-4ahg</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6falaq0t3hsli2ff5ez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6falaq0t3hsli2ff5ez.png" alt="https://medium.com/devops-pro/terraform-deploying-multi-region-aws-rds-cluster-with-failover-setup-using-terraform-89e98da026f7" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will go through how to deploy a multi-region AWS RDS cluster with an automatic failover setup using Terraform. By leveraging AWS RDS (Relational Database Service) and Terraform, we can set up highly available, fault-tolerant database architectures across multiple regions. This ensures that your applications remain online even in the event of regional outages, providing resilience and scalability for critical applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Account: An active AWS account with the necessary permissions.&lt;/li&gt;
&lt;li&gt;AWS CLI: AWS CLI should be configured with your AWS credentials.&lt;/li&gt;
&lt;li&gt;Terraform Installed: Terraform must be installed on your local machine. You can download it from Terraform’s official site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, let’s start!&lt;/p&gt;

&lt;h2&gt;
  
  
  → Create a ”provider.tf”
&lt;/h2&gt;

&lt;p&gt;The provider file tells Terraform which provider you are using.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = local.region_0
  profile = "&amp;lt;profile-name&amp;gt;"

  default_tags {
    tags = {
      Owner       = "primary"
      Project     = "AWS Multi Region rds with active/active setup"
      Provisioner = "Terraform"
    }
  }
}

provider "aws" {
  alias  = "secondory"
  region = local.region_1
  profile = "&amp;lt;profile-name&amp;gt;"

  default_tags {
    tags = {
      Owner       = "secondory"
      Project     = "AWS Multi Region rds with active/active setup"
      Provisioner = "Terraform"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  → Create “data.tf”
&lt;/h2&gt;

&lt;p&gt;Terraform data sources allow you to fetch information from your cloud provider and use it within your configuration. This can be particularly useful for validating inputs, such as checking the list of availability zones in a given region to see if a specific Amazon Machine Image (AMI) ID exists in that region before creating an EC2 instance.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_availability_zones" "region_0" {}
data "aws_availability_zones" "region_1" {
  provider = aws.secondory
}
data "aws_caller_identity" "this" {}
data "aws_kms_key" "rds_0" {
  key_id = "alias/aws/rds"
}
data "aws_kms_key" "rds_1" {
  provider = aws.secondory
  key_id   = "alias/aws/rds"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  → Create “locals.tf”
&lt;/h2&gt;

&lt;p&gt;Terraform Locals are named values that can be assigned and used in your code. It mainly serves the purpose of reducing duplication within the Terraform code. When you use Locals in the code, since you are reducing duplication of the same value, you also increase the readability of the code.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;locals {
environment = replace("${var.environment_input}", "_", "-")

availability_zones_0 = data.aws_availability_zones.region_0.names
  public_subnets_0 = [
    cidrsubnet(local.vpc_cidr_0, 6, 0),
    cidrsubnet(local.vpc_cidr_0, 6, 1),
    cidrsubnet(local.vpc_cidr_0, 6, 2),
  ]
  private_subnets_0 = [
    cidrsubnet(local.vpc_cidr_0, 6, 4),
    cidrsubnet(local.vpc_cidr_0, 6, 5),
    cidrsubnet(local.vpc_cidr_0, 6, 6),
  ]
  database_subnets_0 = [
    cidrsubnet(local.vpc_cidr_0, 6, 7),
    cidrsubnet(local.vpc_cidr_0, 6, 8),
    cidrsubnet(local.vpc_cidr_0, 6, 9),
  ]

  availability_zones_1 = data.aws_availability_zones.region_1.names
  public_subnets_1 = [
    cidrsubnet(local.vpc_cidr_1, 6, 0),
    cidrsubnet(local.vpc_cidr_1, 6, 1),
    cidrsubnet(local.vpc_cidr_1, 6, 2),
  ]
  private_subnets_1 = [
    cidrsubnet(local.vpc_cidr_1, 6, 4),
    cidrsubnet(local.vpc_cidr_1, 6, 5),
    cidrsubnet(local.vpc_cidr_1, 6, 6),
  ]
  database_subnets_1 = [
    cidrsubnet(local.vpc_cidr_1, 6, 7),
    cidrsubnet(local.vpc_cidr_1, 6, 8),
    cidrsubnet(local.vpc_cidr_1, 6, 9),
  ]

  database_username = "aurora_admin"
  database_password = "aurora_admin123"

  region_0 = "us-west-1"
  region_1 = "us-west-2"

  vpc_cidr_0 = "20.1.0.0/16"
  vpc_cidr_1 = "30.2.0.0/16"

  vpc_route_tables_0 = flatten([module.vpc_0.private_route_table_ids, module.vpc_0.public_route_table_ids])
  vpc_route_tables_1 = flatten([module.vpc_1.private_route_table_ids, module.vpc_1.public_route_table_ids])
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Terraform Locals vs Variables
&lt;/h2&gt;

&lt;p&gt;How does Terraform local differ from a Terraform variable?&lt;/p&gt;

&lt;p&gt;The first difference can be pointed towards the scope. A Local is only accessible within the local module vs a Terraform variable, which can be scoped globally.&lt;/p&gt;

&lt;p&gt;Another thing to note is that a local in Terraform doesn’t change its value once assigned. A variable value can be manipulated via expressions. This makes it easier to assign expression outputs to locals and use them throughout the code instead of using the expression itself at multiple places.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: For demonstration, I have used both locals and variables; however, you can modify them according to your use case.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  → Create “variables.tf”
&lt;/h2&gt;

&lt;p&gt;All variables will be in this file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "environment_input" {
  description = "Environment name we are building"
  default     = "aws_multi_region"
}

variable "tags" {
  description = "Default tags for this environment"
  default     = {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you are using terraform.tfvars, you need to add a description only.&lt;/p&gt;
&lt;h2&gt;
  
  
  → Create a "terraform.tfvars
&lt;/h2&gt;

&lt;p&gt;To persist variable values, create a file and assign variables within this file. Create a file named terraform.tfvars With the following contents:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;environment = "aws_multi_region_aurora"
tags        = {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For all files that match terraform.tfvars or *.auto.tfvars present in the current directory, Terraform automatically loads them to populate variables. If the file is named something else, you can use the -var-file flag directly to specify a file.&lt;/p&gt;

&lt;p&gt;I don’t recommend saving usernames and passwords to version control, but you can create a local secret variables file and use -var-file to load it.&lt;/p&gt;
&lt;h2&gt;
  
  
  → Create a “vpc.tf"
&lt;/h2&gt;

&lt;p&gt;For this demo, I'm using different VPC modules to show how we can use external modules in Terraform, but you can follow this article and use my VPC module for this setup as well&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/appgambit/terraform-aws-vpc-with-private-public-subnets-with-nat-4094ad2ab331?source=post_page-----89e98da026f7---------------------------------------" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A64%3A64%2F1%2ACZQ9AWu5XGvAB5cq9NR4Vw.png" alt="Prashant Bhatasana"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/appgambit/terraform-aws-vpc-with-private-public-subnets-with-nat-4094ad2ab331?source=post_page-----89e98da026f7---------------------------------------" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Terraform — AWS VPC with Private, Public Subnets with NAT | by Prashant Bhatasana | AppGambit | Medium&lt;/h2&gt;
      &lt;h3&gt;Prashant Bhatasana ・ &lt;time&gt;Oct 9, 2020&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_region" "current" {}

module "vpc_0" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~&amp;gt; 5.13.0"

  azs                                             = local.availability_zones_0
  cidr                                            = local.vpc_cidr_0
  create_database_subnet_group                    = true
  create_flow_log_cloudwatch_iam_role             = true
  create_flow_log_cloudwatch_log_group            = true
  # database_subnets                                = local.database_subnets_0
  database_subnets                                = local.database_subnets_0
  enable_dhcp_options                             = true
  enable_dns_hostnames                            = true
  enable_dns_support                              = true
  enable_flow_log                                 = true
  enable_ipv6                                     = false
  # enable_nat_gateway                              = true
  flow_log_cloudwatch_log_group_retention_in_days = 7
  flow_log_max_aggregation_interval               = 60
  name                                            = local.environment
  # one_nat_gateway_per_az                          = false
  private_subnet_suffix                           = "private"
  private_subnets                                 = local.private_subnets_0
  public_subnets                                  = local.public_subnets_0
  # single_nat_gateway                              = true
  tags                                            = var.tags
}

module "vpc_1" {
  providers = { aws = aws.secondory }
  source    = "terraform-aws-modules/vpc/aws"
  version   = "~&amp;gt; 5.13.0"

  azs                                             = local.availability_zones_1
  cidr                                            = local.vpc_cidr_1
  create_database_subnet_group                    = true
  create_flow_log_cloudwatch_iam_role             = true
  create_flow_log_cloudwatch_log_group            = true
  # database_subnets                                = local.database_subnets_1
  database_subnets                                = local.database_subnets_1
  enable_dhcp_options                             = true
  enable_dns_hostnames                            = true
  enable_dns_support                              = true
  enable_flow_log                                 = true
  enable_ipv6                                     = false
  # enable_nat_gateway                              = true
  flow_log_cloudwatch_log_group_retention_in_days = 7
  flow_log_max_aggregation_interval               = 60
  name                                            = local.environment
  # one_nat_gateway_per_az                          = false
  private_subnet_suffix                           = "private"
  private_subnets                                 = local.private_subnets_1
  public_subnets                                  = local.public_subnets_1
  # single_nat_gateway                              = true
  tags                                            = var.tags
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;→ Create a “rds.tf”&lt;br&gt;
This file will contain the necessary Terraform configuration for the RDS Cluster setup.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_rds_global_cluster" "this" {
  global_cluster_identifier = local.environment
  storage_encrypted         = true
  engine                    = "aurora-postgresql"
  engine_version            = "15.5"
  database_name             = "multiregion"
}

module "aurora_primary" {
  source = "terraform-aws-modules/rds-aurora/aws"

  name                      = "${local.environment}-${local.region_0}"
  database_name             = aws_rds_global_cluster.this.database_name
  engine                    = aws_rds_global_cluster.this.engine
  engine_version            = aws_rds_global_cluster.this.engine_version
  global_cluster_identifier = aws_rds_global_cluster.this.id
  instance_class            = "db.r6g.large"
  instances                 = { for i in range(2) : i =&amp;gt; {} }

  kms_key_id = data.aws_kms_key.rds_0.arn

  publicly_accessible = true
  vpc_id               = module.vpc_0.vpc_id
  db_subnet_group_name = module.vpc_0.database_subnet_group_name
  security_group_rules = {
    vpc_ingress = {
      cidr_blocks = concat(
        module.vpc_0.public_subnets_cidr_blocks,
        module.vpc_1.public_subnets_cidr_blocks,
      )
    }
  }

  master_username = local.database_username
  master_password = local.database_password

  skip_final_snapshot = true

  tags = var.tags
}

module "aurora_secondary" {
  source = "terraform-aws-modules/rds-aurora/aws"

  providers = { aws = aws.secondory }

  is_primary_cluster = false

  name                      = "${local.environment}-${local.region_1}"
  engine                    = aws_rds_global_cluster.this.engine
  engine_version            = aws_rds_global_cluster.this.engine_version
  global_cluster_identifier = aws_rds_global_cluster.this.id
  source_region             = local.region_0
  instance_class            = "db.r6g.large"
  instances                 = { for i in range(2) : i =&amp;gt; {} }

  kms_key_id = data.aws_kms_key.rds_1.arn

  publicly_accessible = true
  vpc_id               = module.vpc_1.vpc_id
  db_subnet_group_name = module.vpc_1.database_subnet_group_name
  security_group_rules = {
    vpc_ingress = {
      cidr_blocks = concat(
        module.vpc_0.public_subnets_cidr_blocks,
        module.vpc_1.public_subnets_cidr_blocks,
      )
    }
  }

  skip_final_snapshot = true

  depends_on = [
    module.aurora_primary
  ]

  tags = var.tags
}

resource "random_password" "master" {
  length  = 20
  special = false
}

resource "aws_secretsmanager_secret" "rds_credentials" {
  name                    = "${local.environment}-aurora-credentials-multi-region-0"
  description             = "${local.environment} aurora username and password"

  depends_on = [module.aurora_primary]
}

resource "aws_secretsmanager_secret_version" "rds_credentials" {
  secret_id = aws_secretsmanager_secret.rds_credentials.id
  secret_string = jsonencode(
    {
      username = module.aurora_primary.cluster_master_username
      password = module.aurora_primary.cluster_master_password
    }
  )

  depends_on = [module.aurora_primary]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Initialize, plan and Apply the Terraform Configuration&lt;/p&gt;

&lt;p&gt;Initialize Terraform: This command initializes the project, downloads the necessary provider plugins, and sets up the backend for storing the state.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Plan Terraform: This command creates an execution plan, showing what actions Terraform will take to reach the desired infrastructure state. It compares the current state with the configuration and highlights the resources to be created, modified, or destroyed, without making any actual changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Apply the Configuration: This command applies the changes required to reach the desired state of the configuration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform apply&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You’ll be prompted to confirm the changes. Type yes and hit Enter.&lt;/p&gt;
&lt;h2&gt;
  
  
  Verify the RDS Cluster Configuration
&lt;/h2&gt;

&lt;p&gt;After applying the Terraform configuration, you can verify the multi-region database cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecpndcdnx5wf2saj6wwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecpndcdnx5wf2saj6wwq.png" alt=" " width="800" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Thank you for reading. If you have anything to add, please send a response or add a note!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article was originally published here: &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/devops-pro/terraform-deploying-multi-region-aws-rds-cluster-with-failover-setup-using-terraform-89e98da026f7" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A64%3A64%2F1%2ABCmHx6iQkKN9V5qKCBaSPg.png" alt="Prashant Bhatasana"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/devops-pro/terraform-deploying-multi-region-aws-rds-cluster-with-failover-setup-using-terraform-89e98da026f7" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Terraform — Deploying Multi-Region AWS RDS Cluster with Failover Setup using Terraform | by Prashant Bhatasana | DevOps Pro | Medium&lt;/h2&gt;
      &lt;h3&gt;Prashant Bhatasana ・ &lt;time&gt;May 5, 2025&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>aws</category>
      <category>rds</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
    <item>
      <title>AWS Database Migration Service — Incremental Migration from RDS To S3</title>
      <dc:creator>Prashant Bhatasana</dc:creator>
      <pubDate>Fri, 13 Sep 2024 09:39:43 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-database-migration-service-incremental-migration-from-rds-to-s3-3e5d</link>
      <guid>https://dev.to/aws-builders/aws-database-migration-service-incremental-migration-from-rds-to-s3-3e5d</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally Posted on &lt;a href="https://medium.com/@prashant-48386/aws-database-migration-service-incremental-migration-from-rds-to-s3-397af97c1925" rel="noopener noreferrer"&gt;medium.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Migrating data from relational databases to cloud-based data lakes is a common task in modern data architectures. Amazon Web Services (AWS) offers a robust solution called AWS Database Migration Service (DMS) that simplifies this process. This service is particularly useful for incremental migrations, allowing you to replicate ongoing changes in your source databases to a target destination like Amazon S3.&lt;/p&gt;

&lt;p&gt;In this article, we’ll set up an incremental migration from an Amazon RDS database to an S3 bucket using Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use AWS DMS?
&lt;/h2&gt;

&lt;p&gt;AWS DMS provides several advantages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimal Downtime:&lt;/strong&gt; Supports continuous data replication, which is essential for reducing downtime during migrations.&lt;br&gt;
&lt;strong&gt;Versatility:&lt;/strong&gt; Supports various source and target database engines, making it flexible for different use cases.&lt;br&gt;
&lt;strong&gt;Ease of Use:&lt;/strong&gt; Simple to set up and monitor, with a pay-as-you-go pricing model.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;The migration setup involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Source Database:&lt;/strong&gt; An Amazon RDS instance (e.g., MySQL, PostgreSQL).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target Data Store:&lt;/strong&gt; An Amazon S3 bucket where the data will be stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS DMS:&lt;/strong&gt; The service used to perform the migration, including replication instances, endpoints, and tasks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Setting Up the Environment with Terraform&lt;/strong&gt;&lt;br&gt;
Terraform is an Infrastructure as Code (IaC) tool that allows you to define and provision infrastructure using a high-level configuration language. Here’s how to set up the environment:&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Define Provider and Variables
&lt;/h2&gt;

&lt;p&gt;First, set up your provider and variables in a main.tf file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-west-2"
}

variable "rds_instance_id" {
  description = "The RDS instance identifier"
}

variable "s3_bucket_name" {
  description = "The name of the S3 bucket"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create the S3 Bucket
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "target_bucket" {
  bucket = var.s3_bucket_name
  acl    = "private"

  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Define IAM Role for DMS
&lt;/h2&gt;

&lt;p&gt;AWS DMS needs an IAM role with the necessary permissions to access the RDS instance and the S3 bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "dms_role" {
  name = "dms-access-role"

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

resource "aws_iam_policy" "dms_policy" {
  name   = "dms-access-policy"
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [{
      Action = [
        "s3:*",
        "rds:*",
        "dms:*"
      ],
      Effect   = "Allow",
      Resource = "*"
    }]
  })
}

resource "aws_iam_role_policy_attachment" "dms_attach_policy" {
  role       = aws_iam_role.dms_role.name
  policy_arn = aws_iam_policy.dms_policy.arn
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Define DMS Endpoints
&lt;/h2&gt;

&lt;p&gt;Create the source and target endpoints for DMS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_dms_endpoint" "source_endpoint" {
  endpoint_id          = "rds-source-endpoint"
  endpoint_type        = "source"
  engine_name          = "mysql"
  username             = "your-db-username"
  password             = "your-db-password"
  server_name          = "your-db-endpoint"
  port                 = 3306
  database_name        = "your-database-name"
}

resource "aws_dms_endpoint" "target_endpoint" {
  endpoint_id          = "s3-target-endpoint"
  endpoint_type        = "target"
  engine_name          = "s3"
  s3_settings {
    bucket_name        = aws_s3_bucket.target_bucket.bucket
    bucket_folder      = "dms-data"
    compression_type   = "gzip"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Create a DMS Replication Instance
&lt;/h2&gt;

&lt;p&gt;The replication instance handles the migration process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_dms_replication_instance" "replication_instance" {
  replication_instance_id   = "dms-replication-instance"
  replication_instance_class = "dms.t2.micro"
  allocated_storage         = 100
  publicly_accessible       = true
  apply_immediately         = true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Create a DMS Replication Task
&lt;/h2&gt;

&lt;p&gt;Define the task that will perform the migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_dms_replication_task" "replication_task" {
  replication_task_id          = "rds-to-s3-task"
  migration_type               = "full-load-and-cdc"
  table_mappings               = file("table-mappings.json")
  replication_task_settings    = file("task-settings.json")
  source_endpoint_arn          = aws_dms_endpoint.source_endpoint.endpoint_arn
  target_endpoint_arn          = aws_dms_endpoint.target_endpoint.endpoint_arn
  replication_instance_arn     = aws_dms_replication_instance.replication_instance.replication_instance_arn
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The table-mappings.json file defines which tables to migrate, and the task-settings.json file contains task-specific settings like logging and error handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the Incremental Migration
&lt;/h2&gt;

&lt;p&gt;To enable incremental migration (also known as Change Data Capture or CDC), the DMS task must be configured to continuously capture changes from the source database after the initial full load. This is controlled by the migration_type parameter, set to "full-load-and-cdc" in the DMS replication task.&lt;/p&gt;

&lt;p&gt;Ensure that the source database is configured to support CDC, which may involve enabling binary logging in MySQL or a similar mechanism in other database engines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring and Managing the Migration
&lt;/h2&gt;

&lt;p&gt;AWS DMS provides several metrics and logs that you can use to monitor the migration process. You can access these metrics in the AWS Management Console or set up CloudWatch alarms to notify you of any issues.&lt;/p&gt;

&lt;p&gt;Thank you for reading, if you have anything to add please send a response or add a note!&lt;/p&gt;

&lt;p&gt;Happy migrating! 🚀&lt;/p&gt;

</description>
      <category>aws</category>
      <category>rds</category>
      <category>s3</category>
      <category>migration</category>
    </item>
    <item>
      <title>Terraform — Deploy Nodejs Application with AWS AppRunner</title>
      <dc:creator>Prashant Bhatasana</dc:creator>
      <pubDate>Tue, 17 Aug 2021 07:49:58 +0000</pubDate>
      <link>https://dev.to/prashant_b/terraform-deploy-nodejs-application-with-aws-apprunner-22h2</link>
      <guid>https://dev.to/prashant_b/terraform-deploy-nodejs-application-with-aws-apprunner-22h2</guid>
      <description>&lt;p&gt;In this article, we are talking about How we can deploy Nodejs Application with AWS AppRunner service deployment using Terraform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felwbc3o2zy8j7kjdhwib.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felwbc3o2zy8j7kjdhwib.jpg" alt="Terraform — Deploy Nodejs Application with AWS AppRunner" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS App Runner is a fully managed service that makes it easy for developers to quickly deploy containerized web applications and APIs, at scale and with no prior infrastructure experience required. Start with your source code or a container image. App Runner automatically builds and deploys the web application and load balances traffic with encryption. App Runner also scales up or down automatically to meet your traffic needs. With App Runner, rather than thinking about servers or scaling, you have more time to focus on your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We require AWS IAM API keys (access key and secret key) for creating and deleting permissions for all AWS resources.&lt;/li&gt;
&lt;li&gt;Github account and new repository.&lt;/li&gt;
&lt;li&gt;Terraform should be installed on the machine. If Terraform does not exist you can download and install it from here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prepare a Demo NodeJS Application
&lt;/h2&gt;

&lt;p&gt;Create a project directory named demo-application anywhere in your system and make it your current directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir demo-application
cd demo-application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the following command within the demo-application directory to initialize your Node.js project with default settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Set Up Express with Node.js
&lt;/h2&gt;

&lt;p&gt;To use the Express framework in your application, install it as a project dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that package.json look like below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "demo-application",
  "version": "1.0.0",
  "description": "demo-application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1"
  },
  "keywords": [
    "express",
    "hello-world"
  ],
  "author": "Prashant_B",
  "license": "MIT",
  "dependencies": {
    "express": "^4.15.0"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create the entry point of the application, a file named index.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add following code in index.js file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var express = require('express')
var app = express() 
app.get('/', function (req, res) {
  res.send('Hello World!')
}) 
app.listen(3000, function () {
  console.log('Listening on port 3000...')
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This app starts a server and listens on port 3000 for connections. The app responds with “Hello World!” for requests to the root URL (/) or route. For every other path, it will respond with a 404 Not Found.&lt;/p&gt;

&lt;p&gt;Our demo application was ready now goto GitHub, create new repository and push application source code to GitHub repository.&lt;br&gt;
Let’s move to Terraform&lt;br&gt;
version&lt;/p&gt;

&lt;p&gt;To build AWS App Runner, you need to meet the following versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform v0.12 or higher&lt;/li&gt;
&lt;li&gt;Latest version of AWS provider (3.42.0)
Configuring App Runner in the Terraform AWS Provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This time I built it with the following version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform version
Terraform v1.0.0
on linux_amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amazon Resources Created Using Terraform&lt;/p&gt;

&lt;p&gt;A Terraform module is a set of Terraform configuration files in a single directory. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IAM Module&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;IAM Role and policy&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;AppRunner Module&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Auto scaling configuration&lt;/li&gt;
&lt;li&gt;AWS Apprunner service&lt;/li&gt;
&lt;li&gt;AWS Apprunner github connection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create an IAM role to grant to App Runner&lt;/p&gt;

&lt;p&gt;Following code create IAM role and policy for Build AWS App Runner service.&lt;/p&gt;

&lt;p&gt;The key &lt;code&gt;build.apprunner.amazonaws.com&lt;/code&gt; is &lt;code&gt;tasks.apprunner.amazonaws.com&lt;/code&gt; to specify and for the service to which AssumeRole is assigned.&lt;/p&gt;

&lt;p&gt;After that, AWS has prepared a policy for App Runner, so attach it to the IAM role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "role" {
   name = "test-role"
   assume_role_policy = &amp;lt;&amp;lt;EOF 
{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Action": "sts:AssumeRole",
       "Principal": {
         "Service": [
           "build.apprunner.amazonaws.com",
           "tasks.apprunner.amazonaws.com"
         ]
       },
       "Effect": "Allow",
       "Sid": ""
     }
   ]
 } EOF 
}
resource "aws_iam_role_policy_attachment" "test-attach" {
   role       = aws_iam_role.role.name
   policy_arn = "arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess"
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create an App Runner
&lt;/h2&gt;

&lt;p&gt;Finally, create an App Runner resource in Terraform.&lt;/p&gt;

&lt;p&gt;There are some App Runner related resources, but they are the main resources for actually creating App Runner aws_apprunner_service,&lt;br&gt;
source_configuration&lt;/p&gt;

&lt;p&gt;We have 2 ways to deploy App Runner with ECR repository.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy App Runner with ECR private repository&lt;/li&gt;
&lt;li&gt;Deploy App Runner with ECR public repository&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Deploy App Runner with ECR private repository
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_apprunner_auto_scaling_configuration_version" "ngnix-apprunner-autoscaling" {
  auto_scaling_configuration_name = "demo_auto_scalling"
  max_concurrency = 100
  max_size        = 5
  min_size        = 1

  tags = {
    Name = "demo_auto_scalling"
  }
}

resource "aws_apprunner_service" "ngnix-apprunner-service-ecr" {
  service_name = "demo_apprunner"

  source_configuration {
    image_repository {
      image_configuration {
        port = "80"
      }
      image_identifier      = "XXXXX.dkr.ecr.us-east-2.amazonaws.com/nginx-web:latest"
      image_repository_type = "ECR"
    }
    authentication_configuration{
      access_role_arn = aws_iam_role.role.arn
    }
    auto_deployments_enabled = true
  }

  auto_scaling_configuration_arn = aws_apprunner_auto_scaling_configuration_version.ngnix-apprunner-autoscaling.arn

  health_check_configuration {
          healthy_threshold   = 1
          interval            = 10
          path                = "/"
          protocol            = "TCP"
          timeout             = 5
          unhealthy_threshold = 5
        }

  tags = {
    Name = "demo_apprunner"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Deploy App Runner with ECR public repository
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In this approach we don't need IAM role.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_apprunner_auto_scaling_configuration_version" "ngnix-apprunner-autoscaling" {
  auto_scaling_configuration_name = "demo_auto_scalling"
  max_concurrency = 100
  max_size        = 5
  min_size        = 1

  tags = {
    Name = "demo_auto_scalling"
  }
}

resource "aws_apprunner_service" "ngnix-apprunner-service-ecr-public" {
  service_name = "demo_apprunner"

  source_configuration {
    image_repository {
      image_configuration {
        port = var.port
      }
      image_identifier      = "public.ecr.aws/nginx/nginx:latest"
      image_repository_type = "ECR_PUBLIC"
    }
    auto_deployments_enabled = false
  }

  auto_scaling_configuration_arn = aws_apprunner_auto_scaling_configuration_version.ngnix-apprunner-autoscaling.arn

  health_check_configuration {
          healthy_threshold   = 1
          interval            = 10
          path                = "/"
          protocol            = "TCP"
          timeout             = 5
          unhealthy_threshold = 5
        }

  tags = {
    Name = "demo_apprunner"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check the URL of App Runner created by applying
&lt;/h3&gt;

&lt;p&gt;I want to check the URL of the created App Runner as the execution result of the apply command, so &lt;code&gt;output&lt;/code&gt; set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "app_runner_url" {
  value = aws_apprunner_service.example.service_url
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, just run the following commands.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;terraform init&lt;br&gt;
terraform plan&lt;br&gt;
terraform apply&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;it will take 2 to 3 minutes to complete the execution.&lt;br&gt;
When the execution is completed, the URL will be displayed as shown below, so let’s access it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app_runner_url = "xxxxx.us-east-2.awsapprunner.com/"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Thank you for reading, if you have anything to add please send a response or add a note!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>node</category>
      <category>devops</category>
    </item>
    <item>
      <title>Terraform — Deploy docker image on AWS AppRunner from ECR Repository</title>
      <dc:creator>Prashant Bhatasana</dc:creator>
      <pubDate>Wed, 21 Jul 2021 14:16:59 +0000</pubDate>
      <link>https://dev.to/prashant_b/terraform-deploy-docker-image-on-aws-apprunner-from-ecr-repository-164c</link>
      <guid>https://dev.to/prashant_b/terraform-deploy-docker-image-on-aws-apprunner-from-ecr-repository-164c</guid>
      <description>&lt;p&gt;In this article, we are talking about How we can deploy docker image from ECR Repository on AWS AppRunner service using terraform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwqzqmthmdpla2mc9t47.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwqzqmthmdpla2mc9t47.jpg" alt="Terraform — Deploy docker image on AWS AppRunner from ECR Repository" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS App Runner is a fully managed service that makes it easy for developers to quickly deploy containerized web applications and APIs, at scale and with no prior infrastructure experience required.&lt;/p&gt;

&lt;p&gt;Start with your source code or a container image. App Runner automatically builds and deploys the web application and load balances traffic with encryption.&lt;/p&gt;

&lt;p&gt;App Runner also scales up or down automatically to meet your traffic needs. With App Runner, rather than thinking about servers or scaling, you have more time to focus on your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  App Runner Features
&lt;/h2&gt;

&lt;p&gt;AWS has put a lot of effort into making things easy for developers, especially for small-scale projects that don’t need beefy infrastructure. It has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple auto scaling&lt;/strong&gt;: instances are started and stopped as demand changes, between configurable min and max limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load balancing&lt;/strong&gt;: the service includes a transparent, non-configurable load balancer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL enabled&lt;/strong&gt;: you get HTTPS endpoints for all your applications with AWS-managed certificates. You don’t need to issue or renew certificates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build service&lt;/strong&gt;: you can push your own images or let AWS build them for you from code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent URLs&lt;/strong&gt;: the service assigns randomly-generated URLs for each environment. You can optionally map them to domains of your own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;App Runner can run in two modes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In build mode, AWS pulls code from GitHub and builds the application on every change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In container mode, it deploys Docker-compatible images from public or private AWS ECR registries.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this article we will using ECR public as well as private repository with App Runner deployment which mean we are using &lt;code&gt;container mode&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We require AWS IAM API keys (access key and secret key) for creating and deleting permissions for all AWS resources.&lt;/li&gt;
&lt;li&gt;ECR Repository and docker image pushed on it.&lt;/li&gt;
&lt;li&gt;Terraform should be installed on the machine. If Terraform does not exist you can download and install it from here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  version
&lt;/h2&gt;

&lt;p&gt;To build AWS App Runner, you need to meet the following versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform v0.12 or higher
*Latest version of AWS provider (3.42.0)
Configuring App Runner in the Terraform AWS Provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This time I built it with the following version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform version
Terraform v1.0.0
on linux_amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Amazon Resources Created Using Terraform
&lt;/h2&gt;

&lt;p&gt;A Terraform module is a set of Terraform configuration files in a single directory. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IAM Module&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;IAM Role and policy&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;AppRunner Module&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;auto scaling configuration&lt;/li&gt;
&lt;li&gt;aws apprunner service&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create an IAM role to grant to App Runner
&lt;/h2&gt;

&lt;p&gt;Set up an IAM role to build AWS App Runner.&lt;br&gt;
The key &lt;code&gt;build.apprunner.amazonaws.com&lt;/code&gt; is &lt;code&gt;tasks.apprunner.amazonaws.com&lt;/code&gt; to specify and for the service to which AssumeRole is assigned .&lt;br&gt;
After that, AWS has prepared a policy for App Runner, so attach it to the IAM role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "role" {
   name = "test-role"
   assume_role_policy = &amp;lt;&amp;lt;EOF 
{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Action": "sts:AssumeRole",
       "Principal": {
         "Service": [
           "build.apprunner.amazonaws.com",
           "tasks.apprunner.amazonaws.com"
         ]
       },
       "Effect": "Allow",
       "Sid": ""
     }
   ]
 } EOF 
}
resource "aws_iam_role_policy_attachment" "test-attach" {
   role       = aws_iam_role.role.name
   policy_arn = "arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess"
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create an App Runner
&lt;/h2&gt;

&lt;p&gt;Finally, create an App Runner resource in Terraform.&lt;br&gt;
There are some App Runner related resources, but they are the main resources for actually creating App Runner aws_apprunner_service,&lt;br&gt;
source_configuration&lt;/p&gt;

&lt;p&gt;We have 2 ways to deploy App Runner with ECR repository.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy App Runner with ECR private repository&lt;/li&gt;
&lt;li&gt;Deploy App Runner with ECR public repository&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Deploy App Runner with ECR private repository
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_apprunner_auto_scaling_configuration_version" "ngnix-apprunner-autoscaling" {
  auto_scaling_configuration_name = "demo_auto_scalling"
  max_concurrency = 100
  max_size        = 5
  min_size        = 1

  tags = {
    Name = "demo_auto_scalling"
  }
}

resource "aws_apprunner_service" "ngnix-apprunner-service-ecr" {
  service_name = "demo_apprunner"

  source_configuration {
    image_repository {
      image_configuration {
        port = "80"
      }
      image_identifier      = "XXXXX.dkr.ecr.us-east-2.amazonaws.com/nginx-web:latest"
      image_repository_type = "ECR"
    }
    authentication_configuration{
      access_role_arn = aws_iam_role.role.arn
    }
    auto_deployments_enabled = true
  }

  auto_scaling_configuration_arn = aws_apprunner_auto_scaling_configuration_version.ngnix-apprunner-autoscaling.arn

  health_check_configuration {
          healthy_threshold   = 1
          interval            = 10
          path                = "/"
          protocol            = "TCP"
          timeout             = 5
          unhealthy_threshold = 5
        }

  tags = {
    Name = "demo_apprunner"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Deploy App Runner with ECR public repository
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In this approach we don't need IAM role.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_apprunner_auto_scaling_configuration_version" "ngnix-apprunner-autoscaling" {
  auto_scaling_configuration_name = "demo_auto_scalling"
  max_concurrency = 100
  max_size        = 5
  min_size        = 1

  tags = {
    Name = "demo_auto_scalling"
  }
}

resource "aws_apprunner_service" "ngnix-apprunner-service-ecr-public" {
  service_name = "demo_apprunner"

  source_configuration {
    image_repository {
      image_configuration {
        port = var.port
      }
      image_identifier      = "public.ecr.aws/nginx/nginx:latest"
      image_repository_type = "ECR_PUBLIC"
    }
    auto_deployments_enabled = false
  }

  auto_scaling_configuration_arn = aws_apprunner_auto_scaling_configuration_version.ngnix-apprunner-autoscaling.arn

  health_check_configuration {
          healthy_threshold   = 1
          interval            = 10
          path                = "/"
          protocol            = "TCP"
          timeout             = 5
          unhealthy_threshold = 5
        }

  tags = {
    Name = "demo_apprunner"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Check the URL of App Runner created by applying
&lt;/h4&gt;

&lt;p&gt;I want to check the URL of the created App Runner as the execution result of the apply command, so &lt;code&gt;output&lt;/code&gt; set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "app_runner_url" {
  value = aws_apprunner_service.example.service_url
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, just run the following commands.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;terraform init&lt;br&gt;
terraform plan&lt;br&gt;
terraform apply&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;it will take 2 to 3 minutes to complete the execution.&lt;br&gt;
When the execution is completed, the URL will be displayed as shown below, so let’s access it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app_runner_url = "xxxxx.us-east-2.awsapprunner.com/"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading, if you have anything to add please send a response or add a note!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>docker</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
