Skip to content

Google Cloud SQL Terraform Module#

This module provides a comprehensive and flexible solution for provisioning and managing Google Cloud SQL instances. It supports both MySQL and MSSQL database engines and includes best practices for security and configuration, such as creating database users and managing their passwords with Secret Manager.

The module is built on top of the official GoogleCloudPlatform/sql-db/google modules, providing a streamlined interface for creating database instances with private networking, backup configurations, and other common settings.

Compatibility#

This module is compatible with Terraform version ~> 1.0 and has been tested with the following provider versions:

  • Google Provider: >= 6.28.0, < 7.0.0
  • Google Beta Provider: >= 6.28.0, < 7.0.0

Features#

  • Multi-Engine Support: Provision either MySQL or MSSQL instances by setting the appropriate database_version variable. To setup MySQL, set database_version_mysql = "MYSQL_8_0" and do not set anything for database_version_mssql. Same applies to set MSSQL
  • Automated User Management: The module automatically creates an admin user and a read-write user (rw) with randomly generated passwords stored securely in Google Cloud Secret Manager.
  • Private Networking: Easily configure Private Service Access to connect to your Cloud SQL instances from a shared VPC.
  • Configurable Backups: Define backup windows, retention policies, and locations to meet your RPO requirements.
  • Flexible Configuration: Customize nearly every aspect of your Cloud SQL instance, including machine type, disk size, and database flags.

Limitations#

  • No PostgreSQL Support: This module is currently designed for MySQL and MSSQL only. Support for PostgreSQL is not included.

Example Usage#

MySQL Instance#

module "mysql_instance" {
  source = "./modules/terraform-google-sql"

  # General Configuration
network_project_id    = "acme-prod-shared-vpc"
name                  = "sql-shared-prod-me-west1"
region                = "me-west1"
zone                  = "me-west1-b"
tier                  = "db-custom-2-3840"
disk_autoresize_limit = 20
disk_size             = 10
disk_type             = "PD_SSD"
pricing_plan          = "PER_USE"
ip_configuration = {
  "allocated_ip_range" : "private-acme-prod-shared-vpc",
  "authorized_networks" : [],
  "enable_private_path_for_google_cloud_services" : true,
  "ipv4_enabled" : false,
  "private_network" : "https://www.googleapis.com/compute/v1/projects/acme-prod-shared-vpc/global/networks/shared-vpc-network",
  "require_ssl" : null
}
user_name                   = "admin"
deletion_protection         = "false"
deletion_protection_enabled = "false"
enable_default_db           = "true"
enable_default_user         = "true"
edition                     = "ENTERPRISE"
availability_type           = "ZONAL"

  # MySQL-Specific Configuration
  database_version_mysql = "MYSQL_8_0"
  backup_configuration_mysql = {
    enabled    = true
    start_time = "03:00"
    location   = "us"
  }
}

MSSQL Instance#

module "mssql_instance" {
  source = "./modules/terraform-google-sql"

  # General Configuration
network_project_id    = "acme-prod-shared-vpc"
name                  = "sql-shared-prod-me-west1"
region                = "me-west1"
zone                  = "me-west1-b"
tier                  = "db-custom-2-3840"
disk_autoresize_limit = 20
disk_size             = 10
disk_type             = "PD_SSD"
pricing_plan          = "PER_USE"
ip_configuration = {
  "allocated_ip_range" : "private-acme-prod-shared-vpc",
  "authorized_networks" : [],
  "enable_private_path_for_google_cloud_services" : true,
  "ipv4_enabled" : false,
  "private_network" : "https://www.googleapis.com/compute/v1/projects/acme-prod-shared-vpc/global/networks/shared-vpc-network",
  "require_ssl" : null
}
user_name                   = "admin"
deletion_protection         = "false"
deletion_protection_enabled = "false"
enable_default_db           = "true"
enable_default_user         = "true"
edition                     = "ENTERPRISE"
availability_type           = "ZONAL"

  # MSSQL-Specific Configuration
  database_version_mssql = "SQLSERVER_2022_STANDARD"
  backup_configuration_mssql = {
    enabled                        = true
    start_time                     = "04:00"
    point_in_time_recovery_enabled = true
  }
}

Software#

This module requires the following software dependencies:

Service Account#

The service account used to run this module must have the following IAM roles:

  • roles/cloudsql.admin - To create and manage Cloud SQL instances
  • roles/compute.networkAdmin - To configure private networking and service access
  • roles/secretmanager.admin - To create and manage database user passwords in Secret Manager
  • roles/iam.serviceAccountUser - To use service accounts for Cloud SQL instances
  • roles/servicenetworking.networksAdmin - To configure private service access

APIs#

The following GCP APIs must be enabled in the target project:

  • Cloud SQL Admin API (sqladmin.googleapis.com)
  • Compute Engine API (compute.googleapis.com)
  • Service Networking API (servicenetworking.googleapis.com)
  • Secret Manager API (secretmanager.googleapis.com)
  • Cloud Resource Manager API (cloudresourcemanager.googleapis.com)

License#

This module is covered by a commercial license. Please see LICENSE for details.

Support#

This module is developed and maintained by MyOps Limited. For any support inquiries, please contact us at info@myops.co.il.

Requirements#

Name Version
terraform ~> 1
google >= 6.28.0, < 7.0.0
google-beta >= 6.28.0, < 7.0.0
random ~> 3.5

Providers#

Name Version
google >= 6.28.0, < 7.0.0
random ~> 3.5

Modules#

Name Source Version
mssql terraform-google-modules/sql-db/google//modules/mssql ~> 25.0.0
mysql GoogleCloudPlatform/sql-db/google//modules/mysql ~> 25.0.0

Resources#

Name Type
google_secret_manager_secret.db-secret resource
google_secret_manager_secret.user2-db-secret resource
google_secret_manager_secret_version.db-secret-version resource
google_secret_manager_secret_version.user2-db-secret-version resource
random_password.password resource
random_password.user2 resource
google_secret_manager_secret_version_access.admin-user data source
google_secret_manager_secret_version_access.rw-user data source

Inputs#

Name Description Type Default Required
activation_policy The activation policy for the master instance. Can be either ALWAYS, NEVER or ON_DEMAND. string "ALWAYS" no
active_directory_config The active_directory_config settings subblock map(string) {} no
additional_databases A list of databases to be created in your cluster
list(object({
name = string
charset = string
collation = string
}))
[] no
additional_users A list of users to be created in your cluster list(map(any)) [] no
availability_type The availability type for the master instance. Can be either REGIONAL or null. string "REGIONAL" no
backup_configuration_mssql The backup_configuration settings subblock for the database setings for MSSQL
object({
binary_log_enabled = bool
enabled = bool
point_in_time_recovery_enabled = bool
start_time = string
transaction_log_retention_days = string
retained_backups = number
retention_unit = string
})
{
"binary_log_enabled": null,
"enabled": false,
"point_in_time_recovery_enabled": null,
"retained_backups": null,
"retention_unit": null,
"start_time": null,
"transaction_log_retention_days": null
}
no
backup_configuration_mysql The backup_configuration settings subblock for the database setings for MySQL
object({
binary_log_enabled = optional(bool, false)
enabled = optional(bool, false)
start_time = optional(string)
location = optional(string)
transaction_log_retention_days = optional(string)
retained_backups = optional(number)
retention_unit = optional(string)
})
{} no
create_timeout The optional timout that is applied to limit long database creates. string "10m" no
database_flags List of Cloud SQL flags that are applied to the database server. See more details
list(object({
name = string
value = string
}))
[] no
database_version_mssql The database version to use string "" no
database_version_mysql The database version to use string "" no
db_charset The charset for the default database string "" no
db_collation The collation for the default database. Example: 'utf8_general_ci' string "" no
db_name The name of the default database to create string "default" no
delete_timeout The optional timout that is applied to limit long database deletes. string "10m" no
deletion_protection Used to block Terraform from deleting a SQL Instance. bool true no
deletion_protection_enabled Used to block Terraform from deleting a SQL Instance. bool true no
disk_autoresize Configuration to increase storage size bool true no
disk_autoresize_limit The maximum size to which storage can be auto increased number n/a yes
disk_size The disk size for the master instance number 10 no
disk_type The disk type for the master instance. string "PD_SSD" no
edition The edition of the database string "ENTERPRISE" no
enable_default_db Enable or disable the creation of the default database bool true no
enable_default_user Enable or disable the creation of the default user bool true no
encryption_key_name The full path to the encryption key used for the CMEK disk encryption string null no
ip_configuration The ip_configuration settings subblock
object({
authorized_networks = list(map(string))
ipv4_enabled = bool
private_network = string
require_ssl = bool
allocated_ip_range = string
enable_private_path_for_google_cloud_services = bool
})
{
"allocated_ip_range": null,
"authorized_networks": [],
"enable_private_path_for_google_cloud_services": false,
"ipv4_enabled": true,
"private_network": null,
"require_ssl": null
}
no
maintenance_window_day The day of week (1-7) for the master instance maintenance. number 1 no
maintenance_window_hour The hour of day (0-23) maintenance window for the master instance maintenance. number 23 no
maintenance_window_update_track The update track of maintenance window for the master instance maintenance. Can be either canary or stable. string "canary" no
name The name of the Cloud SQL resources string n/a yes
network_project_id The project ID to manage the Cloud SQL network string n/a yes
pricing_plan The pricing plan for the master instance. string "PER_USE" no
random_instance_name Sets random suffix at the end of the Cloud SQL resource name bool false no
read_replica_deletion_protection Used to block Terraform from deleting replica SQL Instances. bool false no
read_replica_name_suffix The optional suffix to add to the read instance name string "" no
read_replicas List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption_key_name = null. This is only for MySQL
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = list(object({
name = string
value = string
}))
backup_configuration = optional(object({
binary_log_enabled = bool
transaction_log_retention_days = string
}))
insights_config = optional(object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
}))
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
[] no
region The region of the Cloud SQL resources string "us-central1" no
sql_server_audit_config The sql_server_audit_config settings subblock map(string) {} no
tier The tier for the master instance. string "db-n1-standard-1" no
time_zone The time zone for the database string null no
update_timeout The optional timout that is applied to limit long database updates. string "10m" no
user_host The host for the default user string "%" no
user_labels labels for master instance map(string) {} no
user_name The name of the default user string "default" no
zone The zone for the master instance, it should be something like: us-central1-a, us-east1-c. string n/a yes

Outputs#

Name Description
mssql_instance_connection_name The connection name of the MSSQL master instance to be used in connection strings
mssql_instance_first_ip_address The first IPv4 address of the addresses assigned for the MSSQL master instance.
mssql_instance_ip_address The IPv4 address assigned for the MSSQL master instance
mssql_instance_name The instance name for the MSSQL master instance
mssql_instance_self_link The URI of the MSSQL master instance
mssql_instance_server_ca_cert The CA certificate information used to connect to the MSSQL instance via SSL
mssql_instance_service_account_email_address The service account email address assigned to the MSSQL master instance
mssql_private_address The private IP address assigned for the MSSQL master instance
mssql_private_ip_address The first private (PRIVATE) IPv4 address assigned for the MSSQL master instance
mysql_generated_user_password The auto generated default user password if not input password was provided for MySQL
mysql_instance_connection_name The connection name of the MySQL master instance to be used in connection strings
mysql_instance_first_ip_address The first IPv4 address of the addresses assigned for the MySQL master instance.
mysql_instance_ip_address The IPv4 address assigned for the MySQL master instance
mysql_instance_name The instance name for the MySQL master instance
mysql_instance_self_link The URI of the MySQL master instance
mysql_instance_server_ca_cert The CA certificate information used to connect to the MySQL instance via SSL
mysql_instance_service_account_email_address The service account email address assigned to the MySQL master instance
mysql_private_address The private IP address assigned for the MySQL master instance
mysql_private_ip_address The first private (PRIVATE) IPv4 address assigned for the MySQL master instance
mysql_public_ip_address The first public (PRIMARY) IPv4 address assigned for the MySQL master instance
mysql_read_replica_instance_names The instance names for the MySQL read replica instances
mysql_replicas_instance_connection_names The connection names of the MySQL replica instances to be used in connection strings
mysql_replicas_instance_first_ip_addresses The first IPv4 addresses of the addresses assigned for the MySQL replica instances
mysql_replicas_instance_self_links The URIs of the MySQL replica instances
mysql_replicas_instance_server_ca_certs The CA certificates information used to connect to the MySQL replica instances via SSL
mysql_replicas_instance_service_account_email_addresses The service account email addresses assigned to the MySQL replica instances