Creating AWS RDS Database with Terraform (4/5)

RDS MariaDB Database and Resource Tags

This is the continuation of a Terraform demo to create a VPC in AWS with an EC2 instance connected to MariaDB database running in RDS (Amazon Relational Database Service) using a single Terraform plan.

Operating System and software configuration is done using Ansible after the infrastructure has been created.

Click to see the New updated tutorial on AWS with Terraform and OpenTufu

AWS and Terraform Tutorial: The Essential Guide for Beginners

Terraform Basics, AWS Basics, Terraform AWS Provider, AWS VPC, AWS Subnets, AWS Internet Gateway, AWS NAT Gateway, AWS Routing Tables, AWS Security Groups, AWS Key Pairs, AWS AMIs, AWS EC2 Instances, AWS RDS, AWS Route 53 (DNS), AWS Auto Scaling, AWS Load Balancers, Terraform AWS & Ansible, Terraform Modules, Terraform Backends, Terraform Tools, Terraform CI/CD.

AWS with Terraform: The Essential Guide: Sections

Our new tutorial series delves into cloud infrastructure deployment using Terraform or OpenTofu on AWS. In this series, the fundamentals are shown, guiding you through minimizing resource usage and simplifying the deployment complexities associated with cloud infrastructure. This tutorial series is a work in progress and will have these sections:

Prerequisites and source code

Configuring an RDS MariaDB Database with Terraform

AWS RDS databases are ready-to-use databases backed by AWS experience and with easy-to-use administration tools.

Best Practice: Use Cloud Services When Possible
Focus all your resources and energy on configuring and developing what is really disruptive and unique. Databases, Email servers, DNS servers, and Queues are now a commodity.

Most of the time if you need full control of those services and If you don't have millions of customers there is a big probability that you have a wrong design.

The AWS RDS database is fully configured in the terraform.tfvars file.

Be aware of the password in clear text in terraform.tfvars. It will also show in terraform.tftstate and terraform.tfstate.backup.  Currently, the recommended action for passwords in Terraform files is to change them after resource creation using a different tool (AWS CLI, AWS Console, Ansible, DB Client ...). A changed password in Terraform doesn't trigger a resource property change.

#------------------------
# RDS INSTANCES
#------------------------

  #------------------------
  # MariaDB PRO 01
  #------------------------
  aws_rds_mariadb_pro_pub_01 = {
    identifier              = "ditwl-rds-mariadb-pro-pub-01"
    allocated_storage       = 20 #GB
    storage_type            = "gp2"
    final_snapshot_id       = "ditwl-rds-mariadb-pro-pub-01-final"
    skip_final_snapshot     = false
    engine                  = "mariadb"
    engine_version          = "10.2.11"
    instance_class          = "db.t2.micro"
    password                = "**************"
    username                = "ditwlRDSPROdb01" #Start with a letter. Only numbers, letters, and _ accepted, 1 to 16 characters long
    availability_zone       = "us-east-1a"
    backup_retention_period = 5
    #db_subnet_group_name   = See var aws_rds_sn_pro_01["name"]
    multi_az                = false
    vpc_security_group_ids  = ""
    parameter_group_name    = ""
    allow_major_version_up  = false
    publicly_accessible     = true
    tag_private_name        = "ditwl-rds-mariadb-pro-pub-01"
    tag_public_name         = "ditwl-rds-mariadb-pro-pub-01"
    tag_app                 = "mariadb"
    tag_app_id              = "mariadb-01"
    tag_os                  = "rds"
    tags_environment        = "pro"
    tag_cost_center         = "ditwl-permanent"
  }

  #------------------------
  # RDS Security Group
  #------------------------
  aws_sg_rds_mariadb_pro_pub_01 = {
    sec_name        = "ditwl-aws-sg-rds-mariadb-pro-pub-01"
    sec_description = "ditwl - MariaDb server access rules - Pub, Env: PRO"
    allow_all_outbound = false
  }
    #------------------------
    # Allow access from my Instances to DB port
    #------------------------
    aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port = {
      type              = "ingress"
      from_port         = "3306"
      to_port           = "3306"
      protocol          = "tcp"
      #source_security_group_id module.aws_sec_group_ec2_default.id
      description       = "Access from Instances to DB port"
    }

aws_rds_pro_mariadb_01.tf is used to create the security group, assign the security rule, and launch the database.

#----------------------
# RDS MariaDB
#----------------------

# SECURITY
  # Group
  module "aws_sg_rds_mariadb_pro_pub_01" {
    source      = "./modules/aws/security/group"
    vpc_id      = module.aws_network_vpc.id
    name        = var.aws_sg_rds_mariadb_pro_pub_01["sec_name"]
    description = var.aws_sg_rds_mariadb_pro_pub_01["sec_description"]
  }

  # Rules
  # Access from instances in group aws_sec_group_ec2_default to DB Port
  module "aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port" {
    source            = "./modules/aws/security/rule/source_group"
    security_group_id = module.aws_sg_rds_mariadb_pro_pub_01.id
    type              = var.aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port["type"]
    from_port         = var.aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port["from_port"]
    to_port           = var.aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port["to_port"]
    protocol          = var.aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port["protocol"]
    source_security_group_id = module.aws_sg_ec2_default.id
    description       = var.aws_sr_rds_mariadb_pro_pub_01_instances_to_db_port["description"]
  }

module "aws_rds_mariadb_pro_pub_01" {
  source = "./modules/aws/rds/instance"

  identifier              = var.aws_rds_mariadb_pro_pub_01["identifier"]
  allocated_storage       = var.aws_rds_mariadb_pro_pub_01["allocated_storage"]
  storage_type            = var.aws_rds_mariadb_pro_pub_01["storage_type"]
  final_snapshot_id       = var.aws_rds_mariadb_pro_pub_01["final_snapshot_id"]
  skip_final_snapshot     = var.aws_rds_mariadb_pro_pub_01["skip_final_snapshot"]
  engine                  = var.aws_rds_mariadb_pro_pub_01["engine"]
  engine_version          = var.aws_rds_mariadb_pro_pub_01["engine_version"]
  instance_class          = var.aws_rds_mariadb_pro_pub_01["instance_class"]
  password                = var.aws_rds_mariadb_pro_pub_01["password"]
  username                = var.aws_rds_mariadb_pro_pub_01["username"]
  availability_zone       = var.aws_rds_mariadb_pro_pub_01["availability_zone"]
  backup_retention_period = var.aws_rds_mariadb_pro_pub_01["backup_retention_period"]

  # Workaround for dependency. We need Terraform to wait for aws_rds_sn_pro_01 creation before the RDS DB can use it.
  db_subnet_group_name    = module.aws_rds_sn_pub_pro_01.id #aws_rds_sn_pro_01["name"]

  multi_az                = var.aws_rds_mariadb_pro_pub_01["multi_az"]
  vpc_security_group_ids  = [module.aws_sg_rds_mariadb_default.id,module.aws_sg_rds_mariadb_pro_pub_01.id]
  publicly_accessible     = var.aws_rds_mariadb_pro_pub_01["publicly_accessible"]

  #parameter_group_name    = aws_db_parameter_group.rds_pos_96_db_parameter_group_01.id
  allow_major_version_up  = var.aws_rds_mariadb_pro_pub_01["allow_major_version_up"]
  tag_private_name        = var.aws_rds_mariadb_pro_pub_01["tag_private_name"]
  tag_public_name         = var.aws_rds_mariadb_pro_pub_01["tag_public_name"]
  tag_app                 = var.aws_rds_mariadb_pro_pub_01["tag_app"]
  tag_app_id              = var.aws_rds_mariadb_pro_pub_01["tag_app_id"]
  tag_os                  = var.aws_rds_mariadb_pro_pub_01["tag_os"]
  tags_environment        = var.aws_rds_mariadb_pro_pub_01["tags_environment"]
  tag_cost_center         = var.aws_rds_mariadb_pro_pub_01["tag_cost_center"]
}

A workaround is used to create a dependency between the RDS subnet group and the RDS database. See RDS subnet group creation in part II (VPC/RDS Sub Nets).

db_subnet_group_name = module.aws_rds_sn_pub_pro_01.id

To launch the RDS database the subnet needs to exist, we provide the name of the RDS subnet using the output ID of the RDS subnet as source, this way Terraform is forced to create the RDS subnet first to evaluate the output ID.

Tag the RDS instance with all the needed identifiers.

Best Practice: Tag all your AWS Resources
Tags can be used to identify resources, split costs between cost centers, and for further configuration, provisioning, and monitoring with dynamic inventories using Ansible or other tools. See AWS Tagging best practices.

Continue the Terraform and Ansible demo, see:

Next Steps

Leave a Reply

Your email address will not be published. Required fields are marked *


Related Cloud Tutorials

Securing your Infrastructure: Encrypting Terraform State Files with OpenTofu
Using the Terraform aws_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS.
Using the Terraform aws_db_instance resource block to configure, launch, and secure RDS instances.
How to use the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.
How to configure and use the Terraform aws_ami data source block to find and use AWS AMIs as templates (root volume snapshot with operating system and applications) for EC2 instances.
Javier Ruiz Cloud and SaaS Expert

Javier Ruiz

IT Wonder Lab tutorials are based on the diverse experience of Javier Ruiz, who founded and bootstrapped a SaaS company in the energy sector. His company, later acquired by a NASDAQ traded company, managed over €2 billion per year of electricity for prominent energy producers across Europe and America. Javier has over 25 years of experience in building and managing IT companies, developing cloud infrastructure, leading cross-functional teams, and transitioning his own company from on-premises, consulting, and custom software development to a successful SaaS model that scaled globally.

Are you looking for cloud automation best practices tailored to your company?

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram