使用 Terraform 執行 Amazon Redshift SQL查詢 - AWS 方案指引

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 Terraform 執行 Amazon Redshift SQL查詢

由 Sylvia Qi (AWS) 和 Aditya Ambati (AWS) 建立

程式碼儲存庫: terraform-execute-redshift-sql

環境:PoC 或試行

技術: DevOps;分析;大數據;資料湖

工作負載:開放原始碼

AWS 服務:Amazon Redshift; AWS CLI

Summary

使用基礎設施作為 Amazon Redshift 部署和管理的程式碼 (IaC) 是 中的普遍做法 DevOps。IaC 有助於各種 Amazon Redshift 資源的部署和組態,例如叢集、快照和參數群組。不過,IaC 不會延伸至資料庫資源的管理,例如資料表、結構描述、檢視和預存程序。這些資料庫元素是透過SQL查詢管理,IaC 工具不會直接支援這些元素。雖然存在用於管理這些資源的解決方案和工具,但您可能不想在技術堆疊中引入其他工具。

此模式概述使用 Terraform 部署 Amazon Redshift 資料庫資源的方法,包括資料表、結構描述、檢視和預存程序。模式區分兩種類型的SQL查詢:

  • 不可重複的查詢 – 這些查詢會在初始 Amazon Redshift 部署期間執行一次,以建立必要的資料庫元件。

  • 可重複查詢 – 這些查詢是不可變的,可以在不影響資料庫的情況下重新執行。解決方案使用 Terraform 來監控可重複查詢的變更,並相應地套用這些變更。

如需詳細資訊,請參閱其他資訊 中的解決方案逐步解說

先決條件和限制

先決條件

您必須具有作用中 , AWS 帳戶 並在部署機器上安裝下列項目:

限制

  • 此解決方案支援單一 Amazon Redshift 資料庫,因為 Terraform 僅允許在叢集建立期間建立一個資料庫。

  • 此模式不包括在套用可重複查詢之前驗證可重複查詢變更的測試。我們建議您整合此類測試,以提高可靠性。

  • 為了說明解決方案,此模式提供使用本機 Terraform 狀態redshift.tf檔案的範例檔案。不過,對於生產環境,我們強烈建議您使用具有鎖定機制的遠端狀態檔案,以提高穩定性和協同合作。

  • 有些 AWS 服務 並非所有 都提供 AWS 區域。如需區域可用性,請參閱AWS 服務 依區域 區分。如需特定端點,請參閱服務端點和配額 ,然後選擇服務的連結。

產品版本

此解決方案是在 Amazon Redshift 修補程式 179 上開發和測試。

程式碼儲存庫

此模式的程式碼可在 GitHub amazon-redshift-sql-deploy-terraform 儲存庫中使用。

架構

下圖說明 Terraform 如何透過處理不可重複和可重複的SQL查詢來管理 Amazon Redshift 資料庫資源。

使用SQL查詢管理 Amazon Redshift 資料庫資源的 Terraform 程序。

圖表顯示下列步驟:

  1. Terraform 會在初始 Amazon Redshift 叢集部署期間套用不可重複的SQL查詢。

  2. 開發人員會將變更遞交至可重複的SQL查詢。

  3. Terraform 會監控可重複SQL查詢中的變更。

  4. Terraform 會將可重複的SQL查詢套用至 Amazon Redshift 資料庫。

此模式提供的解決方案是根據 Amazon Redshift 的 Terraform 模組建置。Terraform 模組會佈建 Amazon Redshift 叢集和資料庫。為了增強模組,我們使用 資源,該terraform_data資源調用自訂 Python 指令碼,以使用 Amazon Redshift ExecuteStatementAPI操作執行SQL查詢。因此,模組可以執行下列動作:

  • 在佈建資料庫之後,使用SQL查詢來部署任何數量的資料庫資源。

  • 持續監控可重複SQL查詢中的變更,並使用 Terraform 套用這些變更。

如需詳細資訊,請參閱其他資訊 中的解決方案逐步解說

工具

AWS 服務

  • Amazon Redshift 是 中完全受管的 PB 級資料倉儲服務 AWS 雲端。

其他工具

  • Terraform 是來自 的基礎設施作為程式碼 IaC) 工具 HashiCorp ,可協助您建立和管理雲端和內部部署資源。

  • Python 是一種一般用途的程式設計語言,用於此模式來執行SQL查詢。

最佳實務

史詩

任務描述所需的技能

複製儲存庫。

若要複製包含 Terraform 程式碼的 Git 儲存庫來佈建 Amazon Redshift 叢集,請使用下列命令。

git clone https://github.com/aws-samples/amazon-redshift-sql-deploy-terraform.git
DevOps 工程師

更新 Terraform 變數。

若要根據您的特定需求自訂 Amazon Redshift 叢集部署,請在 terraform.tfvars 檔案中更新下列參數。

region = "<AWS_REGION>" cluster_identifier = "<REDSHIFT_CLUSTER_IDENTIFIER>" node_type = "<REDSHIFT_NODE_TYPE>" number_of_nodes = "<REDSHIFT_NODE_COUNT>" database_name = "<REDSHIFT_DB_NAME>" subnet_ids = "<REDSHIFT_SUBNET_IDS>" vpc_security_group_ids = "<REDSHIFT_SECURITY_GROUP_IDS>" run_nonrepeatable_queries = true run_repeatable_queries = true sql_path_bootstrap = "<BOOTSTRAP_SQLS_PATH>" sql_path_nonrepeatable = "<NON-REPEATABLE_SQLS_PATH>" sql_path_repeatable = "<REPEATABLE_SQLS_PATH>" sql_path_finalize = "<FINALIZE_SQLS_PATH>" create_random_password = false master_username = "<REDSHIFT_MASTER_USERNAME>"
DevOps 工程師

使用 Terraform 部署資源。

  1. 若要準備部署程序,請使用下列命令在複製的儲存庫中初始化 Terraform。

    terraform init
  2. 若要預覽 Terraform 將套用至基礎設施的變更,請使用下列命令來建立執行計畫。

    terraform plan -var-file terraform.tfvars
  3. 若要佈建 Amazon Redshift 叢集和相關資源,請使用下列命令來套用 Terraform 執行計畫。

    terraform apply -var-file terraform.tfvars
DevOps 工程師

(選用) 執行其他SQL查詢。

範例儲存庫提供多個SQL查詢供示範使用。若要執行您自己的SQL查詢,請將它們新增至下列資料夾:

/bootstrap

/nonrepeatable

/repeatable

/finalize

任務描述所需的技能

監控SQL陳述式的部署。

您可以監控 Amazon Redshift 叢集的SQL執行結果。如需顯示失敗和成功SQL執行的輸出範例,請參閱其他資訊 中的範例SQL陳述式。

DBA, DevOps engineer

清除資源。

若要刪除 Terraform 部署的所有資源,請執行下列命令。

terraform destroy
DevOps 工程師
任務描述所需的技能

驗證 Amazon Redshift 叢集中的資料。

  1. 登入 AWS Management Console,然後開啟 Amazon Redshift 主控台。

  2. 在導覽選單上,選擇叢集。在清單中選擇相關的叢集名稱。

  3. 請遵循 Amazon Redshift 文件中的使用 Amazon Redshift 查詢編輯器 v2 查詢資料庫的指示。

DBA, AWS DevOps

相關資源

AWS 文件

其他資源

其他資訊

解決方案演練

若要使用 解決方案,您必須以特定方式組織 Amazon Redshift SQL查詢。所有SQL查詢都必須存放在具有.sql副檔名的檔案中。

在此模式提供的程式碼範例中,SQL查詢會以下列資料夾結構進行組織。您可以修改程式碼 (sql-queries.tfsql-queries.py),以使用任何符合您獨特使用案例的結構。

/bootstrap |- Any # of files |- Any # of sub-folders /nonrepeatable |- Any # of files |- Any # of sub-folders /repeatable /udf |- Any # of files |- Any # of sub-folders /table |- Any # of files |- Any # of sub-folders /view |- Any # of files |- Any # of sub-folders /stored-procedure |- Any # of files |- Any # of sub-folders /finalize |- Any # of files |- Any # of sub-folders

根據上述資料夾結構,在 Amazon Redshift 叢集部署期間,Terraform 會以下列順序執行查詢:

  1. /bootstrap

  2. /nonrepeatable

  3. /repeatable

  4. /finalize

/repeatable 資料夾包含四個子資料夾:/udf/view/table/stored-procedure。這些子資料夾指出 Terraform 執行SQL查詢的順序。

執行SQL查詢的 Python 指令碼為 sql-queries.py。首先,指令碼會讀取特定來源目錄的所有檔案和子資料夾,例如 sql_path_bootstrap 參數。然後,指令碼會透過呼叫 Amazon Redshift ExecuteStatementAPI操作來執行查詢。檔案中可能有一或多個SQL查詢。下列程式碼片段顯示 Python 函數,該函數會針對 Amazon Redshift 叢集執行存放在檔案中的SQL陳述式。

def execute_sql_statement(filename, cluster_id, db_name, secret_arn, aws_region): """Execute SQL statements in a file""" redshift_client = boto3.client( 'redshift-data', region_name=aws_region) contents = get_contents_from_file(filename), response = redshift_client.execute_statement( Sql=contents[0], ClusterIdentifier=cluster_id, Database=db_name, WithEvent=True, StatementName=filename, SecretArn=secret_arn ) ...

Terraform 指令碼會sql-queries.tf建立叫用sql-queries.py指令碼的 terraform_data 資源。四個資料夾各有一個terraform_data資源:/bootstrap/repeatable/nonrepeatable/finalize。下列程式碼片段顯示執行/bootstrap資料夾中SQL查詢terraform_data的資源。

locals { program = "${path.module}/sql-queries.py" redshift_cluster_name = try(aws_redshift_cluster.this[0].id, null) } resource "terraform_data" "run_bootstrap_queries" { count = var.create && var.run_nonrepeatable_queries && (var.sql_path_bootstrap != "") && (var.snapshot_identifier == null) ? 1 : 0 depends_on = [aws_redshift_cluster.this[0]] provisioner "local-exec" { command = "python3 ${local.program} ${var.sql_path_bootstrap} ${local.redshift_cluster_name} ${var.database_name} ${var.redshift_secret_arn} ${local.aws_region}" } }

您可以使用下列變數來控制是否執行這些查詢。如果您不想在 sql_path_bootstrapsql_path_repeatablesql_path_nonrepeatable或 中執行查詢sql_path_finalize,請將其值設定為 ""

run_nonrepeatable_queries = true run_repeatable_queries = true sql_path_bootstrap = "src/redshift/bootstrap" sql_path_nonrepeatable = "src/redshift/nonrepeatable" sql_path_repeatable = "src/redshift/repeatable" sql_path_finalize = "src/redshift/finalize"

當您執行 時terraform apply,無論指令碼的結果為何,Terraform 都會考慮在指令碼完成後新增terraform_data的資源。如果某些SQL查詢失敗,且您想要重新執行,您可以從 Terraform 狀態手動移除資源,然後terraform apply再次執行。例如,下列命令會從 Terraform 狀態中移除run_bootstrap_queries資源。

terraform state rm module.redshift.terraform_data.run_bootstrap_queries[0]

下列程式碼範例顯示run_repeatable_queries資源如何使用 sha256 雜湊 監控repeatable資料夾中的變更。如果資料夾中的任何檔案已更新,Terraform 會標記整個目錄以進行更新。然後,Terraform 會在下一個 期間再次執行目錄中的查詢terraform apply

resource "terraform_data" "run_repeatable_queries" { count = var.create_redshift && var.run_repeatable_queries && (var.sql_path_repeatable != "") ? 1 : 0 depends_on = [terraform_data.run_nonrepeatable_queries] # Continuously monitor and apply changes in the repeatable folder triggers_replace = { dir_sha256 = sha256(join("", [for f in fileset("${var.sql_path_repeatable}", "**") : filesha256("${var.sql_path_repeatable}/${f}")])) } provisioner "local-exec" { command = "python3 ${local.sql_queries} ${var.sql_path_repeatable} ${local.redshift_cluster_name} ${var.database_name} ${var.redshift_secret_arn}" } }

若要精簡程式碼,您可以實作 機制,以偵測並僅將變更套用至repeatable資料夾中已更新的檔案,而不是不區分地套用變更至所有檔案。

範例SQL陳述式

下列輸出顯示SQL執行失敗,以及錯誤訊息。

module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Executing: ["/bin/sh" "-c" "python3 modules/redshift/sql-queries.py src/redshift/nonrepeatable testcluster-1 db1 arn:aws:secretsmanager:us-east-1:XXXXXXXXXXXX:secret:/redshift/master_user/password-8RapGH us-east-1"] module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): ------------------------------------------------------------------- module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): src/redshift/nonrepeatable/table/admin/admin.application_family.sql module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): ------------------------------------------------------------------- module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Status: FAILED module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): SQL execution failed. module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Error message: ERROR: syntax error at or near ")" module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Position: 244 module.redshift.terraform_data.run_nonrepeatable_queries[0]: Creation complete after 3s [id=ee50ba6c-11ae-5b64-7e2f-86fd8caa8b76]

下列輸出顯示成功SQL執行。

module.redshift.terraform_data.run_bootstrap_queries[0]: Provisioning with 'local-exec'... module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): Executing: ["/bin/sh" "-c" "python3 modules/redshift/sql-queries.py src/redshift/bootstrap testcluster-1 db1 arn:aws:secretsmanager:us-east-1:XXXXXXXXXXXX:secret:/redshift/master_user/password-8RapGH us-east-1"] module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): ------------------------------------------------------------------- module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): src/redshift/bootstrap/db.sql module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): ------------------------------------------------------------------- module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): Status: FINISHED module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): SQL execution successful. module.redshift.terraform_data.run_bootstrap_queries[0]: Creation complete after 2s [id=d565ef6d-be86-8afd-8e90-111e5ea4a1be]