我在Terraform中尝试用于管理Snowflake配置

这是关于Snowflake日历|Advent Calendar 2022 – Qiita第4天的文章。

这是什么?

    • Snowflakeの構成管理をTerraformでやってみたので、その意図や感想等を書き連ねる記事

主にディレクトリ構成について語る記事に仕上がった気がする

前提条件 (Qian ti tiao jian)

雪花是什么?

 

    • みんな大好きクラウドサービスとしてのデータプラットフォーム

Redshift や BigQuery が類似製品として挙げられるけど、データウェアハウス用途だけではないので似て非なるもの(と個人的に思っている)

今回Snowflakeで構築するシステムは下記のETLのようなものを想定

Aシステム(AWS S3)からデータを取得して格納する
格納したデータを良さげに変換してBシステム(AWS S3)に出力する
バッチジョブもSnowflakeのTASK機能で実現し、Snowflakeで完結するシステムにする

Terraform是什么?

 

    • みんな大好きIaC

AWS構成管理やGCP構成管理に用いられるのはよく目にするけど、Snowflakeの構成管理にどれくらい使われているのかは正直不明

Terraformのproviderは Snowflake-Labs/snowflakeのv0.40.0 を利用する

2022/12/04時点でGAされてないためご利用は計画的に

Terraform目录结构

首先,让我们介绍一下Terraform的目录结构。

.
├ terraform/
  ├ .aws/
  ├ src/
    ├ .terraform
    ├ .terraform.lock.hcl
    ├ external_function.tf
    ├ main.tf
    ├ procedure.tf
    ├ schema.tf
    ├ stage.tf
    ├ table.tf
    ├ task.tf
    ├ terraform.tfvars
    ├ user_function.tf
    ├ variables.tf

※只写部分内容。

※由于将后端设置为S3,所以存在 .aws。

重点1:将管理的对象仅限制在数据库下的对象。

正如文件名所示,我们选择使用Terraform来管理数据库中的模式、表和存储过程等对象,并将其按对象类型分割成不同的文件。

意图是将管理对象集中在数据库对象下。

首先,在操作Snowflake时,需要在main.tf文件中指定Snowflake操作的角色。

此外,由于开发人员不想使用 SYSADMIN 角色来操作目标数据库下的对象,因此希望针对每个数据库切换到对应数据库的 Admin 角色。
开发人员基本上只需要目标数据库的 Admin 权限就足以进行系统构建,同时也希望减少开发人员触及到与其无关的数据库的危险性,以及误操作的风险,如对数据库或更高级别的对象(如用户或外部存储集成等)进行了不正确的更改。因此,为每个数据库创建了 Admin 角色。

鉴于上述原因,选择在Terraform中使用目标DB的管理员角色,并且通过此角色,可以管理的仅限于DB下的对象。

顺便说一句,由于数据库下的对象具有最高的变更频率,所以仅通过 Terraform 管理这些对象已经相当不错了。
我们可以在进行变更之前通过 terraform plan 来确认差异,并且通过 Git 进行版本控制,可以享受到引入 Terraform 带来的好处。

问题1:文件太庞大

然而,上述结构存在许多问题。

第一点是文件变得庞大,特别是在添加模式时表现得明显。
例如,如果是表定义,那么所有内容都在table.tf中详细记录,所以当前情况是当添加模式时,记录量会大幅增加。
(当然,即使在未添加模式的情况下,表增加也会导致记录量增加,但是添加模式时增加会更快)

问题点2: 如何管理多个数据库

由于以上结构仅能管理一个数据库,因此存在管理多个数据库的问题。
基本上,我们打算放弃原先的方针,而是将每个数据库分别放在不同的目录下进行管理。
(并且考虑到既然要将每个数据库分开存放的话,是否存在其他目录结构方案也是我们未来设想中的内容,将在后文中提到。)

Terraform目录结构(改进建议)

由于前面提到的问题,以及我们希望将数据库本身也纳入Terraform的管理,因此我们考虑将来改变以下的目录结构可能会更好。(由于以下内容还未经过尝试,所以可能无法按照预期进行。)

根据生命周期的要求,将目录结构和数据库都包括在Terraform的管理范围内。

我想提出一个改善方案,根据生命周期将目录分开(即将tfstate文件分开)。

.
├ terraform/
  ├ src/
    ├ main.tf # システムロール `SYSADMIN` を指定
    ├ db.tf
    ├ main_db/
      ├ main.tf # カスタムロール `MAIN_DB_ADMIN` を指定
      ├ schema.tf
      ├ public_schema/
        ├ main.tf # カスタムロール `MAIN_DB_ADMIN` を指定(スキーマ毎にロール切るのも一案?)
        ├ external_function.tf
        ├ procedure.tf
        ├ stage.tf
        ├ table.tf
        ├ task.tf
        ├ user_function.tf
      ├ mobile_app_schema/
        ├ main.tf # カスタムロール `MAIN_DB_ADMIN` を指定
        ├ table.tf
      ├ web_app_schema/
        ├ main.tf # カスタムロール `MAIN_DB_ADMIN` を指定
        ├ table.tf
    ├ sub_db/
      ├ main.tf # カスタムロール `SUB_DB_ADMIN` を指定
      ├ schema.tf
      ├ public_schema/
        ├ main.tf  # カスタムロール `SUB_DB_ADMIN` を指定
        ├ table.tf

假设省略的部分是每个 main.tf 文件与 variables.tf 和 terraform.tfvars 文件相配套设置。

通过上述方式,可以不仅管理数据库下的对象,还可以管理数据库本身,从而在一定程度上减少单个文件的膨胀。

进一步扩大Terraform的管理范围

如果想要将用户、角色和权限授予,以及存储和API集成都放在Terraform的管辖之下,那么目录结构可能会变得不同。下面是一个例子:

.
├ terraform/
  ├ sysadmin/
    ├ main.tf # システムロール `SYSADMIN` を指定
    ├ db.tf
    ├ main_db/
  ├ accountadmin/
    ├ main.tf # システムロール `ACCOUNTADMIN` を指定
    ├ api_integration.tf
    ├ storage_integration.tf
  ├ useradmin/
    ├ main.tf # システムロール `USERADMIN` を指定
    ├ user.tf
    ├ role.tf
  ├ securityadmin/
    ├ main.tf # システムロール `SECURITYADMIN` を指定
    ├ role_grant.tf

此外,由于这个提案完全没有经过充分的筹划,所以最好不要参考它,而且还存在一些怀疑是否应该将其置于Terraform管理之下的疑虑……

在创建API集成和存储集成时,我记得不仅需要在Snowflake上进行操作,还需要在AWS(或GCP或Azure)上进行操作,并且需要在Snowflake和AWS之间交互进行操作才能创建。因此,我无法确定是否可以有效地使用Terraform进行管理。
(如果只是导入已创建的内容,似乎可以做到)

最后

目前管理对象和目录结构还不清楚,是否适合使用Terraform也还没有判断,需要考虑的因素很多。不过,个人认为使用Terraform可以减轻Snowflake配置管理的负担,所以将其作为一个选择是很好的。(尽管Snowflake的提供者还没有正式发布)

我还有很多其他想要谈论的内容(※1),但这次就先在这里结束吧。


※1: 以下是想要讨论的各种内容。

    • 開発環境・検証環境・本番環境をどのように管理したか

今回は諸事情により、1つのSnowflakeアカウント内にDBを切り分ける形で開発・検証・本番環境を設けた
Terraformのworkspace機能を使うことで上記3環境の管理コストを減らせた

ちなみにworkspace機能はこのような環境管理用途で用意されたものではないが、今回のケースにおいては便利だったので用いた

AWS S3をbackendに設定するにあたり、Terraform実行時のAWSのMFA認証を如何にして突破したか

aws-vaultを用いて実現した

广告
将在 10 秒后关闭
bannerAds