本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 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 帳戶 並在部署機器上安裝下列項目:
AWS Command Line Interface (AWS CLI)
使用 Amazon Redshift 讀取/寫入許可設定的AWS CLI 設定檔
Terraform
1.6.2 版或更新版本
限制
此解決方案支援單一 Amazon Redshift 資料庫,因為 Terraform 僅允許在叢集建立期間建立一個資料庫。
此模式不包括在套用可重複查詢之前驗證可重複查詢變更的測試。我們建議您整合此類測試,以提高可靠性。
為了說明解決方案,此模式提供使用本機 Terraform 狀態
redshift.tf
檔案的範例檔案。不過,對於生產環境,我們強烈建議您使用具有鎖定機制的遠端狀態檔案,以提高穩定性和協同合作。有些 AWS 服務 並非所有 都提供 AWS 區域。如需區域可用性,請參閱AWS 服務 依區域
區分。如需特定端點,請參閱服務端點和配額 ,然後選擇服務的連結。
產品版本
此解決方案是在 Amazon Redshift 修補程式 179 上開發和測試。
程式碼儲存庫
此模式的程式碼可在 GitHub amazon-redshift-sql-deploy-terraform
架構
下圖說明 Terraform 如何透過處理不可重複和可重複的SQL查詢來管理 Amazon Redshift 資料庫資源。
圖表顯示下列步驟:
Terraform 會在初始 Amazon Redshift 叢集部署期間套用不可重複的SQL查詢。
開發人員會將變更遞交至可重複的SQL查詢。
Terraform 會監控可重複SQL查詢中的變更。
Terraform 會將可重複的SQL查詢套用至 Amazon Redshift 資料庫。
此模式提供的解決方案是根據 Amazon Redshift 的 Terraform 模組terraform_data
資源調用自訂 Python 指令碼,以使用 Amazon Redshift ExecuteStatementAPI操作執行SQL查詢。因此,模組可以執行下列動作:
在佈建資料庫之後,使用SQL查詢來部署任何數量的資料庫資源。
持續監控可重複SQL查詢中的變更,並使用 Terraform 套用這些變更。
如需詳細資訊,請參閱其他資訊 中的解決方案逐步解說。
工具
AWS 服務
Amazon Redshift 是 中完全受管的 PB 級資料倉儲服務 AWS 雲端。
其他工具
最佳實務
史詩
任務 | 描述 | 所需的技能 |
---|---|---|
複製儲存庫。 | 若要複製包含 Terraform 程式碼的 Git 儲存庫來佈建 Amazon Redshift 叢集,請使用下列命令。
| DevOps 工程師 |
更新 Terraform 變數。 | 若要根據您的特定需求自訂 Amazon Redshift 叢集部署,請在
| DevOps 工程師 |
使用 Terraform 部署資源。 |
| DevOps 工程師 |
(選用) 執行其他SQL查詢。 | 範例儲存庫提供多個SQL查詢供示範使用。若要執行您自己的SQL查詢,請將它們新增至下列資料夾:
|
任務 | 描述 | 所需的技能 |
---|---|---|
監控SQL陳述式的部署。 | 您可以監控 Amazon Redshift 叢集的SQL執行結果。如需顯示失敗和成功SQL執行的輸出範例,請參閱其他資訊 中的範例SQL陳述式。 | DBA, DevOps engineer |
清除資源。 | 若要刪除 Terraform 部署的所有資源,請執行下列命令。
| DevOps 工程師 |
任務 | 描述 | 所需的技能 |
---|---|---|
驗證 Amazon Redshift 叢集中的資料。 |
| DBA, AWS DevOps |
相關資源
AWS 文件
其他資源
命令:套用
(Terraform 文件)
其他資訊
解決方案演練
若要使用 解決方案,您必須以特定方式組織 Amazon Redshift SQL查詢。所有SQL查詢都必須存放在具有.sql
副檔名的檔案中。
在此模式提供的程式碼範例中,SQL查詢會以下列資料夾結構進行組織。您可以修改程式碼 (sql-queries.tf
和 sql-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 會以下列順序執行查詢:
/bootstrap
/nonrepeatable
/repeatable
/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_dataterraform_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_bootstrap
、sql_path_repeatable
、 sql_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]