如何使用 Terraform 将多个安全组附加到 RDS 和 Elasticache Redis

How to attach multiple security groups to RDS and Elasticache Redis with Terraform

我想将多个安全组附加到我的 RDS 和 Elasticache 实例,我不知何故未能做到,我不太明白为什么,

基本上,我正在尝试合并来自两个不同位置的两个安全组 ID 输出,并将它们分配给我的 RDS 和 Elasticache。

但是一直报下面的错误, 我试着用 concat()、flatten()、toset() 和 tolist() 函数来做,但没有用。 Terraform 文档说可以将多个安全组作为列表给出,但我无法让它工作。

Error: Incorrect attribute value type

  on modules/aws/elasticache-redis/main.tf line 26, in resource "aws_elasticache_replication_group" "elasticache-redis":
  26:   security_group_ids   = [var.security_group_ids]
    |----------------
    | var.security_group_ids is tuple with 2 elements

Inappropriate value for attribute "security_group_ids": element 0: string
required.


Error: Incorrect attribute value type

  on modules/aws/rds-mysql/main.tf line 26, in resource "aws_db_instance" "rds-mysql":
  26:   vpc_security_group_ids          = [var.security_group]
    |----------------
    | var.security_group is tuple with 2 elements

Inappropriate value for attribute "vpc_security_group_ids": element 0: string
required.

这是我的文件,

main.tf

module "example-module" {
  source = "./modules/example-module"

  environment                          = var.environment
  private_subnet_ids                   = module.vpc.private_subnet_ids
  rds_mysql_security_group             = [module.common-rds-mysql-security-group.security_group_id, module.security-group.rds-mysql-security-group]
  elasticache_redis_security_group_ids = [module.common-elasticache-redis-security-group.security_group_id, module.security-group.elasticache-redis-security-group]
  aws_sns_topic_arn                    = module.sns-system-notification-topic.topic_arn
 

  depends_on = [module.vpc, module.sns-system-notification-topic]
}

我的示例模块模块;

module "rds-mysql" {
  source = "../../aws/rds-mysql"

  identifier = "${var.environment}-${var.svc_name}"

  engine_version    = var.rds_mysql_engine_version
  instance_class    = var.rds_mysql_instance_class
  allocated_storage = var.rds_mysql_allocated_storage
  storage_type      = var.rds_mysql_storage_type

  name     = var.rds_mysql_name
  username = var.rds_mysql_username
  password = var.rds_mysql_password
  port     = var.rds_mysql_port

  parameter_group_name = var.rds_mysql_parameter_group_name
  security_group       = var.rds_mysql_security_group

  private_subnet_ids       = var.private_subnet_ids
  subnet_group_name        = "${var.environment}-${var.svc_name}-rds-mysql-subnet-group"
  subnet_group_description = "${var.environment}-${var.svc_name}-rds-mysql-subnet-group"

  auto_minor_version_upgrade      = var.rds_mysql_auto_minor_version_upgrade
  enabled_cloudwatch_logs_exports = var.rds_mysql_enabled_log_types
  publicly_accessible             = var.rds_mysql_publicly_accessible
  skip_final_snapshot             = var.rds_mysql_skip_final_snapshot
  maintenance_window              = var.rds_mysql_maintenance_window
  backup_retention_period         = var.rds_mysql_backup_retention_period
  backup_window                   = var.rds_mysql_backup_window
  copy_tags_to_snapshot           = var.rds_mysql_copy_tags_to_snapshot
  deletion_protection             = var.rds_mysql_deletion_protection
  multi_az                        = var.rds_mysql_multi_az
  enable_slave                    = var.rds_mysql_enable_slave
  slave_count                     = var.rds_mysql_slave_count

  tags = {
    Environment = "${var.environment}-${var.svc_name}"
    Name        = "${var.environment}-${var.svc_name}-rds-mysql"
  }
}

module "elasticache-redis" {
  source = "../../aws/elasticache-redis"

  replication_group_id          = "${var.environment}-${var.svc_name}"
  replication_group_description = "${var.environment}-${var.svc_name}"

  engine_version = var.elasticache_redis_engine_version
  port           = var.elasticache_redis_port

  number_cache_clusters = var.elasticache_redis_number_cache_clusters
  node_type             = var.elasticache_redis_node_type

  notification_topic_arn = var.elasticache_event_alerts_topic_arn

  parameter_group_name = var.elasticache_redis_parameter_group_name
  security_group_ids   = var.elasticache_redis_security_group_ids
  subnet_group_name    = "${var.environment}-${var.svc_name}-redis-subnet-group"
  private_subnet_ids   = var.private_subnet_ids

  auto_minor_version_upgrade = var.elasticache_redis_auto_minor_version_upgrade
  maintenance_window         = var.elasticache_redis_maintenance_window
  snapshot_window            = var.elasticache_redis_snapshot_window
  snapshot_retention_limit   = var.elasticache_redis_snapshot_retention_limit

  tags = {
    Environment = "${var.environment}-${var.svc_name}"
    Name        = "${var.environment}-${var.svc_name}-redis"
  }
}

最后,我的 RDS 和 Elasticache 模块,

resource "aws_elasticache_replication_group" "elasticache-redis" {
  automatic_failover_enabled    = var.automatic_failover_enabled
  availability_zones            = [data.aws_availability_zones.available.names[0]]
  replication_group_id          = var.replication_group_id
  replication_group_description = var.replication_group_description

  engine         = var.engine
  engine_version = var.engine_version
  port           = var.port

  number_cache_clusters = var.number_cache_clusters
  node_type             = var.node_type

  notification_topic_arn = var.notification_topic_arn

  parameter_group_name = var.parameter_group_name
  security_group_ids   = [var.security_group_ids]
  subnet_group_name    = aws_elasticache_subnet_group.elasticache-redis-subnet-group.id

  auto_minor_version_upgrade = var.auto_minor_version_upgrade
  maintenance_window         = var.maintenance_window
  snapshot_window            = var.snapshot_window
  snapshot_retention_limit   = var.snapshot_retention_limit
  tags                       = var.tags

  lifecycle {
    ignore_changes = [
      availability_zones
    ]
  }
}
resource "aws_db_instance" "rds-mysql" {
  identifier = var.identifier

  availability_zone = data.aws_availability_zones.available.names[0]
  engine            = var.engine
  engine_version    = var.engine_version
  instance_class    = var.instance_class
  allocated_storage = var.allocated_storage
  storage_type      = var.storage_type

  name     = var.name
  username = var.username
  password = var.password
  port     = var.port

  parameter_group_name            = var.parameter_group_name
  db_subnet_group_name            = aws_db_subnet_group.rds-mysql-subnet-group.id
  vpc_security_group_ids          = [var.security_group]
  enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports

  auto_minor_version_upgrade = var.auto_minor_version_upgrade
  publicly_accessible        = var.publicly_accessible
  skip_final_snapshot        = var.skip_final_snapshot
  maintenance_window         = var.maintenance_window
  backup_retention_period    = var.backup_retention_period
  backup_window              = var.backup_window
  copy_tags_to_snapshot      = var.copy_tags_to_snapshot
  deletion_protection        = var.deletion_protection
  multi_az                   = var.multi_az

  apply_immediately = true

  tags = var.tags

  lifecycle {
    ignore_changes = [
      availability_zone
    ]
  }
}

resource "aws_db_instance" "rds-mysql-slave" {
  count = var.enable_slave ? var.slave_count : 0

  identifier = "${var.identifier}-${count.index + 1}"

  engine            = var.engine
  engine_version    = var.engine_version
  instance_class    = var.instance_class
  allocated_storage = var.allocated_storage
  storage_type      = var.storage_type

  name     = var.name
  username = var.username
  password = var.password
  port     = var.port

  parameter_group_name   = var.parameter_group_name
  vpc_security_group_ids = [var.security_group]

  replicate_source_db = aws_db_instance.rds-mysql.identifier

  auto_minor_version_upgrade      = var.auto_minor_version_upgrade
  enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports
  publicly_accessible             = var.publicly_accessible
  skip_final_snapshot             = var.skip_final_snapshot
  maintenance_window              = var.maintenance_window
  backup_retention_period         = var.backup_retention_period
  backup_window                   = var.backup_window
  copy_tags_to_snapshot           = var.copy_tags_to_snapshot
  deletion_protection             = var.deletion_protection
  multi_az                        = var.multi_az

  tags = var.tags
}

我的安全组输出;

RDS 1 :
output "rds-mysql-security-group" {
    value = aws_security_group.rds-mysql-security-group.id
}
Elasticache 1 :
output "elasticache-redis-security-group" {
    value = aws_security_group.elasticache-redis-security-group.id
}
RDS 2 :
output "security_group_id" {
    value = module.rds-mysql-security-group.security_group_id
}
Elasticache 2 :
output "security_group_id" {
    value = module.elasticache-redis-security-group.security_group_id
}

以上输出应在 main.tf 中合并为一个列表,并由子模块继承。

任何帮助将不胜感激, 非常感谢。

据我了解,在您的 rds-mysqlrds-mysql-slaveelasticache-redis 中应该是:

resource "aws_elasticache_replication_group" "elasticache-redis" {
  #...
  security_group_ids   = var.security_group_ids
  #...
}

resource "aws_db_instance" "rds-mysql" {
  #... 
  vpc_security_group_ids          = var.security_group
  #...  
}

resource "aws_db_instance" "rds-mysql-slave" {
  #...
  vpc_security_group_ids = var.security_group
  #...  
}

这是因为 var.security_groupvar.security_group_ids 已经是列表。