【问题标题】:How to make a single-AZ (non-HA) RDS instance with terraform?如何使用 terraform 制作单可用区(非 HA)RDS 实例?
【发布时间】:2022-01-11 03:38:36
【问题描述】:

this AWS 数据库博客中,他们断言

您可以在单可用区数据库 (DB) 实例或 满足高可用性要求的多可用区数据库实例

你可以

...将现有的单可用区实例修改为多可用区部署。

此外,

...您可以创建多可用区只读副本,将其与您的 单可用区数据库实例,然后将其提升为主数据库实例 最大限度地减少转换过程中的延迟。

另外,在官方AWS VPC Module的v1.32中,有多次引用single_nat_gateway的用法,特别是

如果 single_nat_gateway = true,那么所有私有子网都会路由 他们的互联网流量通过这个单一的 NAT 网关。

在官方 RDS 模块中,multi_az 显示为默认为 false (link)。

尽管如此,我收到以下错误

╷
│ Error: DBSubnetGroupDoesNotCoverEnoughAZs: The DB subnet group doesn't meet Availability Zone (AZ) coverage requirement. Current AZ coverage: us-west-2a. Add subnets to cover at least 2 AZs.
│   status code: 400, request id: *****
│ 
│   with module.rds.module.db_subnet_group.aws_db_subnet_group.this[0],
│   on .terraform/modules/rds/modules/db_subnet_group/main.tf line 8, in resource "aws_db_subnet_group" "this":
│    8: resource "aws_db_subnet_group" "this" {

当尝试terraform apply 这个main.tf 配置时:

module "rds" {
  source                                = "terraform-aws-modules/rds/aws"
  version                               = "~> 3.4.0"
  identifier                            = "${var.env}-${var.user}-${local.db_name}"
  engine                                = var.postgres.engine
  engine_version                        = var.postgres.engine_version
  family                                = var.postgres.family
  major_engine_version                  = var.postgres.major_engine_version
  instance_class                        = var.postgres.instance_class
  allocated_storage                     = var.postgres.allocated_storage
  max_allocated_storage                 = var.postgres.max_allocated_storage
  storage_encrypted                     = var.postgres.storage_encrypted
  password                              = random_password.password.result
  port                                  = var.postgres.port
  multi_az                              = false
  subnet_ids                            = [data.aws_subnet.priv1.id]
  vpc_security_group_ids                = [module.db_security_group.security_group_id]
  maintenance_window                    = var.postgres.maintenance_window
  backup_window                         = var.postgres.backup_window
  enabled_cloudwatch_logs_exports       = var.postgres.enabled_cloudwatch_logs_exports
  backup_retention_period               = var.postgres.backup_retention_period
  skip_final_snapshot                   = var.postgres.skip_final_snapshot
  deletion_protection                   = var.postgres.deletion_protection
  performance_insights_enabled          = var.postgres.performance_insights_enabled
  performance_insights_retention_period = var.postgres.performance_insights_retention_period
  create_monitoring_role                = var.postgres.create_monitoring_role
  monitoring_role_name                  = "${var.env}-${var.user}-${var.postgres.monitoring_role_name}"
  monitoring_interval                   = var.postgres.monitoring_interval
  snapshot_identifier                   = var.postgres.snapshot_identifier
  iam_database_authentication_enabled   = var.postgres.iam_auth
  apply_immediately                     = true
  tags = {
    Name        = "${var.env}-${var.user}-rds"
    Terraform   = "true"
    Environment = var.env
    Created     = timestamp()
  }
}

在我的terraform.tfvars 中定义了这个postgres 变量:

postgres = {
  db_name = "postgres-db"
  # All available versions: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts
  engine                                = "postgres"
  engine_version                        = "11.12"
  family                                = "postgres11" # DB parameter group
  major_engine_version                  = "11"         # DB option group
  instance_class                        = "db.t2.micro"
  allocated_storage                     = 100
  max_allocated_storage                 = 200
  storage_encrypted                     = false
  port                                  = 5432
  multi_az                              = false
  maintenance_window                    = "Mon:00:00-Mon:03:00"
  backup_window                         = "03:00-06:00"
  enabled_cloudwatch_logs_exports       = ["postgresql", "upgrade"]
  backup_retention_period               = 0
  skip_final_snapshot                   = true
  deletion_protection                   = false
  performance_insights_enabled          = false
  performance_insights_retention_period = 7
  create_monitoring_role                = true
  monitoring_role_name                  = "monitoring_role"
  monitoring_interval                   = 60
  snapshot_identifier                   = "arn:aws:rds:us-west-2:999999999999:snapshot:rds-ss"
  iam_auth                              = true
}

关于 SO 的类似问题似乎都有关于您必须提供多个可用区的主题的答案,这意味着至少有两个子网,如果您手动将它们创建为私有子网 - 将那么每个人都需要自己的 NAT 网关。这似乎是不必要的昂贵和限制,尤其是对于开发和测试环境。

如何使用这些组件部署单可用区 RDS Postgres 实例?

【问题讨论】:

    标签: amazon-web-services terraform amazon-rds terraform-provider-aws high-availability


    【解决方案1】:

    一个数据库子网组必须有多个子网。这是您无法绕过的 RDS 要求。即使您只部署一个实例,如果整个可用区出现故障,Amazon RDS 也会在您指定的其他可用区之一中自动启动一个新实例。这是您通过 Amazon RDS 自动获得的托管数据库服务之一。

    因此,即使您部署的是单可用区实例,也必须在数据库子网组中指定多个可用区。

    【讨论】:

    • 评论 1 了解更多上下文:在我的配置中,我没有指定任何 db 子网组,只为我的公共子网中的两个 EC2 实例指定一个 sg,db_security_groupingress/@ 987654323@s 设置为那个 sg。我正在手动创建我的 2 个私有子网,每个子网都在它们自己的 az 中,如果我将它们都作为列表提供给 rds 的 subnet_ids 参数,我的部署就可以工作。
    • 评论 2:您对提供公共 nat(需要一个 eip)有何想法 - 即使multi_az = false,我是否真的需要为每个私有子网提供一个 nat?
    • 评论 1:是的,这与我所说的相同。即使您只运行一个实例,您也必须为您的数据库提供至少两个子网。评论 2:RDS 根本不需要 NAT。如果您在私有子网中有其他服务,您可能需要一个 NAT,但这是一个完全独立的主题。
    • 我希望 RDS 是私有的,因为它包含 PII。同样,我有正在读取和写入相关 RDS 的 lambda,其中 iirc 确实有私有子网要求并且还需要与外部网络通信,所以如果我必须通过两个子网有两个 AZ,我想我'将需要两个 nat(因此需要两个 eips)不是吗?
    • RDS 不需要连接到外部网络,因此它可以在没有 NAT 网关路由的私有子网中。如果您决定创建 NAT,您可以为每个 VPC 或每个 AZ 一个 NAT,这取决于您是否需要在区域 AWS 中断时进行故障转移。
    猜你喜欢
    • 2021-08-23
    • 1970-01-01
    • 2018-02-08
    • 2017-02-14
    • 2018-09-01
    • 2018-12-31
    • 2018-11-17
    • 2022-07-07
    • 1970-01-01
    相关资源
    最近更新 更多