AWS Glue 管道与 Terraform

AWS Glue pipeline with Terraform

我们正在使用 AWS Glue 作为我公司 ETL 的管道工具。到目前为止,管道是通过控制台手动创建的,我现在正在转向 Terraform 用于未来的管道,因为我相信 IaC 是必经之路。

我一直在尝试开发一个可以重复使用的模块(或多个模块),因为我知道我们将为各种项目制作更多的管道。我遇到的困难是使用模块创建良好的抽象级别。 AWS Glue 有几个 components/resources,包括 Glue 连接、数据库、爬虫、作业、作业触发器和工作流。问题是数据库、作业、爬虫 and/or 触发器 及其交互 的数量(即一些触发器可能是有条件的,而其他可能只是被安排)可能会有所不同,具体取决于项目,我很难通过模块抽象出这种复杂性。

我不得不在资源中创建很多 for_each“循环”和动态块,以尝试尽可能通用地呈现模块(例如,这样我就可以创建 N 个作业 and/or 从根模块触发并定义它们的交互)。

我理解模块实际上应该非常有主见和具体,并且可以说擅长于一项任务,这意味着我的问题可能只是概念性的。这些管道因项目而异,这一事实使它们成为模块的糟糕用例。

附带说明一下,我无法在网上找到任何强大的 AWS Glue 模块示例,因此这可能是另一个表明它确实不是最佳用例的指标。

如有任何想法,我们将不胜感激。

编辑: 根据要求,这是我的根模块中的一些代码:

module "glue_data_catalog" {
  source = "../../modules/aws-glue/data-catalog"

  # Connection
  create_connection = true

  conn_name        = "SAMPLE"
  conn_description = "SAMPLE."
  conn_type        = "JDBC"
  conn_url         = "jdbc:sqlserver:"
  conn_sg_ids      = ["sampleid"]
  conn_subnet_id   = "sampleid"
  conn_az          = "eu-west-1a"

  conn_user = var.conn_user
  conn_pass = var.conn_pass

  # Databases
  db_names = [
    "raw",
    "cleaned",
    "consumption"
  ]

  # Crawlers
  crawler_settings = {
    Crawler_raw = {
      database_name = "raw"
      s3_path       = "bucket-path"
      jdbc_paths    = []
    },
    Crawler_cleaned = {
      database_name = "cleaned"
      s3_path       = "bucket-path"
      jdbc_paths    = []
    }
  }

  crawl_role = "SampleRole"
}

粘附数据目录模块:

#############################
# Glue Connection
#############################
resource "aws_glue_connection" "this" {
  count = var.create_connection ? 1 : 0

  name            = var.conn_name
  description     = var.conn_description
  connection_type = var.conn_type

  connection_properties = {
    JDBC_CONNECTION_URL = var.conn_url
    USERNAME            = var.conn_user
    PASSWORD            = var.conn_pass
  }

  catalog_id     = var.conn_catalog_id
  match_criteria = var.conn_criteria

  physical_connection_requirements {
    security_group_id_list = var.conn_sg_ids
    subnet_id              = var.conn_subnet_id
    availability_zone      = var.conn_az
  }
}

#############################
# Glue Database Catalog
#############################
resource "aws_glue_catalog_database" "this" {
  for_each = var.db_names

  name         = each.key
  description  = var.db_description
  catalog_id   = var.db_catalog_id
  location_uri = var.db_location_uri
  parameters   = var.db_params
}

#############################
# Glue Crawlers
#############################
resource "aws_glue_crawler" "this" {
  for_each = var.crawler_settings

  name          = each.key
  database_name = each.value.database_name

  description   = var.crawl_description
  role          = var.crawl_role
  configuration = var.crawl_configuration

  s3_target {
    connection_name = var.crawl_s3_connection
    path            = each.value.s3_path
    exclusions      = var.crawl_s3_exclusions
  }

  dynamic "jdbc_target" {
    for_each = each.value.jdbc_paths
    content {
      connection_name = var.crawl_jdbc_connection
      path            = jdbc_target.value
      exclusions      = var.crawl_jdbc_exclusions
    }
  }

  recrawl_policy {
    recrawl_behavior = var.crawl_recrawl_behavior
  }

  schedule     = var.crawl_schedule
  table_prefix = var.crawl_table_prefix
  tags         = var.crawl_tags
}

在我看来,我实际上并没有以这种方式提供任何抽象,而只是使事情过于复杂。

我想我找到了解决问题的好方法,尽管它是“偶然”发生的。我们决定将管道分为两个不同的项目:

  • 源数据的 ETL
  • 用于计算各种 KPI 的 BI 作业

然后我注意到我可以将两个项目的资源组合在一起,并标准化我们让它们交互的方式(例如,一个连接、n 个表、n 个爬虫、n 个作业、一个触发器)。然后我能够为 ETL 过程创建一个模块,为 BI/KPIs 过程创建一个模块,它们提供了足够的抽象以实际有用。