我在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を用いて実現した