Unleashing Aurora MySQL: Effortless Clustering with Terraform on AWS

francotel - Apr 19 - - Dev Community

In the ever-evolving world of cloud computing, AWS has introduced Aurora, a next-generation relational database engine that promises high performance, scalability, and availability – all while being cost-effective and compatible with MySQL and PostgreSQL. In this article, we'll dive into the power of Terraform to seamlessly create and manage an Aurora MySQL cluster on AWS.

Aurora: The Cloud-Native Database Powerhouse

Before we delve into the technical details, allow me to introduce you to Aurora, AWS's fully managed database service designed to deliver up to five times better performance than traditional databases.

Aurora combines the speed and reliability of high-end commercial databases with the cost-effectiveness and simplicity of open-source solutions. Some of its key features include:

  • Distributed & Fault-Tolerant: Aurora automatically replicates data across multiple Availability Zones, ensuring high availability and durability. 🌐⚑

  • Automatic Scaling: You can easily scale your database's compute resources up or down with a few clicks, allowing your applications to handle sudden traffic spikes seamlessly. πŸ“ˆπŸ”„

  • Backtrack: Aurora's backtrack feature lets you rewind your database to any point in time without using backups, providing an easy way to undo accidental changes or data corruption. βͺπŸ”™

  • Parallel Query Processing: Aurora can take advantage of multiple CPU cores to execute queries faster, improving performance for read-heavy workloads. πŸš€πŸ’»

With a taste of Aurora's capabilities, let's explore how Terraform can empower us to create and manage an Aurora MySQL cluster with ease.

Types of Aurora Endpoints

An endpoint is represented as an Aurora-specific URL that contains a host address and a port. The following types of endpoints are available from an Aurora DB cluster.

Cluster Endpoint (Writer Endpoint) πŸ“

A cluster endpoint for an Aurora DB cluster connects to the current primary DB instance for that DB cluster. This endpoint is the only one that can perform write operations such as DDL statements. You use the cluster endpoint for all write operations on the DB cluster, including inserts, updates, deletes, and DDL changes. The cluster endpoint provides failover support for read/write connections to the DB cluster.

Example: mydbcluster.cluster-c7tj4example.us-east-1.rds.amazonaws.com:3306

Reader Endpoint πŸ“–

A reader endpoint for an Aurora DB cluster provides load-balancing support for read-only connections to the DB cluster. Use the reader endpoint for read operations, such as queries. Each Aurora DB cluster has one reader endpoint.

Example: mydbcluster.cluster-ro-c7tj4example.us-east-1.rds.amazonaws.com:3306

Custom Endpoint πŸ› οΈ

A custom endpoint for an Aurora cluster represents a set of DB instances that you choose. When you connect to the endpoint, Aurora performs load balancing and chooses one of the instances in the group to handle the connection. You define which instances this endpoint refers to, and you decide what purpose the endpoint serves. An Aurora DB cluster has no custom endpoints until you create one.

Example: myendpoint.cluster-custom-c7tj4example.us-east-1.rds.amazonaws.com:3306

Instance Endpoint 🏁

An instance endpoint connects to a specific DB instance within an Aurora cluster. Each DB instance in a DB cluster has its own unique instance endpoint. The instance endpoint provides direct control over connections to the DB cluster.

Example: mydbinstance.c7tj4example.us-east-1.rds.amazonaws.com:3306

Amazon Aurora Cluster Autoscaling Overview πŸ”„πŸš€

Amazon Aurora provides the capability of autoscaling to automatically scale the storage capacity of an Aurora database cluster in response to workload changes. This autoscaling applies to cluster storage, not to compute capacity.

How Aurora Cluster Autoscaling Works:

  1. Automatic Monitoring: Aurora continuously monitors storage usage across all cluster members and evaluates if it's necessary to increase or decrease the storage size.

  2. Autoscaling Policies: You can define autoscaling policies that establish the conditions under which Aurora should increase or decrease the cluster storage size. These policies include storage usage thresholds and maximum and minimum size limits.

  3. Automatic Adjustment: When an autoscaling policy is triggered due to storage usage exceeding or falling below the specified thresholds, Aurora automatically adjusts the cluster storage size to meet the current demand.

  4. Seamless Process: The autoscaling process is performed automatically and transparently to applications using the Aurora cluster. There's no need for manual intervention, and there are no interruptions in data access during the autoscaling process.

Benefits of Aurora Cluster Autoscaling:

  • Automatic Scalability: Aurora cluster autoscaling provides an automated way to vertically scale storage capacity based on application demand.

  • Cost Optimization: By dynamically adjusting storage size according to actual needs, autoscaling helps optimize costs by avoiding overprovisioning of storage resources.

  • Handling Variable Workloads: Aurora autoscaling allows clusters to automatically adapt to workload variations, ensuring optimal performance at all times.

  • Simplified Management: By automating the process of adjusting storage size, autoscaling reduces administrative burden and simplifies management of the Aurora database cluster.

aurora diagram

In summary, Aurora cluster autoscaling offers a flexible and automated solution for managing storage size based on changing application needs, ensuring optimal performance and simplified management of the database cluster.

Prerequisites

Before we begin, make sure you have the following components installed:

Configuring Terraform

  1. Initialize a new Terraform working directory:


terraform init


Enter fullscreen mode Exit fullscreen mode

vpc.tf



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

  name = "vpc-ibm-${var.env}"

  cidr = "10.0.0.0/16"
  azs  = slice(data.aws_availability_zones.available.names, 0, 2)

  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.6.0/24", "10.0.7.0/24"]

  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true

  map_public_ip_on_launch = true

  public_subnet_tags = {
    ibm = "public-subnet"
  }

  private_subnet_tags = {
    ibm = "private-subnet"
  }
}


Enter fullscreen mode Exit fullscreen mode

aurora.tf



resource "aws_security_group" "rds_security_group" {
  name_prefix = "ibm-rds-sg-cluster-${var.env}"
  vpc_id      = module.vpc.vpc_id

  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "IBM RDS Security Group"
  }
}

resource "aws_db_subnet_group" "rds_subnet_group" {
  name       = "ibm-rds-subnet-group-public-${var.env}"
  subnet_ids = module.vpc.public_subnets

  tags = {
    Name = "IBM RDS Subnet Group"
  }
}

data "aws_kms_alias" "rds" {
  name = "alias/aws/rds"
}

resource "aws_rds_cluster" "ibm_cluster" {
  cluster_identifier      = "ibm-cluster"
  engine                  = "aurora-mysql"
  engine_version          = "5.7.mysql_aurora.2.11.2"
  availability_zones      = module.vpc.azs
  database_name           = "ibm_database"
  master_username         = "ibm_admin_user"
  master_password         = "IbmPassword123"
  backup_retention_period = 7
  preferred_backup_window = "07:00-07:30"
  vpc_security_group_ids  = [aws_security_group.rds_security_group.id]
  db_subnet_group_name    = aws_db_subnet_group.rds_subnet_group.id
  kms_key_id              = data.aws_kms_alias.rds.target_key_arn
  storage_encrypted       = true
  deletion_protection     = false
  skip_final_snapshot     = true

  tags = {
    ENV     = "development"
    Project = "IBM Project"
    Service = "IBM Service"
  }

  lifecycle {
    ignore_changes = [
      availability_zones,
    ]
  }
}

resource "aws_rds_cluster_instance" "ibm_cluster_instance" {
  count               = 1
  cluster_identifier  = aws_rds_cluster.ibm_cluster.id
  apply_immediately   = true
  identifier          = "ibm-cluster-instance-${count.index}"
  instance_class      = "db.t3.medium"
  engine              = "aurora-mysql"
  publicly_accessible = true

  tags = {
    ENV     = "development"
    Project = "IBM Project"
    Service = "IBM Service"
  }
}


Enter fullscreen mode Exit fullscreen mode

rds aurora aws

Recommendation for Code Improvement πŸ› οΈπŸš€

While the provided code serves as a demonstration, there are several areas where it can be further improved for security and monitoring:

  1. Security Enhancements πŸ”’:

    • Implement encryption at rest for the RDS cluster to enhance data security.
    • Use parameter store or secrets manager to securely store sensitive data like passwords and access keys instead of hardcoding them in the Terraform configuration.
    • Restrict inbound and outbound traffic in the security group to only necessary ports and IP ranges for improved network security.
    • Enable VPC flow logs to capture network traffic for monitoring and security analysis.
  2. Monitoring and Logging πŸ“ŠπŸ”:

    • Set up CloudWatch alarms to monitor RDS metrics such as CPU utilization, storage capacity, and database connections.
    • Configure CloudTrail to log API activity for auditing and compliance purposes.
    • Enable enhanced monitoring for RDS instances to collect and visualize database performance metrics.
    • Implement centralized logging using services like CloudWatch Logs or Elasticsearch for consolidated log management and analysis.

By incorporating these enhancements, you can create a more secure and robust infrastructure that is better equipped for production deployments. Remember to regularly review and update your configurations to address any new security threats or compliance requirements.

. . . . . . . . . . . . . . . . . . . . . .