You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform动态创建多DynamoDB表遇属性类型不匹配错误求助

解决Terraform批量创建多属性DynamoDB表的错误

错误原因分析

  • 变量dynamodb_table中attribute字段定义为单个object,但terraform.tfvars中传入的是列表对象,类型不匹配导致报错。
  • main.tf中动态属性循环错误引用了不存在的var.attributes,应指向当前表的属性列表。
  • 全局GSI变量独立于表配置,无法实现每个表的个性化GSI需求。
  • ttl_enabled定义为string类型,不符合Terraform对该参数的bool类型要求;write_capacity定义为string,应为number类型。

修正后的代码实现

1. 修正变量声明(variable.tf)

调整attribute为列表类型,修正字段类型,将GSI嵌入表对象作为可选配置:

variable "dynamodb_table" {
  type = list(object({
    table_name         = string
    billing_mode       = string
    read_capacity      = optional(number)
    write_capacity     = optional(number)  # 修正为number类型
    hash_key           = string
    ttl_attribute_name = string
    ttl_enabled        = bool              # 修正为bool类型
    range_key          = optional(string)
    attributes         = optional(list(object({  # 改为列表类型,命名更规范
      name = string
      type = string
    })))
    global_secondary_indexes = optional(list(object({  # GSI嵌入表配置,支持独立定义
      index_name               = string
      index_projection_type    = string
      index_range_key          = optional(string)
      index_hash_key           = string
      index_write_capacity     = optional(number)
      index_read_capacity      = optional(number)
      index_non_key_attributes = optional(list(string))
    })))
  }))
}

variable "default_tags" {
  type = map(string)
  default = {}
}

2. 修正配置文件(terraform.tfvars)

对应变量调整,修正字段名称和类型,为每个表配置独立属性和GSI:

dynamodb_table = [
  {
    table_name   = "devops-test-01",
    billing_mode = "PAY_PER_REQUEST",
    hash_key           = "UserId",
    range_key          = "GameTitle",
    ttl_attribute_name = "ttl_attribute_name",
    ttl_enabled        = false  # 改为布尔值,无需引号
    attributes = [
      {
        name = "UserId"
        type = "S"
      },
      {
        name = "GameTitle"
        type = "S"
      },
      {
        name = "Id"
        type = "S"
      }
    ],
    global_secondary_indexes = [
      {
        index_name               = "TitleIndex"
        index_hash_key           = "UserId"
        index_range_key          = "GameTitle"
        index_projection_type    = "INCLUDE"
        index_non_key_attributes = ["Id"]
      }
    ]
  },
  {
    table_name   = "devops-test-02",
    billing_mode = "PAY_PER_REQUEST",
    hash_key           = "GameTitle",
    ttl_attribute_name = "ttl_attribute_name",
    ttl_enabled        = false,
    attributes = [
      {
        name = "GameTitle"
        type = "S"
      }
    ]
    # 该表无需GSI,可省略配置
  }
]

default_tags = {
  "Environment" = "Dev",
  "Owner"       = "xxx"
}

3. 修正资源配置(main.tf)

修复动态块循环引用,支持每个表的独立属性和GSI:

resource "aws_dynamodb_table" "basic-dynamodb-table" {
  for_each       = { for idx, table in var.dynamodb_table : table.table_name => table }  # 用表名作为键,更直观
  name           = each.value.table_name
  billing_mode   = each.value.billing_mode
  read_capacity  = each.value.read_capacity
  write_capacity = each.value.write_capacity
  hash_key       = each.value.hash_key
  range_key      = each.value.range_key

  # TTL配置
  ttl {
    attribute_name = each.value.ttl_attribute_name
    enabled        = each.value.ttl_enabled
  }

  # 动态生成表属性
  dynamic "attribute" {
    for_each = each.value.attributes != null ? each.value.attributes : []  # 处理可选属性列表
    content {
      name = attribute.value.name
      type = attribute.value.type
    }
  }

  # 动态生成全局二级索引
  dynamic "global_secondary_index" {
    for_each = each.value.global_secondary_indexes != null ? each.value.global_secondary_indexes : []
    content {
      name               = global_secondary_index.value.index_name
      hash_key           = global_secondary_index.value.index_hash_key
      projection_type    = global_secondary_index.value.index_projection_type
      range_key          = global_secondary_index.value.index_range_key
      read_capacity      = global_secondary_index.value.index_read_capacity
      write_capacity     = global_secondary_index.value.index_write_capacity
      non_key_attributes = global_secondary_index.value.index_non_key_attributes
    }
  }

  tags = merge(
    var.default_tags,
    {
      Name = each.value.table_name
    }
  )
}

验证方法

  1. 执行terraform init初始化环境。
  2. 执行terraform plan查看执行计划,确认会创建两个符合预期的DynamoDB表,每个表的属性和GSI独立。
  3. 执行terraform apply完成创建。

内容的提问来源于stack exchange,提问作者beginnertopython

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:45:23