A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developer.hashicorp.com/terraform/tutorials/aws/aws-rds below:

Manage AWS RDS instances | Terraform

AWS's Relational Database Service (RDS) provides hosted relational databases, which are easier to operate and maintain than self-managed implementations. Terraform can provision, scale, and modify RDS, enabling you to manage the RDS instance and cluster life cycle programmatically, safely, and declaratively.

In this tutorial, you will use Terraform to provision an RDS instance, subnet group, and parameter group, modify the RDS instance configuration, and provision a replica instance.

This tutorial assumes that you are familiar with the standard Terraform workflow. If you are new to Terraform, complete the Get Started tutorials first.

For this tutorial, you will need:

Note

Some of the infrastructure in this tutorial may not qualify for the AWS free tier. Destroy the infrastructure at the end of the guide to avoid unnecessary charges. We are not responsible for any charges that you incur.

Clone the sample repository for this tutorial, which contains Terraform configuration for an RDS instance, parameter group, security group, and subnet group.

$ git clone https://github.com/hashicorp-education/learn-terraform-rds

Change into the repository directory.

Open the main.tf file in your editor to review the sample configuration.

Networking components

The first resources defined are the VPC and subnets, using the terraform-aws-vpc module.

Warning

For simplicity, this RDS tutorial instance is publicly accessible. Avoid configuring database instances in public subnets in production, since it increases the risk of security attacks.

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.77.0"

  name                 = "education"
  cidr                 = "10.0.0.0/16"
  azs                  = data.aws_availability_zones.available.names
  public_subnets       = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
  enable_dns_hostnames = true
  enable_dns_support   = true
}
Subnet group

The next resource is an aws_db_subnet_group, which designates a collection of subnets that your RDS instance can be provisioned in. This subnet group uses the subnets created by the VPC module.

resource "aws_db_subnet_group" "education" {
  name       = "education"
  subnet_ids = module.vpc.public_subnets

  tags = {
    Name = "Education"
  }
}

This subnet group resource is an optional parameter in your aws_db_instance block below. Without it, Terraform creates your RDS instances in the default VPC.

Database instance

Review the aws_db_instance configuration.

resource "aws_db_instance" "education" {
  identifier             = "education"
  instance_class         = "db.t3.micro"
  allocated_storage      = 5
  engine                 = "postgres"
  engine_version         = "14.1"
  username               = "edu"
  password               = var.db_password
  db_subnet_group_name   = aws_db_subnet_group.education.name
  vpc_security_group_ids = [aws_security_group.rds.id]
  parameter_group_name   = aws_db_parameter_group.education.name
  publicly_accessible    = true
  skip_final_snapshot    = true
}

Note the following arguments.

You can review all of the supported arguments on the aws_db_instance resource documentation page.

Parameter group

Now review the definition for the aws_db_parameter_group.

resource "aws_db_parameter_group" "education" {
  name   = "education"
  family = "postgres14"

  parameter {
    name  = "log_connections"
    value = "1"
  }
}

This configuration enables connection logging for all instances using this parameter group. Note that the family parameter must correspond with the engine version of the RDS instance.

The parameter group resource contains all of the database-level settings for your RDS instance, which will be specific to the database engine and version you use.

Custom parameter groups are optional, and AWS will create the instance using a default parameter group if you do not supply one. However, you cannot modify the settings of a default parameter group, and changing the associated parameter group for an AWS instance always requires a reboot, so it is best to use a custom one to support modifications over the RDS life cycle.

Input variables

Note that the aws_db_instance root user password relies on an input variable. Open the variables.tf file to review its configuration.

variable "db_password" {
  description = "RDS root user password"
  type        = string
  sensitive   = true
}

Take note of the sensitive meta-argument for the db_password variable. This argument tells Terraform to hide the password from the output during Terraform operations. However, Terraform will store the password in plaintext in the state file.

Output variables

Now review the contents of the outputs.tf file.

output "rds_hostname" {
  description = "RDS instance hostname"
  value       = aws_db_instance.education.address
  sensitive   = true
}

output "rds_port" {
  description = "RDS instance port"
  value       = aws_db_instance.education.port
  sensitive   = true
}

output "rds_username" {
  description = "RDS instance root username"
  value       = aws_db_instance.education.username
  sensitive   = true
}

These outputs return details for the RDS instance that you will use to construct the database connection string later in this tutorial.

Now that you have reviewed the configuration, provision the RDS instance and associated resources.

First, set the db_password variable as an environment variable.

$ export TF_VAR_db_password="hashicorp"

Initialize the Terraform configuration.

$ terraform init
Initializing modules...
Downloading terraform-aws-modules/vpc/aws 2.77.0 for vpc...
- vpc in .terraform/modules/vpc

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v3.32.0...
- Installed hashicorp/aws v3.32.0 (signed by HashiCorp)

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Next, apply the configuration. Respond yes to the prompt to confirm.

$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:
##...
Plan: 14 to add, 0 to change, 0 to destroy.
##...
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
##..
aws_db_instance.education: Creation complete after 4m28s [id=education]

Apply complete! Resources: 14 added, 0 changed, 0 destroyed.

Outputs:

rds_hostname = <sensitive>
rds_port = <sensitive>
rds_username = <sensitive>

Terraform will now provision your resources. It may take 5-7 minutes for AWS to provision the RDS instance.

Verify your configuration by using the endpoint, the password, and username outputs to connect to the database using psql. Enter the password hashicorp when prompted.

$ psql -h $(terraform output -raw rds_hostname) -p $(terraform output -raw rds_port) -U $(terraform output -raw rds_username) postgres
Password for user edu:
psql (14.2, server 14.1)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=>

You are now connected to the database instance, verifying that the resource is provisioned as expected.

Create a new database called "hashicorp" within this instance.

$ CREATE DATABASE hashicorp;
CREATE DATABASE

Now verify that the hashicorp database is included in the list of databases in the instance by using the /list command. Along with the database you created, the list includes the default databases created in Postgres RDS instances.

$ \list
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 hashicorp | edu      | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | edu      | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 rdsadmin  | rdsadmin | UTF8     | en_US.UTF-8 | en_US.UTF-8 | rdsadmin=CTc/rdsadmin
 template0 | rdsadmin | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/rdsadmin          +
           |          |          |             |             | rdsadmin=CTc/rdsadmin
 template1 | edu      | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/edu               +
           |          |          |             |             | edu=CTc/edu
(5 rows)

You will use this database to verify replication later in this tutorial.

Leave the terminal by typing exit.

In addition to initially provisioning resources, you will likely need to modify the RDS configuration over the instance life cycle.

In main.tf, change the allocated storage from 5 to 10GB.

resource "aws_db_instance" "education" {
   name                   = "education"
   instance_class         = "db.t3.micro"
-  allocated_storage      = 5
+  allocated_storage      = 10
##...
}

Apply your changes. Respond to yes to the prompt to confirm.

$ terraform apply
Terraform will perform the following actions:

  # aws_db_instance.education will be updated in-place
  ~ resource "aws_db_instance" "education" {
      ~ allocated_storage                     = 5 -> 10
        id                                    = "education"
        name                                  = ""
        tags                                  = {}
        # (49 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
##...
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:

rds_hostname = <sensitive>
rds_port = <sensitive>
rds_username = <sensitive>

Even after the apply completes successfully, the change will still be pending. Verify by running terraform plan.

$ terraform plan
##...
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_db_instance.education will be updated in-place
  ~ resource "aws_db_instance" "education" {
      ~ allocated_storage                     = 5 -> 10
        id                                    = "terraform-20210315135307744800000001"
        name                                  = "education"
        tags                                  = {}
        # (42 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Though some RDS configuration changes are safe to apply immediately, others (such as engine_version) require an instance reboot or may cause performance degradation (such as allocated_storage). By default, AWS will defer applying any changes that can cause degradation or outage until your next scheduled maintenance window. For a detailed breakdown of which attributes require a reboot, consult the AWS RDS documentation.

To make the changes take effect immediately, add the apply_immediately argument to aws_db_instance and set it to true.

resource "aws_db_instance" "education" {
   name                   = "education"
   instance_class         = "db.t3.micro"
   allocated_storage      = 10
+  apply_immediately      = true
##...
}

Apply your changes again. The proposed modifications will include the still-pending storage resize and the apply_immediately argument. Respond yes to the prompt to apply your changes.

$ terraform apply
##...
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_db_instance.education will be updated in-place
  ~ resource "aws_db_instance" "education" {
      ~ allocated_storage                     = 5 -> 10
      + apply_immediately                     = true
        id                                    = "terraform-20210315135307744800000001"
        name                                  = "education"
        tags                                  = {}
        # (42 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
##...

This apply step will take longer than the previous one since Terraform will wait for the instance reboot to complete.

Once this update is complete, run terraform plan.

$ terraform plan
##...
No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

There are no pending changes remaining, confirming that Terraform resized the RDS instance. You can also verify this by navigating to your instance in the RDS console for your region and reviewing the database instances.

Warning

Use the apply_immediately argument with caution since it can allow unexpected instance reboots and downtime.

A read replica is one way to reduce load on the primary database. AWS will asynchronously copy all data from the primary database to the replica, to which you can then target all read queries.

Add the following configuration block to the main.tf file to declare a replica RDS instance.

resource "aws_db_instance" "education_replica" {
   name                   = "education-replica"
   identifier             = "education-replica"
   replicate_source_db    = aws_db_instance.education.identifier
   instance_class         = "db.t3.micro"
   apply_immediately      = true
   publicly_accessible    = true
   skip_final_snapshot    = true
   vpc_security_group_ids = [aws_security_group.rds.id]
   parameter_group_name   = aws_db_parameter_group.education.name
}

This provisions a read replica instance based on the aws_db_instance.education RDS instance. Since there is a replicate_source_db set, you don't need to set the required arguments for engine, allocated_storage, username, and password — Terraform will determine them from the corresponding values on the source RDS instance.

You will also need to enable backup retention on the primary instance to use it as a source database. Add the backup_retention_period argument to the primary instance configration.

resource "aws_db_instance" "education" {
    name                      = "education"
    instance_class            = "db.t3.micro"
    allocated_storage         = 10
+   backup_retention_period   = 1
##...
}

For the primary instance, you constructed the database connection string by passing the individual outputs to the psql parameters. You can also construct and output the entire connection string using Terraform's string interpolation functionality.

Add the output variable for the connection string for the new replica instance to the outputs.tf file.

output "rds_replica_connection_parameters" {
  description = "RDS replica instance connection parameters"
  value       = "-h ${aws_db_instance.education_replica.address} -p ${aws_db_instance.education_replica.port} -U ${aws_db_instance.education_replica.username} postgres"
}

Apply your changes to provision this additional instance. Respond yes to the prompt to confirm.

$ terraform apply
aws_db_parameter_group.education: Refreshing state... [id=education]
module.vpc.aws_vpc.this[0]: Refreshing state... [id=vpc-03d07a04a25ae3f80]

##...

Plan: 1 to add, 1 to change, 0 to destroy.

Changes to Outputs:
  + rds_replica_connection_parameters = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

rds_hostname = <sensitive>
rds_port = <sensitive>
rds_replica_connection_parameters = "-h education-replica.cyfmek5yt2i5.us-east-2.rds.amazonaws.com -p 5432 -U edu postgres"
rds_username = <sensitive>

As with the original instance, it may take 5-7 minutes to provision the replica, and a few additional minutes to make updates to the primary instance.

Once it is complete, use the new endpoint to connect to the replica database instance to verify your configuration.

$ psql $(terraform output -raw rds_replica_connection_parameters)

Enter the password hashicorp when prompted.

Now, confirm that the replica instance has the database you created in the primary RDS instance. Use the /list command to see all of the databases.

Notice that the hashicorp database you created in the source RDS instance is in the database list for the replica instance, confirming that this instance is properly replicated from the primary.

$ \list
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 hashicorp | edu      | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | edu      | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 rdsadmin  | rdsadmin | UTF8     | en_US.UTF-8 | en_US.UTF-8 | rdsadmin=CTc/rdsadmin
 template0 | rdsadmin | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/rdsadmin          +
           |          |          |             |             | rdsadmin=CTc/rdsadmin
 template1 | edu      | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/edu               +
           |          |          |             |             | edu=CTc/edu
(5 rows)

Leave the terminal by typing exit.

In this tutorial you provisioned and modified an RDS instance and read replica using Terraform. Clean up the infrastructure you have created. Respond yes to the prompt to confirm destroying the resources.

$ terraform destroy

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:
##...

Plan: 0 to add, 0 to change, 15 to destroy.

Changes to Outputs:
  - rds_hostname                      = (sensitive value)
  - rds_port                          = (sensitive value)
  - rds_replica_connection_parameters = "-h education-replica.cyfmek5yt2i5.us-east-2.rds.amazonaws.com -p 5432 -U edu postgres" -> null
  - rds_username                      = (sensitive value)

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

##...

Destroy complete! Resources: 15 destroyed.

Terraform allows you to easily provision and manage AWS RDS instances using infrastructure as code. Since data storage resources are critical components of infrastructure, a declarative way to manage the resources over their life cycle will add an extra level of safety and consistency.

To learn more about managing RDS and other databases with HashiCorp tools:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4